/*
* 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 "GrPendingIOResource.h"
#include "GrProcessorSet.h"
#include "GrProgramDesc.h"
#include "GrRect.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 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,
};
struct InitArgs {
uint32_t fFlags = 0;
const GrUserStencilSettings* fUserStencil = &GrUserStencilSettings::kUnused;
const GrCaps* fCaps = nullptr;
GrResourceProvider* fResourceProvider = nullptr;
GrXferProcessor::DstProxy fDstProxy;
};
/**
* Some state can be changed between GrMeshes without changing GrPipelines. This is generally
* less expensive then using multiple pipelines. Such state is called "dynamic state". It can
* be specified in two ways:
* 1) FixedDynamicState - use this to specify state that does not vary between GrMeshes.
* 2) DynamicStateArrays - use this to specify per mesh values for dynamic state.
**/
struct FixedDynamicState {
explicit FixedDynamicState(const SkIRect& scissorRect) : fScissorRect(scissorRect) {}
FixedDynamicState() = default;
SkIRect fScissorRect = SkIRect::EmptyIRect();
// Must have GrPrimitiveProcessor::numTextureSamplers() entries. Can be null if no samplers
// or textures are passed using DynamicStateArrays.
GrTextureProxy** fPrimitiveProcessorTextures = nullptr;
};
/**
* Any non-null array overrides the FixedDynamicState on a mesh-by-mesh basis. Arrays must
* have one entry for each GrMesh.
*/
struct DynamicStateArrays {
const SkIRect* fScissorRects = nullptr;
// Must have GrPrimitiveProcessor::numTextureSamplers() * num_meshes entries.
// Can be null if no samplers or to use the same textures for all meshes via'
// FixedDynamicState.
GrTextureProxy** fPrimitiveProcessorTextures = nullptr;
};
/**
* Creates a simple pipeline with default settings and no processors. The provided blend mode
* must be "Porter Duff" (<= kLastCoeffMode). If using GrScissorTest::kEnabled, the caller must
* specify a scissor rectangle through the DynamicState struct.
**/
GrPipeline(GrScissorTest, 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->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();
}
/// @}
const GrUserStencilSettings* getUserStencil() const { return fUserStencilSettings; }
bool isScissorEnabled() const {
return SkToBool(fFlags & kScissorEnabled_Flag);
}
const GrWindowRectsState& getWindowRectsState() const { return fWindowRectsState; }
bool isHWAntialiasState() const { return SkToBool(fFlags & kHWAntialias_Flag); }
bool snapVerticesToPixelCenters() const {
return SkToBool(fFlags & kSnapVerticesToPixelCenters_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(GrTexture*, const GrCaps&) 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");
}
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,
kScissorEnabled_Flag = 0x40,
kIsBad_Flag = 0x80,
};
using DstTextureProxy = GrPendingIOResource<GrTextureProxy, kRead_GrIOType>;
using FragmentProcessorArray = SkAutoSTArray<8, std::unique_ptr<const GrFragmentProcessor>>;
DstTextureProxy fDstTextureProxy;
SkIPoint fDstTextureOffset;
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;
};
#endif