/* * Copyright 2015 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrPipeline_DEFINED #define GrPipeline_DEFINED #include "GrColor.h" #include "GrFragmentProcessor.h" #include "GrNonAtomicRef.h" #include "GrPendingProgramElement.h" #include "GrProcessorSet.h" #include "GrProgramDesc.h" #include "GrRect.h" #include "GrRenderTargetProxy.h" #include "GrScissorState.h" #include "GrUserStencilSettings.h" #include "GrWindowRectsState.h" #include "SkMatrix.h" #include "SkRefCnt.h" #include "effects/GrCoverageSetOpXP.h" #include "effects/GrDisableColorXP.h" #include "effects/GrPorterDuffXferProcessor.h" #include "effects/GrSimpleTextureEffect.h" class GrAppliedClip; class GrDeviceCoordTexture; class GrOp; class GrRenderTargetContext; /** * This immutable object contains information needed to set build a shader program and set API * state for a draw. It is used along with a GrPrimitiveProcessor and a source of geometric * data (GrMesh or GrPath) to draw. */ class GrPipeline { public: /////////////////////////////////////////////////////////////////////////// /// @name Creation enum Flags { /** * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target, * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by * the 3D API. */ kHWAntialias_Flag = 0x1, /** * Modifies the vertex shader so that vertices will be positioned at pixel centers. */ kSnapVerticesToPixelCenters_Flag = 0x2, /** Disables conversion to sRGB from linear when writing to a sRGB destination. */ kDisableOutputConversionToSRGB_Flag = 0x4, /** Allows conversion from sRGB to linear when reading from processor's sRGB texture. */ kAllowSRGBInputs_Flag = 0x8, }; static uint32_t SRGBFlagsFromPaint(const GrPaint& paint) { uint32_t flags = 0; if (paint.getAllowSRGBInputs()) { flags |= kAllowSRGBInputs_Flag; } if (paint.getDisableOutputConversionToSRGB()) { flags |= kDisableOutputConversionToSRGB_Flag; } return flags; } enum ScissorState : bool { kEnabled = true, kDisabled = false }; struct InitArgs { uint32_t fFlags = 0; const GrUserStencilSettings* fUserStencil = &GrUserStencilSettings::kUnused; GrRenderTargetProxy* fProxy = nullptr; const GrCaps* fCaps = nullptr; GrResourceProvider* fResourceProvider = nullptr; GrXferProcessor::DstProxy fDstProxy; }; /** * Graphics state that can change dynamically without creating a new pipeline. **/ struct DynamicState { // Overrides the scissor rectangle (if scissor is enabled in the pipeline). // TODO: eventually this should be the only way to specify a scissor rectangle, as is the // case with the simple constructor. SkIRect fScissorRect; }; /** * Creates a simple pipeline with default settings and no processors. The provided blend mode * must be "Porter Duff" (<= kLastCoeffMode). If using ScissorState::kEnabled, the caller must * specify a scissor rectangle through the DynamicState struct. **/ GrPipeline(GrRenderTargetProxy*, ScissorState, SkBlendMode); GrPipeline(const InitArgs&, GrProcessorSet&&, GrAppliedClip&&); GrPipeline(const GrPipeline&) = delete; GrPipeline& operator=(const GrPipeline&) = delete; /// @} /////////////////////////////////////////////////////////////////////////// /// @name GrFragmentProcessors // Make the renderTargetContext's GrOpList be dependent on any GrOpLists in this pipeline void addDependenciesTo(GrOpList* recipient, const GrCaps&) const; int numColorFragmentProcessors() const { return fNumColorProcessors; } int numCoverageFragmentProcessors() const { return fFragmentProcessors.count() - fNumColorProcessors; } int numFragmentProcessors() const { return fFragmentProcessors.count(); } const GrXferProcessor& getXferProcessor() const { if (fXferProcessor) { return *fXferProcessor.get(); } else { // A null xp member means the common src-over case. GrXferProcessor's ref'ing // mechanism is not thread safe so we do not hold a ref on this global. return GrPorterDuffXPFactory::SimpleSrcOverXP(); } } /** * If the GrXferProcessor uses a texture to access the dst color, then this returns that * texture and the offset to the dst contents within that texture. */ GrTextureProxy* dstTextureProxy(SkIPoint* offset = nullptr) const { if (offset) { *offset = fDstTextureOffset; } return fDstTextureProxy.get(); } GrTexture* peekDstTexture(SkIPoint* offset = nullptr) const { if (GrTextureProxy* dstProxy = this->dstTextureProxy(offset)) { return dstProxy->priv().peekTexture(); } return nullptr; } const GrFragmentProcessor& getColorFragmentProcessor(int idx) const { SkASSERT(idx < this->numColorFragmentProcessors()); return *fFragmentProcessors[idx].get(); } const GrFragmentProcessor& getCoverageFragmentProcessor(int idx) const { SkASSERT(idx < this->numCoverageFragmentProcessors()); return *fFragmentProcessors[fNumColorProcessors + idx].get(); } const GrFragmentProcessor& getFragmentProcessor(int idx) const { return *fFragmentProcessors[idx].get(); } /// @} /** * Retrieves the currently set render-target. * * @return The currently set render target. */ GrRenderTargetProxy* proxy() const { return fProxy.get(); } GrRenderTarget* renderTarget() const { return fProxy.get()->priv().peekRenderTarget(); } const GrUserStencilSettings* getUserStencil() const { return fUserStencilSettings; } const GrScissorState& getScissorState() const { return fScissorState; } const GrWindowRectsState& getWindowRectsState() const { return fWindowRectsState; } bool isHWAntialiasState() const { return SkToBool(fFlags & kHWAntialias_Flag); } bool snapVerticesToPixelCenters() const { return SkToBool(fFlags & kSnapVerticesToPixelCenters_Flag); } bool getDisableOutputConversionToSRGB() const { return SkToBool(fFlags & kDisableOutputConversionToSRGB_Flag); } bool getAllowSRGBInputs() const { return SkToBool(fFlags & kAllowSRGBInputs_Flag); } bool hasStencilClip() const { return SkToBool(fFlags & kHasStencilClip_Flag); } bool isStencilEnabled() const { return SkToBool(fFlags & kStencilEnabled_Flag); } bool isBad() const { return SkToBool(fFlags & kIsBad_Flag); } GrXferBarrierType xferBarrierType(const GrCaps& caps) const; static SkString DumpFlags(uint32_t flags) { if (flags) { SkString result; if (flags & GrPipeline::kSnapVerticesToPixelCenters_Flag) { result.append("Snap vertices to pixel center.\n"); } if (flags & GrPipeline::kHWAntialias_Flag) { result.append("HW Antialiasing enabled.\n"); } if (flags & GrPipeline::kDisableOutputConversionToSRGB_Flag) { result.append("Disable output conversion to sRGB.\n"); } if (flags & GrPipeline::kAllowSRGBInputs_Flag) { result.append("Allow sRGB Inputs.\n"); } return result; } return SkString("No pipeline flags\n"); } private: void markAsBad() { fFlags |= kIsBad_Flag; } /** This is a continuation of the public "Flags" enum. */ enum PrivateFlags { kHasStencilClip_Flag = 0x10, kStencilEnabled_Flag = 0x20, kIsBad_Flag = 0x40, }; using RenderTargetProxy = GrPendingIOResource<GrRenderTargetProxy, kWrite_GrIOType>; using DstTextureProxy = GrPendingIOResource<GrTextureProxy, kRead_GrIOType>; using FragmentProcessorArray = SkAutoSTArray<8, std::unique_ptr<const GrFragmentProcessor>>; DstTextureProxy fDstTextureProxy; SkIPoint fDstTextureOffset; // MDB TODO: do we still need the destination proxy here? RenderTargetProxy fProxy; GrScissorState fScissorState; GrWindowRectsState fWindowRectsState; const GrUserStencilSettings* fUserStencilSettings; uint16_t fFlags; sk_sp<const GrXferProcessor> fXferProcessor; FragmentProcessorArray fFragmentProcessors; // This value is also the index in fFragmentProcessors where coverage processors begin. int fNumColorProcessors; typedef SkRefCnt INHERITED; }; #endif