Add Coverage Drawing XP
BUG=skia: Review URL: https://codereview.chromium.org/808813002
This commit is contained in:
parent
3739913b6a
commit
8750924a14
@ -177,6 +177,8 @@
|
||||
'<(skia_src_path)/gpu/effects/Gr1DKernelEffect.h',
|
||||
'<(skia_src_path)/gpu/effects/GrConfigConversionEffect.cpp',
|
||||
'<(skia_src_path)/gpu/effects/GrConfigConversionEffect.h',
|
||||
'<(skia_src_path)/gpu/effects/GrCoverageSetOpXP.cpp',
|
||||
'<(skia_src_path)/gpu/effects/GrCoverageSetOpXP.h',
|
||||
'<(skia_src_path)/gpu/effects/GrBezierEffect.cpp',
|
||||
'<(skia_src_path)/gpu/effects/GrBezierEffect.h',
|
||||
'<(skia_src_path)/gpu/effects/GrConvolutionEffect.cpp',
|
||||
|
@ -86,11 +86,9 @@ public:
|
||||
* A caller who calls this function on a XP is required to honor the returned OptFlags
|
||||
* and color values for its draw.
|
||||
*/
|
||||
// TODO: remove need for isCoverageDrawing once coverageDrawing is its own XP.
|
||||
// TODO: remove need for colorWriteDisabled once colorWriteDisabled is its own XP.
|
||||
virtual OptFlags getOptimizations(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
bool isCoverageDrawing,
|
||||
bool colorWriteDisabled,
|
||||
bool doesStencilWrite,
|
||||
GrColor* overrideColor,
|
||||
@ -127,7 +125,6 @@ public:
|
||||
return this->onIsEqual(that);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
GrXferProcessor() : fWillReadDstColor(false) {}
|
||||
|
||||
@ -138,11 +135,6 @@ protected:
|
||||
*/
|
||||
void setWillReadDstColor() { fWillReadDstColor = true; }
|
||||
|
||||
/**
|
||||
* Subclass implements this to support getConstantColorComponents(...).
|
||||
*/
|
||||
virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const = 0;
|
||||
|
||||
private:
|
||||
virtual bool onIsEqual(const GrXferProcessor&) const = 0;
|
||||
|
||||
@ -181,30 +173,27 @@ public:
|
||||
* fractional pixel coverage generated by the fragment shader.
|
||||
*
|
||||
* This function considers the known color and coverage input into the xfer processor and
|
||||
* certain state information (isCoverageDrawing and colorWriteDisabled) to determine whether
|
||||
* certain state information (colorWriteDisabled) to determine whether
|
||||
* coverage can be handled correctly.
|
||||
*/
|
||||
// TODO: remove need for isCoverageDrawing once coverageDrawing is its own XP.
|
||||
// TODO: remove need for colorWriteDisabled once colorWriteDisabled is its own XP.
|
||||
virtual bool canApplyCoverage(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
|
||||
bool isCoverageDrawing, bool colorWriteDisabled) const = 0;
|
||||
bool colorWriteDisabled) const = 0;
|
||||
|
||||
/**
|
||||
* This function returns true if the destination pixel values will be read for blending during
|
||||
* draw.
|
||||
*/
|
||||
// TODO: remove need for isCoverageDrawing once coverageDrawing is its own XP.
|
||||
// TODO: remove need for colorWriteDisabled once only XP can read dst.
|
||||
virtual bool willBlendWithDst(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
|
||||
bool isCoverageDrawing, bool colorWriteDisabled) const = 0;
|
||||
bool colorWriteDisabled) const = 0;
|
||||
|
||||
/**
|
||||
* Determines whether multiplying the computed per-pixel color by the pixel's fractional
|
||||
* coverage before the blend will give the correct final destination color. In general it
|
||||
* will not as coverage is applied after blending.
|
||||
*/
|
||||
// TODO: remove need for isCoverageDrawing once coverageDrawing is its own XP.
|
||||
virtual bool canTweakAlphaForCoverage(bool isCoverageDrawing) const = 0;
|
||||
virtual bool canTweakAlphaForCoverage() const = 0;
|
||||
|
||||
virtual bool getOpaqueAndKnownColor(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI, GrColor* solidColor,
|
||||
|
@ -12,8 +12,8 @@
|
||||
#include "GrXferProcessor.h"
|
||||
#include "SkXfermode.h"
|
||||
|
||||
class GrDrawState;
|
||||
class GrInvariantOutput;
|
||||
class GrProcOptInfo;
|
||||
|
||||
class GrPorterDuffXferProcessor : public GrXferProcessor {
|
||||
public:
|
||||
@ -68,7 +68,6 @@ public:
|
||||
|
||||
GrXferProcessor::OptFlags getOptimizations(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
bool isCoverageDrawing,
|
||||
bool colorWriteDisabled,
|
||||
bool doesStencilWrite,
|
||||
GrColor* overrideColor,
|
||||
@ -95,11 +94,8 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE;
|
||||
|
||||
GrXferProcessor::OptFlags internalGetOptimizations(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
bool isCoverageDrawing,
|
||||
bool colorWriteDisabled,
|
||||
bool doesStencilWrite);
|
||||
|
||||
@ -135,12 +131,12 @@ public:
|
||||
bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const SK_OVERRIDE;
|
||||
|
||||
bool canApplyCoverage(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
|
||||
bool isCoverageDrawing, bool colorWriteDisabled) const SK_OVERRIDE;
|
||||
bool colorWriteDisabled) const SK_OVERRIDE;
|
||||
|
||||
bool willBlendWithDst(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
|
||||
bool isCoverageDrawing, bool colorWriteDisabled) const SK_OVERRIDE;
|
||||
bool colorWriteDisabled) const SK_OVERRIDE;
|
||||
|
||||
bool canTweakAlphaForCoverage(bool isCoverageDrawing) const SK_OVERRIDE;
|
||||
bool canTweakAlphaForCoverage() const SK_OVERRIDE;
|
||||
|
||||
bool getOpaqueAndKnownColor(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
|
@ -330,39 +330,15 @@ bool GrClipMaskManager::setupClipping(GrDrawState* drawState,
|
||||
|
||||
namespace {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// set up the OpenGL blend function to perform the specified
|
||||
// boolean operation for alpha clip mask creation
|
||||
void setup_boolean_blendcoeffs(SkRegion::Op op, GrDrawState* drawState) {
|
||||
// TODO: once we have a coverageDrawing XP this will all use that instead of PD
|
||||
switch (op) {
|
||||
case SkRegion::kReplace_Op:
|
||||
drawState->setPorterDuffXPFactory(kOne_GrBlendCoeff, kZero_GrBlendCoeff);
|
||||
break;
|
||||
case SkRegion::kIntersect_Op:
|
||||
drawState->setPorterDuffXPFactory(kDC_GrBlendCoeff, kZero_GrBlendCoeff);
|
||||
break;
|
||||
case SkRegion::kUnion_Op:
|
||||
drawState->setPorterDuffXPFactory(kOne_GrBlendCoeff, kISC_GrBlendCoeff);
|
||||
break;
|
||||
case SkRegion::kXOR_Op:
|
||||
drawState->setPorterDuffXPFactory(kIDC_GrBlendCoeff, kISC_GrBlendCoeff);
|
||||
break;
|
||||
case SkRegion::kDifference_Op:
|
||||
drawState->setPorterDuffXPFactory(kZero_GrBlendCoeff, kISC_GrBlendCoeff);
|
||||
break;
|
||||
case SkRegion::kReverseDifference_Op:
|
||||
drawState->setPorterDuffXPFactory(kIDC_GrBlendCoeff, kZero_GrBlendCoeff);
|
||||
break;
|
||||
default:
|
||||
SkASSERT(false);
|
||||
break;
|
||||
}
|
||||
// Set a coverage drawing XPF on the drawState for the given op and invertCoverage mode
|
||||
void set_coverage_drawing_xpf(SkRegion::Op op, bool invertCoverage, GrDrawState* drawState) {
|
||||
SkASSERT(op <= SkRegion::kLastOp);
|
||||
drawState->setCoverageSetOpXPFactory(op, invertCoverage);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool GrClipMaskManager::drawElement(GrDrawState* drawState,
|
||||
GrColor color,
|
||||
GrTexture* target,
|
||||
const SkClipStack::Element* element,
|
||||
GrPathRenderer* pr) {
|
||||
@ -370,6 +346,10 @@ bool GrClipMaskManager::drawElement(GrDrawState* drawState,
|
||||
|
||||
drawState->setRenderTarget(target->asRenderTarget());
|
||||
|
||||
// The color we use to draw does not matter since we will always be using a GrCoverageSetOpXP
|
||||
// which ignores color.
|
||||
GrColor color = GrColor_WHITE;
|
||||
|
||||
// TODO: Draw rrects directly here.
|
||||
switch (element->getType()) {
|
||||
case Element::kEmpty_Type:
|
||||
@ -451,17 +431,19 @@ void GrClipMaskManager::mergeMask(GrDrawState* drawState,
|
||||
|
||||
drawState->setRenderTarget(dstMask->asRenderTarget());
|
||||
|
||||
setup_boolean_blendcoeffs(op, drawState);
|
||||
// We want to invert the coverage here
|
||||
set_coverage_drawing_xpf(op, false, drawState);
|
||||
|
||||
SkMatrix sampleM;
|
||||
sampleM.setIDiv(srcMask->width(), srcMask->height());
|
||||
|
||||
drawState->addColorProcessor(
|
||||
drawState->addCoverageProcessor(
|
||||
GrTextureDomainEffect::Create(srcMask,
|
||||
sampleM,
|
||||
GrTextureDomain::MakeTexelDomain(srcMask, srcBound),
|
||||
GrTextureDomain::kDecal_Mode,
|
||||
GrTextureParams::kNone_FilterMode))->unref();
|
||||
// The color passed in here does not matter since the coverageSetOpXP won't read it.
|
||||
fClipTarget->drawSimpleRect(drawState, GrColor_WHITE, SkRect::Make(dstBound));
|
||||
}
|
||||
|
||||
@ -567,9 +549,7 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID,
|
||||
bool invert = element->isInverseFilled();
|
||||
if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) {
|
||||
GrDrawState drawState(translate);
|
||||
// We're drawing a coverage mask and want coverage to be run through the blend function.
|
||||
drawState.enableState(GrDrawState::kCoverageDrawing_StateBit |
|
||||
GrDrawState::kClip_StateBit);
|
||||
drawState.enableState(GrDrawState::kClip_StateBit);
|
||||
|
||||
GrPathRenderer* pr = NULL;
|
||||
bool useTemp = !this->canStencilAndDrawElement(&drawState, result, &pr, element);
|
||||
@ -603,7 +583,7 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID,
|
||||
invert ? 0xffffffff : 0x00000000,
|
||||
true,
|
||||
dst->asRenderTarget());
|
||||
setup_boolean_blendcoeffs(SkRegion::kReplace_Op, &drawState);
|
||||
set_coverage_drawing_xpf(SkRegion::kReplace_Op, invert, &drawState);
|
||||
} else {
|
||||
// draw directly into the result with the stencil set to make the pixels affected
|
||||
// by the clip shape be non-zero.
|
||||
@ -616,29 +596,29 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID,
|
||||
0xffff,
|
||||
0xffff);
|
||||
drawState.setStencil(kStencilInElement);
|
||||
setup_boolean_blendcoeffs(op, &drawState);
|
||||
set_coverage_drawing_xpf(op, invert, &drawState);
|
||||
}
|
||||
|
||||
// We have to backup the drawstate because the drawElement call may call into
|
||||
// renderers which consume it.
|
||||
GrDrawState backupDrawState(drawState);
|
||||
|
||||
if (!this->drawElement(&drawState, invert ? GrColor_TRANS_BLACK :
|
||||
GrColor_WHITE, dst, element, pr)) {
|
||||
if (!this->drawElement(&drawState, dst, element, pr)) {
|
||||
fAACache.reset();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GrDrawState backgroundDrawState(translate);
|
||||
backgroundDrawState.enableState(GrDrawState::kClip_StateBit);
|
||||
backgroundDrawState.setRenderTarget(result->asRenderTarget());
|
||||
|
||||
if (useTemp) {
|
||||
// Now draw into the accumulator using the real operation and the temp buffer as a
|
||||
// texture
|
||||
this->mergeMask(&backupDrawState,
|
||||
this->mergeMask(&backgroundDrawState,
|
||||
result,
|
||||
temp,
|
||||
op,
|
||||
maskSpaceIBounds,
|
||||
maskSpaceElementIBounds);
|
||||
} else {
|
||||
set_coverage_drawing_xpf(op, !invert, &backgroundDrawState);
|
||||
// Draw to the exterior pixels (those with a zero stencil value).
|
||||
GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement,
|
||||
kZero_StencilOp,
|
||||
@ -647,19 +627,18 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID,
|
||||
0xffff,
|
||||
0x0000,
|
||||
0xffff);
|
||||
backupDrawState.setStencil(kDrawOutsideElement);
|
||||
fClipTarget->drawSimpleRect(&backupDrawState,
|
||||
invert ? GrColor_WHITE : GrColor_TRANS_BLACK,
|
||||
clipSpaceIBounds);
|
||||
backgroundDrawState.setStencil(kDrawOutsideElement);
|
||||
// The color passed in here does not matter since the coverageSetOpXP won't read it.
|
||||
fClipTarget->drawSimpleRect(&backgroundDrawState, GrColor_WHITE, clipSpaceIBounds);
|
||||
}
|
||||
} else {
|
||||
GrDrawState drawState(translate);
|
||||
drawState.enableState(GrDrawState::kCoverageDrawing_StateBit |
|
||||
GrDrawState::kClip_StateBit);
|
||||
drawState.enableState(GrDrawState::kClip_StateBit);
|
||||
|
||||
// all the remaining ops can just be directly draw into the accumulation buffer
|
||||
setup_boolean_blendcoeffs(op, &drawState);
|
||||
this->drawElement(&drawState, GrColor_WHITE, result, element);
|
||||
set_coverage_drawing_xpf(op, false, &drawState);
|
||||
// The color passed in here does not matter since the coverageSetOpXP won't read it.
|
||||
this->drawElement(&drawState, result, element);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,6 @@ private:
|
||||
// desired blend operation. Optionally if the caller already selected a path renderer it can
|
||||
// be passed. Otherwise the function will select one if the element is a path.
|
||||
bool drawElement(GrDrawState*,
|
||||
GrColor,
|
||||
GrTexture* target,
|
||||
const SkClipStack::Element*,
|
||||
GrPathRenderer* pr = NULL);
|
||||
|
@ -185,21 +185,7 @@ bool GrDrawState::canUseFracCoveragePrimProc(GrColor color, const GrDrawTargetCa
|
||||
// so we don't have to pass in a seemingly known coverage
|
||||
this->calcCoverageInvariantOutput(GrColor_WHITE);
|
||||
return fXPFactory->canApplyCoverage(fColorProcInfo, fCoverageProcInfo,
|
||||
this->isCoverageDrawing(), this->isColorWriteDisabled());
|
||||
}
|
||||
|
||||
bool GrDrawState::hasSolidCoverage(const GrPrimitiveProcessor* pp) const {
|
||||
// If we're drawing coverage directly then coverage is effectively treated as color.
|
||||
if (this->isCoverageDrawing()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this->numCoverageStages() > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->calcCoverageInvariantOutput(pp);
|
||||
return fCoverageProcInfo.isSolidWhite();
|
||||
this->isColorWriteDisabled());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////s
|
||||
@ -252,7 +238,7 @@ void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
|
||||
// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
|
||||
// others will blend incorrectly.
|
||||
bool GrDrawState::canTweakAlphaForCoverage() const {
|
||||
return fXPFactory->canTweakAlphaForCoverage(this->isCoverageDrawing());
|
||||
return fXPFactory->canTweakAlphaForCoverage();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -354,7 +340,7 @@ bool GrDrawState::willBlendWithDst(const GrPrimitiveProcessor* pp) const {
|
||||
this->calcColorInvariantOutput(pp);
|
||||
this->calcCoverageInvariantOutput(pp);
|
||||
return fXPFactory->willBlendWithDst(fColorProcInfo, fCoverageProcInfo,
|
||||
this->isCoverageDrawing(), this->isColorWriteDisabled());
|
||||
this->isColorWriteDisabled());
|
||||
}
|
||||
|
||||
void GrDrawState::calcColorInvariantOutput(const GrPrimitiveProcessor* pp) const {
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "GrStencil.h"
|
||||
#include "GrXferProcessor.h"
|
||||
#include "SkMatrix.h"
|
||||
#include "effects/GrCoverageSetOpXP.h"
|
||||
#include "effects/GrPorterDuffXferProcessor.h"
|
||||
#include "effects/GrSimpleTextureEffect.h"
|
||||
|
||||
@ -82,11 +83,6 @@ public:
|
||||
*/
|
||||
bool canUseFracCoveragePrimProc(GrColor color, const GrDrawTargetCaps& caps) const;
|
||||
|
||||
/**
|
||||
* Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
|
||||
*/
|
||||
bool hasSolidCoverage(const GrPrimitiveProcessor*) const;
|
||||
|
||||
/**
|
||||
* This function returns true if the render target destination pixel values will be read for
|
||||
* blending during draw.
|
||||
@ -144,6 +140,10 @@ public:
|
||||
fXPFactory.reset(GrPorterDuffXPFactory::Create(src, dst));
|
||||
}
|
||||
|
||||
void setCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage = false) {
|
||||
fXPFactory.reset(GrCoverageSetOpXPFactory::Create(regionOp, invertCoverage));
|
||||
}
|
||||
|
||||
const GrFragmentProcessor* addColorProcessor(const GrFragmentProcessor* effect) {
|
||||
SkASSERT(effect);
|
||||
SkNEW_APPEND_TO_TARRAY(&fColorStages, GrFragmentStage, (effect));
|
||||
@ -416,21 +416,11 @@ public:
|
||||
*/
|
||||
kNoColorWrites_StateBit = 0x08,
|
||||
|
||||
/**
|
||||
* Usually coverage is applied after color blending. The color is blended using the coeffs
|
||||
* specified by setBlendFunc(). The blended color is then combined with dst using coeffs
|
||||
* of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
|
||||
* this case there is no distinction between coverage and color and the caller needs direct
|
||||
* control over the blend coeffs. When set, there will be a single blend step controlled by
|
||||
* setBlendFunc() which will use coverage*color as the src color.
|
||||
*/
|
||||
kCoverageDrawing_StateBit = 0x10,
|
||||
kLast_StateBit = kCoverageDrawing_StateBit,
|
||||
kLast_StateBit = kNoColorWrites_StateBit,
|
||||
};
|
||||
|
||||
bool isClipState() const { return 0 != (fFlagBits & kClip_StateBit); }
|
||||
bool isColorWriteDisabled() const { return 0 != (fFlagBits & kNoColorWrites_StateBit); }
|
||||
bool isCoverageDrawing() const { return 0 != (fFlagBits & kCoverageDrawing_StateBit); }
|
||||
bool isDither() const { return 0 != (fFlagBits & kDither_StateBit); }
|
||||
bool isHWAntialias() const { return 0 != (fFlagBits & kHWAntialias_StateBit); }
|
||||
|
||||
|
@ -55,7 +55,6 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
|
||||
|
||||
optFlags = xferProcessor->getOptimizations(colorPOI,
|
||||
coveragePOI,
|
||||
drawState.isCoverageDrawing(),
|
||||
drawState.isColorWriteDisabled(),
|
||||
drawState.getStencil().doesWrite(),
|
||||
&overrideColor,
|
||||
|
@ -52,7 +52,7 @@ GrProcessorTestFactory<GrGeometryProcessor>::GetFactories() {
|
||||
*/
|
||||
static const int kFPFactoryCount = 37;
|
||||
static const int kGPFactoryCount = 14;
|
||||
static const int kXPFactoryCount = 1;
|
||||
static const int kXPFactoryCount = 2;
|
||||
|
||||
template<>
|
||||
void GrProcessorTestFactory<GrFragmentProcessor>::VerifyFactoryCount() {
|
||||
|
235
src/gpu/effects/GrCoverageSetOpXP.cpp
Normal file
235
src/gpu/effects/GrCoverageSetOpXP.cpp
Normal file
@ -0,0 +1,235 @@
|
||||
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "effects/GrCoverageSetOpXP.h"
|
||||
#include "GrColor.h"
|
||||
#include "GrDrawTargetCaps.h"
|
||||
#include "GrInvariantOutput.h"
|
||||
#include "GrProcessor.h"
|
||||
#include "GrProcOptInfo.h"
|
||||
#include "gl/GrGLXferProcessor.h"
|
||||
#include "gl/builders/GrGLFragmentShaderBuilder.h"
|
||||
#include "gl/builders/GrGLProgramBuilder.h"
|
||||
|
||||
class GrGLCoverageSetOpXP : public GrGLXferProcessor {
|
||||
public:
|
||||
GrGLCoverageSetOpXP(const GrProcessor&) {}
|
||||
|
||||
~GrGLCoverageSetOpXP() SK_OVERRIDE {}
|
||||
|
||||
void emitCode(const EmitArgs& args) SK_OVERRIDE {
|
||||
const GrCoverageSetOpXP& xp = args.fXP.cast<GrCoverageSetOpXP>();
|
||||
GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
|
||||
|
||||
if (xp.invertCoverage()) {
|
||||
fsBuilder->codeAppendf("%s = 1.0 - %s;", args.fOutputPrimary, args.fInputCoverage);
|
||||
} else {
|
||||
fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
|
||||
}
|
||||
}
|
||||
|
||||
void setData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {};
|
||||
|
||||
static void GenKey(const GrProcessor& processor, const GrGLCaps& caps,
|
||||
GrProcessorKeyBuilder* b) {
|
||||
const GrCoverageSetOpXP& xp = processor.cast<GrCoverageSetOpXP>();
|
||||
uint32_t key = xp.invertCoverage() ? 0x0 : 0x1;
|
||||
b->add32(key);
|
||||
};
|
||||
|
||||
private:
|
||||
typedef GrGLXferProcessor INHERITED;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrCoverageSetOpXP::GrCoverageSetOpXP(SkRegion::Op regionOp, bool invertCoverage)
|
||||
: fRegionOp(regionOp)
|
||||
, fInvertCoverage(invertCoverage) {
|
||||
this->initClassID<GrCoverageSetOpXP>();
|
||||
}
|
||||
|
||||
GrCoverageSetOpXP::~GrCoverageSetOpXP() {
|
||||
}
|
||||
|
||||
void GrCoverageSetOpXP::getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
|
||||
GrGLCoverageSetOpXP::GenKey(*this, caps, b);
|
||||
}
|
||||
|
||||
GrGLXferProcessor* GrCoverageSetOpXP::createGLInstance() const {
|
||||
return SkNEW_ARGS(GrGLCoverageSetOpXP, (*this));
|
||||
}
|
||||
|
||||
GrXferProcessor::OptFlags
|
||||
GrCoverageSetOpXP::getOptimizations(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
bool colorWriteDisabled,
|
||||
bool doesStencilWrite,
|
||||
GrColor* color,
|
||||
const GrDrawTargetCaps& caps) {
|
||||
// We never look at the color input
|
||||
return GrXferProcessor::kIgnoreColor_OptFlag;
|
||||
}
|
||||
|
||||
void GrCoverageSetOpXP::getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const {
|
||||
switch (fRegionOp) {
|
||||
case SkRegion::kReplace_Op:
|
||||
blendInfo->fSrcBlend = kOne_GrBlendCoeff;
|
||||
blendInfo->fDstBlend = kZero_GrBlendCoeff;
|
||||
break;
|
||||
case SkRegion::kIntersect_Op:
|
||||
blendInfo->fSrcBlend = kDC_GrBlendCoeff;
|
||||
blendInfo->fDstBlend = kZero_GrBlendCoeff;
|
||||
break;
|
||||
case SkRegion::kUnion_Op:
|
||||
blendInfo->fSrcBlend = kOne_GrBlendCoeff;
|
||||
blendInfo->fDstBlend = kISC_GrBlendCoeff;
|
||||
break;
|
||||
case SkRegion::kXOR_Op:
|
||||
blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
|
||||
blendInfo->fDstBlend = kISC_GrBlendCoeff;
|
||||
break;
|
||||
case SkRegion::kDifference_Op:
|
||||
blendInfo->fSrcBlend = kZero_GrBlendCoeff;
|
||||
blendInfo->fDstBlend = kISC_GrBlendCoeff;
|
||||
break;
|
||||
case SkRegion::kReverseDifference_Op:
|
||||
blendInfo->fSrcBlend = kIDC_GrBlendCoeff;
|
||||
blendInfo->fDstBlend = kZero_GrBlendCoeff;
|
||||
break;
|
||||
}
|
||||
blendInfo->fBlendConstant = 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage)
|
||||
: fRegionOp(regionOp)
|
||||
, fInvertCoverage(invertCoverage) {
|
||||
this->initClassID<GrCoverageSetOpXPFactory>();
|
||||
}
|
||||
|
||||
GrXPFactory* GrCoverageSetOpXPFactory::Create(SkRegion::Op regionOp, bool invertCoverage) {
|
||||
switch (regionOp) {
|
||||
case SkRegion::kReplace_Op: {
|
||||
if (invertCoverage) {
|
||||
static GrCoverageSetOpXPFactory gReplaceCDXPFI(regionOp, invertCoverage);
|
||||
return SkRef(&gReplaceCDXPFI);
|
||||
} else {
|
||||
static GrCoverageSetOpXPFactory gReplaceCDXPF(regionOp, invertCoverage);
|
||||
return SkRef(&gReplaceCDXPF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SkRegion::kIntersect_Op: {
|
||||
if (invertCoverage) {
|
||||
static GrCoverageSetOpXPFactory gIntersectCDXPFI(regionOp, invertCoverage);
|
||||
return SkRef(&gIntersectCDXPFI);
|
||||
} else {
|
||||
static GrCoverageSetOpXPFactory gIntersectCDXPF(regionOp, invertCoverage);
|
||||
return SkRef(&gIntersectCDXPF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SkRegion::kUnion_Op: {
|
||||
if (invertCoverage) {
|
||||
static GrCoverageSetOpXPFactory gUnionCDXPFI(regionOp, invertCoverage);
|
||||
return SkRef(&gUnionCDXPFI);
|
||||
} else {
|
||||
static GrCoverageSetOpXPFactory gUnionCDXPF(regionOp, invertCoverage);
|
||||
return SkRef(&gUnionCDXPF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SkRegion::kXOR_Op: {
|
||||
if (invertCoverage) {
|
||||
static GrCoverageSetOpXPFactory gXORCDXPFI(regionOp, invertCoverage);
|
||||
return SkRef(&gXORCDXPFI);
|
||||
} else {
|
||||
static GrCoverageSetOpXPFactory gXORCDXPF(regionOp, invertCoverage);
|
||||
return SkRef(&gXORCDXPF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SkRegion::kDifference_Op: {
|
||||
if (invertCoverage) {
|
||||
static GrCoverageSetOpXPFactory gDifferenceCDXPFI(regionOp, invertCoverage);
|
||||
return SkRef(&gDifferenceCDXPFI);
|
||||
} else {
|
||||
static GrCoverageSetOpXPFactory gDifferenceCDXPF(regionOp, invertCoverage);
|
||||
return SkRef(&gDifferenceCDXPF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SkRegion::kReverseDifference_Op: {
|
||||
if (invertCoverage) {
|
||||
static GrCoverageSetOpXPFactory gRevDiffCDXPFI(regionOp, invertCoverage);
|
||||
return SkRef(&gRevDiffCDXPFI);
|
||||
} else {
|
||||
static GrCoverageSetOpXPFactory gRevDiffCDXPF(regionOp, invertCoverage);
|
||||
return SkRef(&gRevDiffCDXPF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GrXferProcessor* GrCoverageSetOpXPFactory::createXferProcessor(const GrProcOptInfo& /* colorPOI*/,
|
||||
const GrProcOptInfo& covPOI) const {
|
||||
return GrCoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
|
||||
}
|
||||
|
||||
bool GrCoverageSetOpXPFactory::willBlendWithDst(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
bool colorWriteDisabled) const {
|
||||
// TODO: once all SkXferEffects are XP's then we will never reads dst here since only XP's
|
||||
// will readDst and this XP doesn't read dst.
|
||||
if (coveragePOI.readsDst()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Besides Replace all other SkRegion ops will either have a src coeff that references dst or a
|
||||
// non zero dst coeff
|
||||
return SkRegion::kReplace_Op != fRegionOp;
|
||||
}
|
||||
|
||||
bool GrCoverageSetOpXPFactory::getOpaqueAndKnownColor(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
GrColor* solidColor,
|
||||
uint32_t* solidColorKnownComponents) const {
|
||||
if (!coveragePOI.isSolidWhite()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkASSERT((NULL == solidColor) == (NULL == solidColorKnownComponents));
|
||||
|
||||
bool opaque = SkRegion::kReplace_Op == fRegionOp;
|
||||
if (solidColor) {
|
||||
if (opaque) {
|
||||
*solidColor = GrColor_WHITE;
|
||||
*solidColorKnownComponents = kRGBA_GrColorComponentFlags;
|
||||
} else {
|
||||
solidColorKnownComponents = 0;
|
||||
}
|
||||
}
|
||||
return opaque;
|
||||
}
|
||||
|
||||
GR_DEFINE_XP_FACTORY_TEST(GrCoverageSetOpXPFactory);
|
||||
|
||||
GrXPFactory* GrCoverageSetOpXPFactory::TestCreate(SkRandom* random,
|
||||
GrContext*,
|
||||
const GrDrawTargetCaps&,
|
||||
GrTexture*[]) {
|
||||
SkRegion::Op regionOp = SkRegion::Op(random->nextULessThan(SkRegion::kLastOp + 1));
|
||||
bool invertCoverage = random->nextBool();
|
||||
return GrCoverageSetOpXPFactory::Create(regionOp, invertCoverage);
|
||||
}
|
||||
|
109
src/gpu/effects/GrCoverageSetOpXP.h
Normal file
109
src/gpu/effects/GrCoverageSetOpXP.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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 GrCoverageSetOpXP_DEFINED
|
||||
#define GrCoverageSetOpXP_DEFINED
|
||||
|
||||
#include "GrTypes.h"
|
||||
#include "GrXferProcessor.h"
|
||||
#include "SkRegion.h"
|
||||
|
||||
class GrInvariantOutput;
|
||||
class GrProcOptInfo;
|
||||
|
||||
/**
|
||||
* This xfer processor directly blends the the src coverage with the dst using a set operator. It is
|
||||
* useful for rendering coverage masks using CSG. It can optionally invert the src coverage before
|
||||
* applying the set operator.
|
||||
* */
|
||||
class GrCoverageSetOpXP : public GrXferProcessor {
|
||||
public:
|
||||
static GrXferProcessor* Create(SkRegion::Op regionOp, bool invertCoverage) {
|
||||
return SkNEW_ARGS(GrCoverageSetOpXP, (regionOp, invertCoverage));
|
||||
}
|
||||
|
||||
~GrCoverageSetOpXP() SK_OVERRIDE;
|
||||
|
||||
virtual const char* name() const { return "Coverage Set Op"; }
|
||||
|
||||
void getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const SK_OVERRIDE;
|
||||
|
||||
GrGLXferProcessor* createGLInstance() const SK_OVERRIDE;
|
||||
|
||||
bool hasSecondaryOutput() const SK_OVERRIDE { return false; }
|
||||
|
||||
GrXferProcessor::OptFlags getOptimizations(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
bool colorWriteDisabled,
|
||||
bool doesStencilWrite,
|
||||
GrColor* color,
|
||||
const GrDrawTargetCaps& caps) SK_OVERRIDE;
|
||||
|
||||
void getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const SK_OVERRIDE;
|
||||
|
||||
bool invertCoverage() const { return fInvertCoverage; }
|
||||
|
||||
private:
|
||||
GrCoverageSetOpXP(SkRegion::Op regionOp, bool fInvertCoverage);
|
||||
|
||||
bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE {
|
||||
const GrCoverageSetOpXP& xp = xpBase.cast<GrCoverageSetOpXP>();
|
||||
return (fRegionOp == xp.fRegionOp &&
|
||||
fInvertCoverage == xp.fInvertCoverage);
|
||||
}
|
||||
|
||||
SkRegion::Op fRegionOp;
|
||||
bool fInvertCoverage;
|
||||
|
||||
typedef GrXferProcessor INHERITED;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class GrCoverageSetOpXPFactory : public GrXPFactory {
|
||||
public:
|
||||
static GrXPFactory* Create(SkRegion::Op regionOp, bool invertCoverage = false);
|
||||
|
||||
GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI) const SK_OVERRIDE;
|
||||
|
||||
bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const SK_OVERRIDE {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool canApplyCoverage(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
|
||||
bool colorWriteDisabled) const SK_OVERRIDE {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool willBlendWithDst(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI,
|
||||
bool colorWriteDisabled) const SK_OVERRIDE;
|
||||
|
||||
bool canTweakAlphaForCoverage() const SK_OVERRIDE { return false; }
|
||||
|
||||
bool getOpaqueAndKnownColor(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
GrColor* solidColor,
|
||||
uint32_t* solidColorKnownComponents) const SK_OVERRIDE;
|
||||
|
||||
private:
|
||||
GrCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage);
|
||||
|
||||
bool onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE {
|
||||
const GrCoverageSetOpXPFactory& xpf = xpfBase.cast<GrCoverageSetOpXPFactory>();
|
||||
return fRegionOp == xpf.fRegionOp;
|
||||
}
|
||||
|
||||
GR_DECLARE_XP_FACTORY_TEST;
|
||||
|
||||
SkRegion::Op fRegionOp;
|
||||
bool fInvertCoverage;
|
||||
|
||||
typedef GrXPFactory INHERITED;
|
||||
};
|
||||
#endif
|
||||
|
@ -8,17 +8,17 @@
|
||||
#include "effects/GrPorterDuffXferProcessor.h"
|
||||
|
||||
#include "GrBlend.h"
|
||||
#include "GrDrawState.h"
|
||||
#include "GrDrawTargetCaps.h"
|
||||
#include "GrInvariantOutput.h"
|
||||
#include "GrProcessor.h"
|
||||
#include "GrProcOptInfo.h"
|
||||
#include "GrTypes.h"
|
||||
#include "GrXferProcessor.h"
|
||||
#include "gl/GrGLXferProcessor.h"
|
||||
#include "gl/builders/GrGLFragmentShaderBuilder.h"
|
||||
#include "gl/builders/GrGLProgramBuilder.h"
|
||||
|
||||
static bool can_tweak_alpha_for_coverage(GrBlendCoeff dstCoeff, bool isCoverageDrawing) {
|
||||
static bool can_tweak_alpha_for_coverage(GrBlendCoeff dstCoeff) {
|
||||
/*
|
||||
The fractional coverage is f.
|
||||
The src and dst coeffs are Cs and Cd.
|
||||
@ -27,14 +27,10 @@ static bool can_tweak_alpha_for_coverage(GrBlendCoeff dstCoeff, bool isCoverageD
|
||||
we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
|
||||
term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
|
||||
find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
|
||||
Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
|
||||
color by definition.
|
||||
*/
|
||||
// TODO: Once we have a CoverageDrawing XP, we don't need to check is CoverageDrawing here
|
||||
return kOne_GrBlendCoeff == dstCoeff ||
|
||||
kISA_GrBlendCoeff == dstCoeff ||
|
||||
kISC_GrBlendCoeff == dstCoeff ||
|
||||
isCoverageDrawing;
|
||||
kISC_GrBlendCoeff == dstCoeff;
|
||||
}
|
||||
|
||||
class GrGLPorterDuffXferProcessor : public GrGLXferProcessor {
|
||||
@ -128,14 +124,9 @@ GrGLXferProcessor* GrPorterDuffXferProcessor::createGLInstance() const {
|
||||
return SkNEW_ARGS(GrGLPorterDuffXferProcessor, (*this));
|
||||
}
|
||||
|
||||
void GrPorterDuffXferProcessor::onComputeInvariantOutput(GrInvariantOutput* inout) const {
|
||||
inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
|
||||
}
|
||||
|
||||
GrXferProcessor::OptFlags
|
||||
GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
bool isCoverageDrawing,
|
||||
bool colorWriteDisabled,
|
||||
bool doesStencilWrite,
|
||||
GrColor* overrideColor,
|
||||
@ -153,11 +144,10 @@ GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI,
|
||||
} else {
|
||||
optFlags = this->internalGetOptimizations(colorPOI,
|
||||
coveragePOI,
|
||||
isCoverageDrawing,
|
||||
colorWriteDisabled,
|
||||
doesStencilWrite);
|
||||
}
|
||||
this->calcOutputTypes(optFlags, caps, isCoverageDrawing || coveragePOI.isSolidWhite(),
|
||||
this->calcOutputTypes(optFlags, caps, coveragePOI.isSolidWhite(),
|
||||
colorPOI.readsDst() || coveragePOI.readsDst());
|
||||
return optFlags;
|
||||
}
|
||||
@ -208,7 +198,6 @@ void GrPorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFla
|
||||
GrXferProcessor::OptFlags
|
||||
GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
bool isCoverageDrawing,
|
||||
bool colorWriteDisabled,
|
||||
bool doesStencilWrite) {
|
||||
if (colorWriteDisabled) {
|
||||
@ -218,13 +207,9 @@ GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPO
|
||||
|
||||
bool srcAIsOne;
|
||||
bool hasCoverage;
|
||||
if (isCoverageDrawing) {
|
||||
srcAIsOne = colorPOI.isOpaque() && coveragePOI.isOpaque();
|
||||
hasCoverage = false;
|
||||
} else {
|
||||
srcAIsOne = colorPOI.isOpaque();
|
||||
hasCoverage = !coveragePOI.isSolidWhite();
|
||||
}
|
||||
|
||||
srcAIsOne = colorPOI.isOpaque();
|
||||
hasCoverage = !coveragePOI.isSolidWhite();
|
||||
|
||||
bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend ||
|
||||
(kSA_GrBlendCoeff == fDstBlend && srcAIsOne);
|
||||
@ -262,13 +247,10 @@ GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPO
|
||||
GrXferProcessor::kIgnoreCoverage_OptFlag;
|
||||
}
|
||||
}
|
||||
} else if (isCoverageDrawing) {
|
||||
// we have coverage but we aren't distinguishing it from alpha by request.
|
||||
return GrXferProcessor::kSetCoverageDrawing_OptFlag;
|
||||
} else {
|
||||
} else {
|
||||
// check whether coverage can be safely rolled into alpha
|
||||
// of if we can skip color computation and just emit coverage
|
||||
if (can_tweak_alpha_for_coverage(fDstBlend, isCoverageDrawing)) {
|
||||
if (can_tweak_alpha_for_coverage(fDstBlend)) {
|
||||
return GrXferProcessor::kSetCoverageDrawing_OptFlag;
|
||||
}
|
||||
if (dstCoeffIsZero) {
|
||||
@ -418,9 +400,8 @@ bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/,
|
||||
|
||||
bool GrPorterDuffXPFactory::canApplyCoverage(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
bool isCoverageDrawing,
|
||||
bool colorWriteDisabled) const {
|
||||
bool srcAIsOne = colorPOI.isOpaque() && (!isCoverageDrawing || coveragePOI.isOpaque());
|
||||
bool srcAIsOne = colorPOI.isOpaque();
|
||||
|
||||
if (colorWriteDisabled) {
|
||||
return true;
|
||||
@ -437,24 +418,19 @@ bool GrPorterDuffXPFactory::canApplyCoverage(const GrProcOptInfo& colorPOI,
|
||||
|
||||
// if we don't have coverage we can check whether the dst
|
||||
// has to read at all.
|
||||
if (isCoverageDrawing) {
|
||||
// we have coverage but we aren't distinguishing it from alpha by request.
|
||||
// check whether coverage can be safely rolled into alpha
|
||||
// of if we can skip color computation and just emit coverage
|
||||
if (this->canTweakAlphaForCoverage()) {
|
||||
return true;
|
||||
} else {
|
||||
// check whether coverage can be safely rolled into alpha
|
||||
// of if we can skip color computation and just emit coverage
|
||||
if (this->canTweakAlphaForCoverage(isCoverageDrawing)) {
|
||||
return true;
|
||||
}
|
||||
if (dstCoeffIsZero) {
|
||||
if (kZero_GrBlendCoeff == fSrcCoeff) {
|
||||
return true;
|
||||
} else if (srcAIsOne) {
|
||||
return true;
|
||||
}
|
||||
} else if (dstCoeffIsOne) {
|
||||
}
|
||||
if (dstCoeffIsZero) {
|
||||
if (kZero_GrBlendCoeff == fSrcCoeff) {
|
||||
return true;
|
||||
} else if (srcAIsOne) {
|
||||
return true;
|
||||
}
|
||||
} else if (dstCoeffIsOne) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: once all SkXferEffects are XP's then we will never reads dst here since only XP's
|
||||
@ -469,9 +445,8 @@ bool GrPorterDuffXPFactory::canApplyCoverage(const GrProcOptInfo& colorPOI,
|
||||
|
||||
bool GrPorterDuffXPFactory::willBlendWithDst(const GrProcOptInfo& colorPOI,
|
||||
const GrProcOptInfo& coveragePOI,
|
||||
bool isCoverageDrawing,
|
||||
bool colorWriteDisabled) const {
|
||||
if (!(isCoverageDrawing || coveragePOI.isSolidWhite())) {
|
||||
if (!coveragePOI.isSolidWhite()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -485,7 +460,7 @@ bool GrPorterDuffXPFactory::willBlendWithDst(const GrProcOptInfo& colorPOI,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool srcAIsOne = colorPOI.isOpaque() && (!isCoverageDrawing || coveragePOI.isOpaque());
|
||||
bool srcAIsOne = colorPOI.isOpaque();
|
||||
|
||||
if (!(kZero_GrBlendCoeff == fDstCoeff ||
|
||||
(kISA_GrBlendCoeff == fDstCoeff && srcAIsOne))) {
|
||||
@ -495,8 +470,8 @@ bool GrPorterDuffXPFactory::willBlendWithDst(const GrProcOptInfo& colorPOI,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GrPorterDuffXPFactory::canTweakAlphaForCoverage(bool isCoverageDrawing) const {
|
||||
return can_tweak_alpha_for_coverage(fDstCoeff, isCoverageDrawing);
|
||||
bool GrPorterDuffXPFactory::canTweakAlphaForCoverage() const {
|
||||
return can_tweak_alpha_for_coverage(fDstCoeff);
|
||||
}
|
||||
|
||||
bool GrPorterDuffXPFactory::getOpaqueAndKnownColor(const GrProcOptInfo& colorPOI,
|
||||
|
Loading…
Reference in New Issue
Block a user