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 GrPipeline_DEFINED 9 #define GrPipeline_DEFINED 10 11 #include "GrColor.h" 12 #include "GrFragmentProcessor.h" 13 #include "GrNonAtomicRef.h" 14 #include "GrPendingProgramElement.h" 15 #include "GrProcessorSet.h" 16 #include "GrProgramDesc.h" 17 #include "GrRect.h" 18 #include "GrRenderTarget.h" 19 #include "GrScissorState.h" 20 #include "GrUserStencilSettings.h" 21 #include "GrWindowRectsState.h" 22 #include "SkMatrix.h" 23 #include "SkRefCnt.h" 24 #include "effects/GrCoverageSetOpXP.h" 25 #include "effects/GrDisableColorXP.h" 26 #include "effects/GrPorterDuffXferProcessor.h" 27 #include "effects/GrSimpleTextureEffect.h" 28 29 class GrAppliedClip; 30 class GrDeviceCoordTexture; 31 class GrOp; 32 class GrRenderTargetContext; 33 34 /** 35 * This immutable object contains information needed to set build a shader program and set API 36 * state for a draw. It is used along with a GrPrimitiveProcessor and a source of geometric 37 * data (GrMesh or GrPath) to draw. 38 */ 39 class GrPipeline : public GrNonAtomicRef<GrPipeline> { 40 public: 41 /////////////////////////////////////////////////////////////////////////// 42 /// @name Creation 43 44 enum Flags { 45 /** 46 * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target, 47 * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by 48 * the 3D API. 49 */ 50 kHWAntialias_Flag = 0x1, 51 /** 52 * Modifies the vertex shader so that vertices will be positioned at pixel centers. 53 */ 54 kSnapVerticesToPixelCenters_Flag = 0x2, 55 /** Disables conversion to sRGB from linear when writing to a sRGB destination. */ 56 kDisableOutputConversionToSRGB_Flag = 0x4, 57 /** Allows conversion from sRGB to linear when reading from processor's sRGB texture. */ 58 kAllowSRGBInputs_Flag = 0x8, 59 }; 60 SRGBFlagsFromPaint(const GrPaint & paint)61 static uint32_t SRGBFlagsFromPaint(const GrPaint& paint) { 62 uint32_t flags = 0; 63 if (paint.getAllowSRGBInputs()) { 64 flags |= kAllowSRGBInputs_Flag; 65 } 66 if (paint.getDisableOutputConversionToSRGB()) { 67 flags |= kDisableOutputConversionToSRGB_Flag; 68 } 69 return flags; 70 } 71 72 enum ScissorState : bool { 73 kEnabled = true, 74 kDisabled = false 75 }; 76 77 struct InitArgs { 78 uint32_t fFlags = 0; 79 const GrProcessorSet* fProcessors = nullptr; // Must be finalized 80 const GrUserStencilSettings* fUserStencil = &GrUserStencilSettings::kUnused; 81 const GrAppliedClip* fAppliedClip = nullptr; 82 GrRenderTarget* fRenderTarget = nullptr; 83 const GrCaps* fCaps = nullptr; 84 GrResourceProvider* fResourceProvider = nullptr; 85 GrXferProcessor::DstProxy fDstProxy; 86 }; 87 88 /** 89 * Graphics state that can change dynamically without creating a new pipeline. 90 **/ 91 struct DynamicState { 92 // Overrides the scissor rectangle (if scissor is enabled in the pipeline). 93 // TODO: eventually this should be the only way to specify a scissor rectangle, as is the 94 // case with the simple constructor. 95 SkIRect fScissorRect; 96 }; 97 98 /** 99 * A Default constructed pipeline is unusable until init() is called. 100 **/ 101 GrPipeline() = default; 102 103 /** 104 * Creates a simple pipeline with default settings and no processors. The provided blend mode 105 * must be "Porter Duff" (<= kLastCoeffMode). If using ScissorState::kEnabled, the caller must 106 * specify a scissor rectangle through the DynamicState struct. 107 **/ 108 GrPipeline(GrRenderTarget*, ScissorState, SkBlendMode); 109 GrPipeline(const InitArgs & args)110 GrPipeline(const InitArgs& args) { this->init(args); } 111 112 /** (Re)initializes a pipeline. After initialization the pipeline can be used. */ 113 void init(const InitArgs&); 114 115 /** True if the pipeline has been initialized. */ isInitialized()116 bool isInitialized() const { return SkToBool(fRenderTarget.get()); } 117 118 /// @} 119 120 /////////////////////////////////////////////////////////////////////////// 121 /// @name Comparisons 122 123 /** 124 * Returns true if these pipelines are equivalent. Coord transforms may be applied either on 125 * the GPU or the CPU. When we apply them on the CPU then the matrices need not agree in order 126 * to combine draws. Therefore we take a param that indicates whether coord transforms should be 127 * compared." 128 */ 129 static bool AreEqual(const GrPipeline& a, const GrPipeline& b); 130 131 /** 132 * Allows a GrOp subclass to determine whether two GrOp instances can combine. This is a 133 * stricter test than isEqual because it also considers blend barriers when the two ops' 134 * bounds overlap 135 */ CanCombine(const GrPipeline & a,const SkRect & aBounds,const GrPipeline & b,const SkRect & bBounds,const GrCaps & caps)136 static bool CanCombine(const GrPipeline& a, const SkRect& aBounds, 137 const GrPipeline& b, const SkRect& bBounds, 138 const GrCaps& caps) { 139 if (!AreEqual(a, b)) { 140 return false; 141 } 142 if (a.xferBarrierType(caps)) { 143 return !GrRectsTouchOrOverlap(aBounds, bBounds); 144 } 145 return true; 146 } 147 148 /// @} 149 150 /////////////////////////////////////////////////////////////////////////// 151 /// @name GrFragmentProcessors 152 153 // Make the renderTargetContext's GrOpList be dependent on any GrOpLists in this pipeline 154 void addDependenciesTo(GrOpList* recipient, const GrCaps&) const; 155 numColorFragmentProcessors()156 int numColorFragmentProcessors() const { return fNumColorProcessors; } numCoverageFragmentProcessors()157 int numCoverageFragmentProcessors() const { 158 return fFragmentProcessors.count() - fNumColorProcessors; 159 } numFragmentProcessors()160 int numFragmentProcessors() const { return fFragmentProcessors.count(); } 161 getXferProcessor()162 const GrXferProcessor& getXferProcessor() const { 163 if (fXferProcessor) { 164 return *fXferProcessor.get(); 165 } else { 166 // A null xp member means the common src-over case. GrXferProcessor's ref'ing 167 // mechanism is not thread safe so we do not hold a ref on this global. 168 return GrPorterDuffXPFactory::SimpleSrcOverXP(); 169 } 170 } 171 172 /** 173 * If the GrXferProcessor uses a texture to access the dst color, then this returns that 174 * texture and the offset to the dst contents within that texture. 175 */ 176 GrTextureProxy* dstTextureProxy(SkIPoint* offset = nullptr) const { 177 if (offset) { 178 *offset = fDstTextureOffset; 179 } 180 return fDstTextureProxy.get(); 181 } 182 183 GrTexture* peekDstTexture(SkIPoint* offset = nullptr) const { 184 if (GrTextureProxy* dstProxy = this->dstTextureProxy(offset)) { 185 return dstProxy->priv().peekTexture(); 186 } 187 188 return nullptr; 189 } 190 getColorFragmentProcessor(int idx)191 const GrFragmentProcessor& getColorFragmentProcessor(int idx) const { 192 SkASSERT(idx < this->numColorFragmentProcessors()); 193 return *fFragmentProcessors[idx].get(); 194 } 195 getCoverageFragmentProcessor(int idx)196 const GrFragmentProcessor& getCoverageFragmentProcessor(int idx) const { 197 SkASSERT(idx < this->numCoverageFragmentProcessors()); 198 return *fFragmentProcessors[fNumColorProcessors + idx].get(); 199 } 200 getFragmentProcessor(int idx)201 const GrFragmentProcessor& getFragmentProcessor(int idx) const { 202 return *fFragmentProcessors[idx].get(); 203 } 204 205 /// @} 206 207 /** 208 * Retrieves the currently set render-target. 209 * 210 * @return The currently set render target. 211 */ getRenderTarget()212 GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); } 213 getUserStencil()214 const GrUserStencilSettings* getUserStencil() const { return fUserStencilSettings; } 215 getScissorState()216 const GrScissorState& getScissorState() const { return fScissorState; } 217 getWindowRectsState()218 const GrWindowRectsState& getWindowRectsState() const { return fWindowRectsState; } 219 isHWAntialiasState()220 bool isHWAntialiasState() const { return SkToBool(fFlags & kHWAntialias_Flag); } snapVerticesToPixelCenters()221 bool snapVerticesToPixelCenters() const { 222 return SkToBool(fFlags & kSnapVerticesToPixelCenters_Flag); 223 } getDisableOutputConversionToSRGB()224 bool getDisableOutputConversionToSRGB() const { 225 return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag); 226 } getAllowSRGBInputs()227 bool getAllowSRGBInputs() const { 228 return SkToBool(fFlags & kAllowSRGBInputs_Flag); 229 } hasStencilClip()230 bool hasStencilClip() const { 231 return SkToBool(fFlags & kHasStencilClip_Flag); 232 } isStencilEnabled()233 bool isStencilEnabled() const { 234 return SkToBool(fFlags & kStencilEnabled_Flag); 235 } isBad()236 bool isBad() const { return SkToBool(fFlags & kIsBad_Flag); } 237 238 GrXferBarrierType xferBarrierType(const GrCaps& caps) const; 239 DumpFlags(uint32_t flags)240 static SkString DumpFlags(uint32_t flags) { 241 if (flags) { 242 SkString result; 243 if (flags & GrPipeline::kSnapVerticesToPixelCenters_Flag) { 244 result.append("Snap vertices to pixel center.\n"); 245 } 246 if (flags & GrPipeline::kHWAntialias_Flag) { 247 result.append("HW Antialiasing enabled.\n"); 248 } 249 if (flags & GrPipeline::kDisableOutputConversionToSRGB_Flag) { 250 result.append("Disable output conversion to sRGB.\n"); 251 } 252 if (flags & GrPipeline::kAllowSRGBInputs_Flag) { 253 result.append("Allow sRGB Inputs.\n"); 254 } 255 return result; 256 } 257 return SkString("No pipeline flags\n"); 258 } 259 260 private: markAsBad()261 void markAsBad() { fFlags |= kIsBad_Flag; } 262 263 /** This is a continuation of the public "Flags" enum. */ 264 enum PrivateFlags { 265 kHasStencilClip_Flag = 0x10, 266 kStencilEnabled_Flag = 0x20, 267 kIsBad_Flag = 0x40, 268 }; 269 270 using RenderTarget = GrPendingIOResource<GrRenderTarget, kWrite_GrIOType>; 271 using DstTextureProxy = GrPendingIOResource<GrTextureProxy, kRead_GrIOType>; 272 using PendingFragmentProcessor = GrPendingProgramElement<const GrFragmentProcessor>; 273 using FragmentProcessorArray = SkAutoSTArray<8, PendingFragmentProcessor>; 274 275 DstTextureProxy fDstTextureProxy; 276 SkIPoint fDstTextureOffset; 277 RenderTarget fRenderTarget; 278 GrScissorState fScissorState; 279 GrWindowRectsState fWindowRectsState; 280 const GrUserStencilSettings* fUserStencilSettings; 281 uint16_t fFlags; 282 sk_sp<const GrXferProcessor> fXferProcessor; 283 FragmentProcessorArray fFragmentProcessors; 284 285 // This value is also the index in fFragmentProcessors where coverage processors begin. 286 int fNumColorProcessors; 287 288 typedef SkRefCnt INHERITED; 289 }; 290 291 #endif 292