diff options
author | Brian Salomon <bsalomon@google.com> | 2017-02-21 16:32:20 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-02-21 22:27:17 +0000 |
commit | 94cce4cb2cf40b5ed3a1928c02618c1a98b1e0fa (patch) | |
tree | bd311de3092f22788eb90123138e444347b752db /src/gpu/GrXferProcessor.h | |
parent | 5d5601c42982482552b9cde144558ddce9f789da (diff) |
Make GrXferProcessor and related classes private.
Change-Id: I81ea6f5ea5c8b7b23848ef24524a7e48e531efe8
Reviewed-on: https://skia-review.googlesource.com/8819
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src/gpu/GrXferProcessor.h')
-rw-r--r-- | src/gpu/GrXferProcessor.h | 372 |
1 files changed, 372 insertions, 0 deletions
diff --git a/src/gpu/GrXferProcessor.h b/src/gpu/GrXferProcessor.h new file mode 100644 index 0000000000..9cb7189133 --- /dev/null +++ b/src/gpu/GrXferProcessor.h @@ -0,0 +1,372 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrXferProcessor_DEFINED +#define GrXferProcessor_DEFINED + +#include "GrBlend.h" +#include "GrColor.h" +#include "GrProcessor.h" +#include "GrTexture.h" +#include "GrTypes.h" + +class GrShaderCaps; +class GrGLSLXferProcessor; +class GrProcOptInfo; +struct GrPipelineAnalysis; + +/** + * Barriers for blending. When a shader reads the dst directly, an Xfer barrier is sometimes + * required after a pixel has been written, before it can be safely read again. + */ +enum GrXferBarrierType { + kNone_GrXferBarrierType = 0, //<! No barrier is required + kTexture_GrXferBarrierType, //<! Required when a shader reads and renders to the same texture. + kBlend_GrXferBarrierType, //<! Required by certain blend extensions. +}; +/** Should be able to treat kNone as false in boolean expressions */ +GR_STATIC_ASSERT(SkToBool(kNone_GrXferBarrierType) == false); + +/** + * GrXferProcessor is responsible for implementing the xfer mode that blends the src color and dst + * color, and for applying any coverage. It does this by emitting fragment shader code and + * controlling the fixed-function blend state. When dual-source blending is available, it may also + * write a seconday fragment shader output color. GrXferProcessor has two modes of operation: + * + * Dst read: When allowed by the backend API, or when supplied a texture of the destination, the + * GrXferProcessor may read the destination color. While operating in this mode, the subclass only + * provides shader code that blends the src and dst colors, and the base class applies coverage. + * + * No dst read: When not performing a dst read, the subclass is given full control of the fixed- + * function blend state and/or secondary output, and is responsible to apply coverage on its own. + * + * A GrXferProcessor is never installed directly into our draw state, but instead is created from a + * GrXPFactory once we have finalized the state of our draw. + */ +class GrXferProcessor : public GrProcessor { +public: + /** + * A texture that contains the dst pixel values and an integer coord offset from device space + * to the space of the texture. Depending on GPU capabilities a DstTexture may be used by a + * GrXferProcessor for blending in the fragment shader. + */ + class DstTexture { + public: + DstTexture() { fOffset.set(0, 0); } + + DstTexture(const DstTexture& other) { + *this = other; + } + + DstTexture(GrTexture* texture, const SkIPoint& offset) + : fTexture(SkSafeRef(texture)) + , fOffset(offset) { + } + + DstTexture& operator=(const DstTexture& other) { + fTexture = other.fTexture; + fOffset = other.fOffset; + return *this; + } + + const SkIPoint& offset() const { return fOffset; } + + void setOffset(const SkIPoint& offset) { fOffset = offset; } + void setOffset(int ox, int oy) { fOffset.set(ox, oy); } + + GrTexture* texture() const { return fTexture.get(); } + + void setTexture(sk_sp<GrTexture> texture) { + fTexture = std::move(texture); + } + + private: + sk_sp<GrTexture> fTexture; + SkIPoint fOffset; + }; + + /** + * Sets a unique key on the GrProcessorKeyBuilder calls onGetGLSLProcessorKey(...) to get the + * specific subclass's key. + */ + void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const; + + /** Returns a new instance of the appropriate *GL* implementation class + for the given GrXferProcessor; caller is responsible for deleting + the object. */ + virtual GrGLSLXferProcessor* createGLSLInstance() const = 0; + + /** + * Optimizations for blending / coverage that an OptDrawState should apply to itself. + */ + enum OptFlags { + /** + * The draw can be skipped completely. + */ + kSkipDraw_OptFlag = 0x1, + /** + * GrXferProcessor will ignore color, thus no need to provide + */ + kIgnoreColor_OptFlag = 0x2, + /** + * Clear color stages and override input color to that returned by getOptimizations + */ + kOverrideColor_OptFlag = 0x4, + /** + * Can tweak alpha for coverage. Currently this flag should only be used by a GrDrawOp. + */ + kCanTweakAlphaForCoverage_OptFlag = 0x8, + }; + + static const OptFlags kNone_OptFlags = (OptFlags)0; + + GR_DECL_BITFIELD_OPS_FRIENDS(OptFlags); + + /** + * Determines which optimizations (as described by the ptFlags above) can be performed by + * the draw with this xfer processor. If this function is called, the xfer processor may change + * its state to reflected the given blend optimizations. If the XP needs to see a specific input + * color to blend correctly, it will set the OverrideColor flag and the output parameter + * overrideColor will be the required value that should be passed into the XP. + * A caller who calls this function on a XP is required to honor the returned OptFlags + * and color values for its draw. + */ + OptFlags getOptimizations(const GrPipelineAnalysis&, + bool doesStencilWrite, + GrColor* overrideColor, + const GrCaps& caps) const; + + /** + * Returns whether this XP will require an Xfer barrier on the given rt. If true, outBarrierType + * is updated to contain the type of barrier needed. + */ + GrXferBarrierType xferBarrierType(const GrRenderTarget* rt, const GrCaps& caps) const; + + struct BlendInfo { + void reset() { + fEquation = kAdd_GrBlendEquation; + fSrcBlend = kOne_GrBlendCoeff; + fDstBlend = kZero_GrBlendCoeff; + fBlendConstant = 0; + fWriteColor = true; + } + + SkDEBUGCODE(SkString dump() const;) + + GrBlendEquation fEquation; + GrBlendCoeff fSrcBlend; + GrBlendCoeff fDstBlend; + GrColor fBlendConstant; + bool fWriteColor; + }; + + void getBlendInfo(BlendInfo* blendInfo) const; + + bool willReadDstColor() const { return fWillReadDstColor; } + + /** + * Returns the texture to be used as the destination when reading the dst in the fragment + * shader. If the returned texture is NULL then the XP is either not reading the dst or we have + * extentions that support framebuffer fetching and thus don't need a copy of the dst texture. + */ + const GrTexture* getDstTexture() const { return fDstTexture.texture(); } + + /** + * Returns the offset in device coords to use when accessing the dst texture to get the dst + * pixel color in the shader. This value is only valid if getDstTexture() != NULL. + */ + const SkIPoint& dstTextureOffset() const { + SkASSERT(this->getDstTexture()); + return fDstTextureOffset; + } + + /** + * If we are performing a dst read, returns whether the base class will use mixed samples to + * antialias the shader's final output. If not doing a dst read, the subclass is responsible + * for antialiasing and this returns false. + */ + bool dstReadUsesMixedSamples() const { return fDstReadUsesMixedSamples; } + + /** + * Returns whether or not this xferProcossor will set a secondary output to be used with dual + * source blending. + */ + bool hasSecondaryOutput() const; + + /** Returns true if this and other processor conservatively draw identically. It can only return + true when the two processor are of the same subclass (i.e. they return the same object from + from getFactory()). + + A return value of true from isEqual() should not be used to test whether the processor would + generate the same shader code. To test for identical code generation use getGLSLProcessorKey + */ + + bool isEqual(const GrXferProcessor& that) const { + if (this->classID() != that.classID()) { + return false; + } + if (this->fWillReadDstColor != that.fWillReadDstColor) { + return false; + } + if (this->fDstTexture.texture() != that.fDstTexture.texture()) { + return false; + } + if (this->fDstTextureOffset != that.fDstTextureOffset) { + return false; + } + if (this->fDstReadUsesMixedSamples != that.fDstReadUsesMixedSamples) { + return false; + } + return this->onIsEqual(that); + } + +protected: + GrXferProcessor(); + GrXferProcessor(const DstTexture*, bool willReadDstColor, bool hasMixedSamples); + +private: + void notifyRefCntIsZero() const final {} + + virtual OptFlags onGetOptimizations(const GrPipelineAnalysis&, + bool doesStencilWrite, + GrColor* overrideColor, + const GrCaps& caps) const = 0; + + /** + * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this xfer + * processor's GL backend implementation. + */ + virtual void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0; + + /** + * Determines the type of barrier (if any) required by the subclass. Note that the possibility + * that a kTexture type barrier is required is handled by the base class and need not be + * considered by subclass overrides of this function. + */ + virtual GrXferBarrierType onXferBarrier(const GrRenderTarget*, const GrCaps&) const { + return kNone_GrXferBarrierType; + } + + /** + * If we are not performing a dst read, returns whether the subclass will set a secondary + * output. When using dst reads, the base class controls the secondary output and this method + * will not be called. + */ + virtual bool onHasSecondaryOutput() const { return false; } + + /** + * If we are not performing a dst read, retrieves the fixed-function blend state required by the + * subclass. When using dst reads, the base class controls the fixed-function blend state and + * this method will not be called. The BlendInfo struct comes initialized to "no blending". + */ + virtual void onGetBlendInfo(BlendInfo*) const {} + + virtual bool onIsEqual(const GrXferProcessor&) const = 0; + + bool fWillReadDstColor; + bool fDstReadUsesMixedSamples; + SkIPoint fDstTextureOffset; + TextureSampler fDstTexture; + + typedef GrFragmentProcessor INHERITED; +}; + +GR_MAKE_BITFIELD_OPS(GrXferProcessor::OptFlags); + +/////////////////////////////////////////////////////////////////////////////// + +/** + * We install a GrXPFactory (XPF) early on in the pipeline before all the final draw information is + * known (e.g. whether there is fractional pixel coverage, will coverage be 1 or 4 channel, is the + * draw opaque, etc.). Once the state of the draw is finalized, we use the XPF along with all the + * draw information to create a GrXferProcessor (XP) which can implement the desired blending for + * the draw. + * + * Before the XP is created, the XPF is able to answer queries about what functionality the XPs it + * creates will have. For example, can it create an XP that supports RGB coverage or will the XP + * blend with the destination color. + * + * GrXPFactories are intended to be static immutable objects. We pass them around as raw pointers + * and expect the pointers to always be valid and for the factories to be reusable and thread safe. + * Equality is tested for using pointer comparison. GrXPFactory destructors must be no-ops. + */ + +// In order to construct GrXPFactory subclass instances as constexpr the subclass, and therefore +// GrXPFactory, must be a literal type. One requirement is having a trivial destructor. This is ok +// since these objects have no need for destructors. However, GCC and clang throw a warning when a +// class has virtual functions and a non-virtual destructor. We suppress that warning here and +// for the subclasses. +#if defined(__GNUC__) || defined(__clang) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" +#endif +class GrXPFactory { +public: + typedef GrXferProcessor::DstTexture DstTexture; + + /** Describes known properties of a draw's color input to the GrXferProcessor. */ + enum class ColorType { kUnknown, kOpaqueConstant, kConstant, kOpaque }; + + /** + * Indicates whether a draw's coverage input to the GrXferProcessor is solid, single channel + * or LCD (four channel coverage). + */ + enum class CoverageType { kNone, kSingleChannel, kLCD }; + + GrXferProcessor* createXferProcessor(const GrPipelineAnalysis&, + bool hasMixedSamples, + const DstTexture*, + const GrCaps& caps) const; + + /** + * Is the destination color required either in the shader or fixed function blending. + */ + static bool WillReadDst(const GrXPFactory*, const GrProcOptInfo& colorInput, + const GrProcOptInfo& coverageInput); + + /** + * This will return true if the xfer processor needs the dst color in the shader and the way + * that the color will be made available to the xfer processor is by sampling a texture. + */ + bool willNeedDstTexture(const GrCaps& caps, const GrPipelineAnalysis& analysis) const; + +protected: + constexpr GrXPFactory() {} + + static bool ColorTypeIsOpaque(ColorType type) { + return ColorType::kOpaqueConstant == type || ColorType::kOpaque == type; + } + + static bool ColorTypeIsConstant(ColorType type) { + return ColorType::kOpaqueConstant == type || ColorType::kConstant == type; + } + +private: + /** Subclass-specific implementation of WillReadDst(). */ + virtual bool willReadsDst(const GrProcOptInfo& colorInput, + const GrProcOptInfo& coverageInput) const = 0; + + virtual GrXferProcessor* onCreateXferProcessor(const GrCaps& caps, + const GrPipelineAnalysis&, + bool hasMixedSamples, + const DstTexture*) const = 0; + + bool willReadDstInShader(const GrCaps& caps, const GrPipelineAnalysis& analysis) const; + + /** + * Returns true if the XP generated by this factory will explicitly read dst in the fragment + * shader. This will not be called for draws that read from PLS since the dst color is always + * available in such draws. + */ + virtual bool willReadDstInShader(const GrCaps&, ColorType, CoverageType) const = 0; +}; +#if defined(__GNUC__) || defined(__clang) +#pragma GCC diagnostic pop +#endif + +#endif + |