Home | History | Annotate | Download | only in gpu
      1 
      2 /*
      3  * Copyright 2010 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 
     11 #ifndef GrProcessorStage_DEFINED
     12 #define GrProcessorStage_DEFINED
     13 
     14 #include "GrBackendProcessorFactory.h"
     15 #include "GrCoordTransform.h"
     16 #include "GrProcessor.h"
     17 #include "GrGeometryProcessor.h"
     18 #include "GrProgramElementRef.h"
     19 #include "SkMatrix.h"
     20 #include "SkShader.h"
     21 
     22 // TODO: Make two variations on this class: One for GrDrawState that only owns regular refs
     23 // and supports compatibility checks and changing local coords. The second is for GrOptDrawState,
     24 // is immutable, and only owns pending execution refs. This requries removing the common base
     25 // class from GrDrawState and GrOptDrawState called GrRODrawState and converting to GrOptDrawState
     26 // when draws are enqueued in the GrInOrderDrawBuffer.
     27 class GrProcessorStage {
     28 public:
     29     explicit GrProcessorStage(const GrProcessor* proc)
     30     : fProc(SkRef(proc)) {
     31         fCoordChangeMatrixSet = false;
     32     }
     33 
     34     GrProcessorStage(const GrProcessorStage& other) {
     35         fCoordChangeMatrixSet = other.fCoordChangeMatrixSet;
     36         if (other.fCoordChangeMatrixSet) {
     37             fCoordChangeMatrix = other.fCoordChangeMatrix;
     38         }
     39         fProc.initAndRef(other.fProc);
     40     }
     41 
     42     static bool AreCompatible(const GrProcessorStage& a, const GrProcessorStage& b,
     43                               bool usingExplicitLocalCoords) {
     44         SkASSERT(a.fProc.get());
     45         SkASSERT(b.fProc.get());
     46 
     47         if (!a.getProcessor()->isEqual(*b.getProcessor())) {
     48             return false;
     49         }
     50 
     51         // We always track the coord change matrix, but it has no effect when explicit local coords
     52         // are used.
     53         if (usingExplicitLocalCoords) {
     54             return true;
     55         }
     56 
     57         if (a.fCoordChangeMatrixSet != b.fCoordChangeMatrixSet) {
     58             return false;
     59         }
     60 
     61         if (!a.fCoordChangeMatrixSet) {
     62             return true;
     63         }
     64 
     65         return a.fCoordChangeMatrix == b.fCoordChangeMatrix;
     66     }
     67 
     68     /**
     69      * This is called when the coordinate system in which the geometry is specified will change.
     70      *
     71      * @param matrix    The transformation from the old coord system in which geometry is specified
     72      *                  to the new one from which it will actually be drawn.
     73      */
     74     void localCoordChange(const SkMatrix& matrix) {
     75         if (fCoordChangeMatrixSet) {
     76             fCoordChangeMatrix.preConcat(matrix);
     77         } else {
     78             fCoordChangeMatrixSet = true;
     79             fCoordChangeMatrix = matrix;
     80         }
     81     }
     82 
     83     class SavedCoordChange {
     84     public:
     85         SkDEBUGCODE(SavedCoordChange() : fEffectUniqueID(SK_InvalidUniqueID) {})
     86     private:
     87         bool fCoordChangeMatrixSet;
     88         SkMatrix fCoordChangeMatrix;
     89         SkDEBUGCODE(mutable uint32_t fEffectUniqueID;)
     90 
     91         friend class GrProcessorStage;
     92     };
     93 
     94     /**
     95      * This gets the current coordinate system change. It is the accumulation of
     96      * localCoordChange calls since the effect was installed. It is used when then caller
     97      * wants to temporarily change the source geometry coord system, draw something, and then
     98      * restore the previous coord system (e.g. temporarily draw in device coords).
     99      */
    100     void saveCoordChange(SavedCoordChange* savedCoordChange) const {
    101         savedCoordChange->fCoordChangeMatrixSet = fCoordChangeMatrixSet;
    102         if (fCoordChangeMatrixSet) {
    103             savedCoordChange->fCoordChangeMatrix = fCoordChangeMatrix;
    104         }
    105         SkASSERT(SK_InvalidUniqueID == savedCoordChange->fEffectUniqueID);
    106         SkDEBUGCODE(savedCoordChange->fEffectUniqueID = fProc->getUniqueID();)
    107     }
    108 
    109     /**
    110      * This balances the saveCoordChange call.
    111      */
    112     void restoreCoordChange(const SavedCoordChange& savedCoordChange) {
    113         fCoordChangeMatrixSet = savedCoordChange.fCoordChangeMatrixSet;
    114         if (fCoordChangeMatrixSet) {
    115             fCoordChangeMatrix = savedCoordChange.fCoordChangeMatrix;
    116         }
    117         SkASSERT(savedCoordChange.fEffectUniqueID == fProc->getUniqueID());
    118         SkDEBUGCODE(savedCoordChange.fEffectUniqueID = SK_InvalidUniqueID);
    119     }
    120 
    121     /**
    122      * Gets the matrix representing all changes of coordinate system since the GrProcessor was
    123      * installed in the stage.
    124      */
    125     const SkMatrix& getCoordChangeMatrix() const {
    126         if (fCoordChangeMatrixSet) {
    127             return fCoordChangeMatrix;
    128         } else {
    129             return SkMatrix::I();
    130         }
    131     }
    132 
    133     bool isPerspectiveCoordTransform(int matrixIndex, bool useExplicitLocalCoords) const {
    134         const GrCoordTransform& coordTransform = this->getProcessor()->coordTransform(matrixIndex);
    135         SkMatrix::TypeMask type0 = coordTransform.getMatrix().getType();
    136         SkMatrix::TypeMask type1 = SkMatrix::kIdentity_Mask;
    137         if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
    138           type1 = useExplicitLocalCoords ?
    139                   SkMatrix::kIdentity_Mask : this->getCoordChangeMatrix().getType();
    140         }
    141 
    142         int combinedTypes = type0 | type1;
    143         if (SkMatrix::kPerspective_Mask & combinedTypes) {
    144           return true;
    145         } else {
    146           return false;
    147         }
    148     }
    149 
    150     const GrProcessor* getProcessor() const { return fProc.get(); }
    151 
    152     void convertToPendingExec() { fProc.convertToPendingExec(); }
    153 
    154 private:
    155     bool                                   fCoordChangeMatrixSet;
    156     SkMatrix                               fCoordChangeMatrix;
    157     GrProgramElementRef<const GrProcessor> fProc;
    158 };
    159 
    160 class GrFragmentStage : public GrProcessorStage {
    161 public:
    162     GrFragmentStage(const GrFragmentProcessor* fp) : GrProcessorStage(fp) {}
    163 
    164     const GrFragmentProcessor* getFragmentProcessor() const {
    165         return static_cast<const GrFragmentProcessor*>(this->getProcessor());
    166     }
    167 };
    168 
    169 class GrGeometryStage : public GrProcessorStage {
    170 public:
    171     GrGeometryStage(const GrGeometryProcessor* gp) : GrProcessorStage(gp) {}
    172 
    173     const GrGeometryProcessor* getGeometryProcessor() const {
    174         return static_cast<const GrGeometryProcessor*>(this->getProcessor());
    175     }
    176 };
    177 
    178 #endif
    179