LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/ops - GrOp.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 63 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 46 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2015 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #ifndef GrOp_DEFINED
       9             : #define GrOp_DEFINED
      10             : 
      11             : #include "../private/SkAtomics.h"
      12             : #include "GrGpuResource.h"
      13             : #include "GrNonAtomicRef.h"
      14             : #include "GrXferProcessor.h"
      15             : #include "SkMatrix.h"
      16             : #include "SkRect.h"
      17             : #include "SkString.h"
      18             : 
      19             : #include <new>
      20             : 
      21             : class GrCaps;
      22             : class GrGpuCommandBuffer;
      23             : class GrOpFlushState;
      24             : 
      25             : /**
      26             :  * GrOp is the base class for all Ganesh deferred GPU operations. To facilitate reordering and to
      27             :  * minimize draw calls, Ganesh does not generate geometry inline with draw calls. Instead, it
      28             :  * captures the arguments to the draw and then generates the geometry when flushing. This gives GrOp
      29             :  * subclasses complete freedom to decide how/when to combine in order to produce fewer draw calls
      30             :  * and minimize state changes.
      31             :  *
      32             :  * Ops of the same subclass may be merged using combineIfPossible. When two ops merge, one
      33             :  * takes on the union of the data and the other is left empty. The merged op becomes responsible
      34             :  * for drawing the data from both the original ops.
      35             :  *
      36             :  * If there are any possible optimizations which might require knowing more about the full state of
      37             :  * the draw, e.g. whether or not the GrOp is allowed to tweak alpha for coverage, then this
      38             :  * information will be communicated to the GrOp prior to geometry generation.
      39             :  *
      40             :  * The bounds of the op must contain all the vertices in device space *irrespective* of the clip.
      41             :  * The bounds are used in determining which clip elements must be applied and thus the bounds cannot
      42             :  * in turn depend upon the clip.
      43             :  */
      44             : #define GR_OP_SPEW 0
      45             : #if GR_OP_SPEW
      46             :     #define GrOP_SPEW(code) code
      47             :     #define GrOP_INFO(...) SkDebugf(__VA_ARGS__)
      48             : #else
      49             :     #define GrOP_SPEW(code)
      50             :     #define GrOP_INFO(...)
      51             : #endif
      52             : 
      53             : // A helper macro to generate a class static id
      54             : #define DEFINE_OP_CLASS_ID \
      55             :     static uint32_t ClassID() { \
      56             :         static uint32_t kClassID = GenOpClassID(); \
      57             :         return kClassID; \
      58             :     }
      59             : 
      60             : class GrOp : private SkNoncopyable {
      61             : public:
      62             :     GrOp(uint32_t classID);
      63             :     virtual ~GrOp();
      64             : 
      65             :     virtual const char* name() const = 0;
      66             : 
      67           0 :     bool combineIfPossible(GrOp* that, const GrCaps& caps) {
      68           0 :         if (this->classID() != that->classID()) {
      69           0 :             return false;
      70             :         }
      71             : 
      72           0 :         return this->onCombineIfPossible(that, caps);
      73             :     }
      74             : 
      75           0 :     const SkRect& bounds() const {
      76           0 :         SkASSERT(kUninitialized_BoundsFlag != fBoundsFlags);
      77           0 :         return fBounds;
      78             :     }
      79             : 
      80           0 :     void setClippedBounds(const SkRect& clippedBounds) {
      81           0 :         fBounds = clippedBounds;
      82             :         // The clipped bounds already incorporate any effect of the bounds flags.
      83           0 :         fBoundsFlags = 0;
      84           0 :     }
      85             : 
      86           0 :     bool hasAABloat() const {
      87           0 :         SkASSERT(fBoundsFlags != kUninitialized_BoundsFlag);
      88           0 :         return SkToBool(fBoundsFlags & kAABloat_BoundsFlag);
      89             :     }
      90             : 
      91           0 :     bool hasZeroArea() const {
      92           0 :         SkASSERT(fBoundsFlags != kUninitialized_BoundsFlag);
      93           0 :         return SkToBool(fBoundsFlags & kZeroArea_BoundsFlag);
      94             :     }
      95             : 
      96             :     void* operator new(size_t size);
      97             :     void operator delete(void* target);
      98             : 
      99             :     void* operator new(size_t size, void* placement) {
     100             :         return ::operator new(size, placement);
     101             :     }
     102             :     void operator delete(void* target, void* placement) {
     103             :         ::operator delete(target, placement);
     104             :     }
     105             : 
     106             :     /**
     107             :      * Helper for safely down-casting to a GrOp subclass
     108             :      */
     109             :     template <typename T> const T& cast() const {
     110             :         SkASSERT(T::ClassID() == this->classID());
     111             :         return *static_cast<const T*>(this);
     112             :     }
     113             : 
     114           0 :     template <typename T> T* cast() {
     115           0 :         SkASSERT(T::ClassID() == this->classID());
     116           0 :         return static_cast<T*>(this);
     117             :     }
     118             : 
     119           0 :     uint32_t classID() const { SkASSERT(kIllegalOpID != fClassID); return fClassID; }
     120             : 
     121             :     // We lazily initialize the uniqueID because currently the only user is GrAuditTrail
     122           0 :     uint32_t uniqueID() const {
     123           0 :         if (kIllegalOpID == fUniqueID) {
     124           0 :             fUniqueID = GenOpID();
     125             :         }
     126           0 :         return fUniqueID;
     127             :     }
     128             : 
     129             :     /**
     130             :      * This is called to notify the op that it has been recorded into a GrOpList. Ops can use this
     131             :      * to begin preparations for the flush of the op list. Note that the op still may either be
     132             :      * combined into another op or have another op combined into it via combineIfPossible() after
     133             :      * this call is made.
     134             :      */
     135           0 :     virtual void wasRecorded() {}
     136             : 
     137             :     /**
     138             :      * Called prior to executing. The op should perform any resource creation or data transfers
     139             :      * necessary before execute() is called.
     140             :      */
     141           0 :     void prepare(GrOpFlushState* state) { this->onPrepare(state); }
     142             : 
     143             :     /** Issues the op's commands to GrGpu. */
     144           0 :     void execute(GrOpFlushState* state) { this->onExecute(state); }
     145             : 
     146             :     /** Used for spewing information about ops when debugging. */
     147           0 :     virtual SkString dumpInfo() const {
     148           0 :         SkString string;
     149           0 :         string.appendf("OpBounds: [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
     150           0 :                        fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom);
     151           0 :         return string;
     152             :     }
     153             : 
     154             : protected:
     155             :     /**
     156             :      * Indicates that the op will produce geometry that extends beyond its bounds for the
     157             :      * purpose of ensuring that the fragment shader runs on partially covered pixels for
     158             :      * non-MSAA antialiasing.
     159             :      */
     160             :     enum class HasAABloat {
     161             :         kYes,
     162             :         kNo
     163             :     };
     164             :     /**
     165             :      * Indicates that the geometry represented by the op has zero area (e.g. it is hairline or
     166             :      * points).
     167             :      */
     168             :     enum class IsZeroArea {
     169             :         kYes,
     170             :         kNo
     171             :     };
     172           0 :     void setBounds(const SkRect& newBounds, HasAABloat aabloat, IsZeroArea zeroArea) {
     173           0 :         fBounds = newBounds;
     174           0 :         this->setBoundsFlags(aabloat, zeroArea);
     175           0 :     }
     176           0 :     void setTransformedBounds(const SkRect& srcBounds, const SkMatrix& m,
     177             :                               HasAABloat aabloat, IsZeroArea zeroArea) {
     178           0 :         m.mapRect(&fBounds, srcBounds);
     179           0 :         this->setBoundsFlags(aabloat, zeroArea);
     180           0 :     }
     181             : 
     182           0 :     void joinBounds(const GrOp& that) {
     183           0 :         if (that.hasAABloat()) {
     184           0 :             fBoundsFlags |= kAABloat_BoundsFlag;
     185             :         }
     186           0 :         if (that.hasZeroArea()) {
     187           0 :             fBoundsFlags |= kZeroArea_BoundsFlag;
     188             :         }
     189           0 :         return fBounds.joinPossiblyEmptyRect(that.fBounds);
     190             :     }
     191             : 
     192           0 :     void replaceBounds(const GrOp& that) {
     193           0 :         fBounds = that.fBounds;
     194           0 :         fBoundsFlags = that.fBoundsFlags;
     195           0 :     }
     196             : 
     197           0 :     static uint32_t GenOpClassID() { return GenID(&gCurrOpClassID); }
     198             : 
     199             : private:
     200             :     virtual bool onCombineIfPossible(GrOp*, const GrCaps& caps) = 0;
     201             : 
     202             :     virtual void onPrepare(GrOpFlushState*) = 0;
     203             :     virtual void onExecute(GrOpFlushState*) = 0;
     204             : 
     205           0 :     static uint32_t GenID(int32_t* idCounter) {
     206             :         // The atomic inc returns the old value not the incremented value. So we add
     207             :         // 1 to the returned value.
     208           0 :         uint32_t id = static_cast<uint32_t>(sk_atomic_inc(idCounter)) + 1;
     209           0 :         if (!id) {
     210           0 :             SkFAIL("This should never wrap as it should only be called once for each GrOp "
     211             :                    "subclass.");
     212             :         }
     213           0 :         return id;
     214             :     }
     215             : 
     216           0 :     void setBoundsFlags(HasAABloat aabloat, IsZeroArea zeroArea) {
     217           0 :         fBoundsFlags = 0;
     218           0 :         fBoundsFlags |= (HasAABloat::kYes == aabloat) ? kAABloat_BoundsFlag : 0;
     219           0 :         fBoundsFlags |= (IsZeroArea ::kYes == zeroArea) ? kZeroArea_BoundsFlag : 0;
     220           0 :     }
     221             : 
     222             :     enum {
     223             :         kIllegalOpID = 0,
     224             :     };
     225             : 
     226             :     enum BoundsFlags {
     227             :         kAABloat_BoundsFlag                     = 0x1,
     228             :         kZeroArea_BoundsFlag                    = 0x2,
     229             :         SkDEBUGCODE(kUninitialized_BoundsFlag   = 0x4)
     230             :     };
     231             : 
     232             :     const uint16_t                      fClassID;
     233             :     uint16_t                            fBoundsFlags;
     234             : 
     235           0 :     static uint32_t GenOpID() { return GenID(&gCurrOpUniqueID); }
     236             :     mutable uint32_t                    fUniqueID;
     237             :     SkRect                              fBounds;
     238             : 
     239             :     static int32_t                      gCurrOpUniqueID;
     240             :     static int32_t                      gCurrOpClassID;
     241             : };
     242             : 
     243             : #endif

Generated by: LCOV version 1.13