Remove NVPR

Bug: skia:11760
Change-Id: Ie0fc1aaa3120b37b1d452fdc9a8b5cb91b6ffe1e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/386559
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2021-03-18 13:32:56 -04:00 committed by Skia Commit-Bot
parent 15206fb30d
commit 31798c2796
60 changed files with 64 additions and 2425 deletions

View File

@ -872,10 +872,6 @@ optional("gpu") {
sources -= skia_ccpr_sources
sources += [ "src/gpu/ccpr/GrCoverageCountingPathRenderer_none.cpp" ]
}
if (!skia_enable_nvpr) {
sources -= skia_nvpr_sources
sources += [ "src/gpu/GrPathRendering_none.cpp" ]
}
libs = []
frameworks = []

View File

@ -10,6 +10,8 @@ Milestone 91
development and isn't quite ready for prime time yet.
https://review.skia.org/378496
* Skia's GPU backend no longer supports NVPR. Our more recent path renderers are more
performant and are not limited to nVidia hardware.
* * *
Milestone 90

View File

@ -164,7 +164,6 @@ echo "Compiling bitcode"
\
skia_enable_skshaper=true \
skia_enable_ccpr=false \
skia_enable_nvpr=false \
skia_enable_pdf=false"
# Build all the libs we will need below

View File

@ -111,7 +111,6 @@ echo "Compiling bitcode"
skia_enable_tools=false \
skia_enable_skshaper=false \
skia_enable_ccpr=false \
skia_enable_nvpr=false \
skia_enable_fontmgr_custom_directory=false \
skia_enable_fontmgr_custom_embedded=true \
skia_enable_fontmgr_custom_empty=false \

View File

@ -613,7 +613,6 @@ skia_gl_gpu_sources = [
"$_src/gpu/gl/GrGLUniformHandler.h",
"$_src/gpu/gl/GrGLUtil.cpp",
"$_src/gpu/gl/GrGLUtil.h",
"$_src/gpu/gl/GrGLVaryingHandler.cpp",
"$_src/gpu/gl/GrGLVaryingHandler.h",
"$_src/gpu/gl/GrGLVertexArray.cpp",
"$_src/gpu/gl/GrGLVertexArray.h",
@ -640,27 +639,7 @@ skia_ccpr_sources = [
"$_src/gpu/ccpr/GrCoverageCountingPathRenderer.h",
]
skia_nvpr_sources = [
"$_src/gpu/GrPath.cpp",
"$_src/gpu/GrPath.h",
"$_src/gpu/GrPathProcessor.cpp",
"$_src/gpu/GrPathProcessor.h",
"$_src/gpu/GrPathRendering.cpp",
"$_src/gpu/GrPathRendering.h",
"$_src/gpu/gl/GrGLPath.cpp",
"$_src/gpu/gl/GrGLPath.h",
"$_src/gpu/gl/GrGLPathRendering.cpp",
"$_src/gpu/gl/GrGLPathRendering.h",
"$_src/gpu/ops/GrDrawPathOp.cpp",
"$_src/gpu/ops/GrDrawPathOp.h",
"$_src/gpu/ops/GrStencilAndCoverPathRenderer.cpp",
"$_src/gpu/ops/GrStencilAndCoverPathRenderer.h",
"$_src/gpu/ops/GrStencilPathOp.cpp",
"$_src/gpu/ops/GrStencilPathOp.h",
]
skia_gpu_sources += skia_ccpr_sources
skia_gpu_sources += skia_nvpr_sources
skia_null_gpu_sources = [ "$_src/gpu/gl/GrGLMakeNativeInterface_none.cpp" ]

View File

@ -108,7 +108,6 @@ declare_args() {
skia_enable_fontmgr_win_gdi = is_win && !skia_enable_winuwp
skia_enable_fontmgr_FontConfigInterface =
skia_use_freetype && skia_use_fontconfig
skia_enable_nvpr = !skia_enable_flutter_defines
skia_enable_spirv_validation = is_skia_dev_build && is_debug && !skia_use_dawn
skia_use_dng_sdk =
!is_fuchsia && skia_use_libjpeg_turbo_decode && skia_use_zlib

View File

@ -218,7 +218,6 @@ enum GrGLBackendState {
kProgram_GrGLBackendState = 1 << 8,
kFixedFunction_GrGLBackendState = 1 << 9,
kMisc_GrGLBackendState = 1 << 10,
kPathRendering_GrGLBackendState = 1 << 11,
kALL_GrGLBackendState = 0xffff
};

View File

@ -780,8 +780,7 @@ enum class GpuPathRenderers {
kAALinearizing = 1 << 5,
kSmall = 1 << 6,
kTriangulating = 1 << 7,
kStencilAndCover = 1 << 8,
kDefault = ((1 << 8) - 1) // All path renderers except NVPR
kDefault = ((1 << 8) - 1) // All path renderers.
};
/**

View File

@ -320,7 +320,6 @@ echo "Compiling bitcode"
${GN_VIEWER} \
\
skia_enable_skshaper=true \
skia_enable_nvpr=false \
skia_enable_skparagraph=true \
skia_enable_pdf=false"

View File

@ -131,7 +131,6 @@ echo "Compiling bitcode"
skia_enable_ccpr=true \
skia_enable_svg=true \
skia_enable_skshaper=true \
skia_enable_nvpr=false \
skia_enable_skparagraph=true \
skia_enable_pdf=false"

View File

@ -223,7 +223,6 @@ BASE_SRCS_ALL = struct(
"src/utils/win/**/*",
# Exclude multiple definitions.
"src/gpu/GrPathRendering_none.cpp",
"src/gpu/ccpr/GrCoverageCountingPathRenderer_none.cpp",
"src/gpu/gl/GrGLMakeNativeInterface_none.cpp",
"src/pdf/SkDocument_PDF_None.cpp", # We use src/pdf/SkPDFDocument.cpp.

View File

@ -22,7 +22,6 @@
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrGpuResourcePriv.h"
#include "src/gpu/GrNativeRect.h"
#include "src/gpu/GrPathRendering.h"
#include "src/gpu/GrPipeline.h"
#include "src/gpu/GrRenderTarget.h"
#include "src/gpu/GrResourceCache.h"

View File

@ -33,7 +33,6 @@ class GrGLContext;
class GrPath;
class GrPathRenderer;
class GrPathRendererChain;
class GrPathRendering;
class GrPipeline;
class GrPrimitiveProcessor;
class GrRenderTarget;
@ -64,8 +63,6 @@ public:
const GrCaps* caps() const { return fCaps.get(); }
sk_sp<const GrCaps> refCaps() const { return fCaps; }
GrPathRendering* pathRendering() { return fPathRendering.get(); }
virtual GrStagingBufferManager* stagingBufferManager() { return nullptr; }
virtual GrRingBuffer* uniformsRingBuffer() { return nullptr; }
@ -700,7 +697,6 @@ protected:
void setOOMed() { fOOMed = true; }
Stats fStats;
std::unique_ptr<GrPathRendering> fPathRendering;
// Subclass must call this to initialize caps & compiler in its constructor.
void initCapsAndCompiler(sk_sp<const GrCaps> caps);

View File

@ -21,7 +21,6 @@
#include "src/core/SkStringUtils.h"
#include "src/core/SkTLazy.h"
#include "src/gpu/GrAppliedClip.h"
#include "src/gpu/GrPathRendering.h"
#include "src/gpu/GrPrimitiveProcessor.h"
#include "src/gpu/GrRenderTask.h"
#include "src/gpu/ops/GrDrawOp.h"

View File

@ -1,55 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/GrPath.h"
#include "src/gpu/geometry/GrStyledShape.h"
static inline void write_style_key(uint32_t* key, const GrStyle& style) {
// Pass 1 for the scale since the GPU will apply the style not GrStyle::applyToPath().
GrStyle::WriteKey(key, style, GrStyle::Apply::kPathEffectAndStrokeRec, SK_Scalar1);
}
void GrPath::ComputeKey(const GrStyledShape& shape, GrUniqueKey* key, bool* outIsVolatile) {
int geoCnt = shape.unstyledKeySize();
int styleCnt = GrStyle::KeySize(shape.style(), GrStyle::Apply::kPathEffectAndStrokeRec);
// This should only fail for an arbitrary path effect, and we should not have gotten
// here with anything other than a dash path effect.
SkASSERT(styleCnt >= 0);
if (geoCnt < 0) {
*outIsVolatile = true;
return;
}
static const GrUniqueKey::Domain kGeneralPathDomain = GrUniqueKey::GenerateDomain();
GrUniqueKey::Builder builder(key, kGeneralPathDomain, geoCnt + styleCnt, "Path");
shape.writeUnstyledKey(&builder[0]);
if (styleCnt) {
write_style_key(&builder[geoCnt], shape.style());
}
*outIsVolatile = false;
}
#ifdef SK_DEBUG
bool GrPath::isEqualTo(const SkPath& path, const GrStyle& style) const {
// Since this is only called in debug we don't care about performance.
int cnt0 = GrStyle::KeySize(fStyle, GrStyle::Apply::kPathEffectAndStrokeRec);
int cnt1 = GrStyle::KeySize(style, GrStyle::Apply::kPathEffectAndStrokeRec);
if (cnt0 < 0 || cnt1 < 0 || cnt0 != cnt1) {
return false;
}
if (cnt0) {
SkAutoTArray<uint32_t> key0(cnt0);
SkAutoTArray<uint32_t> key1(cnt0);
write_style_key(key0.get(), fStyle);
write_style_key(key1.get(), style);
if (0 != memcmp(key0.get(), key1.get(), cnt0)) {
return false;
}
}
return fSkPath == path;
}
#endif

View File

@ -1,58 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrPath_DEFINED
#define GrPath_DEFINED
#include "include/core/SkPath.h"
#include "include/core/SkRect.h"
#include "src/gpu/GrGpuResource.h"
#include "src/gpu/GrPathRendering.h"
#include "src/gpu/GrStyle.h"
class GrStyledShape;
class GrPath : public GrGpuResource {
public:
/**
* Initialize to a path with a fixed stroke. Stroke must not be hairline.
*/
GrPath(GrGpu* gpu, const SkPath& skPath, const GrStyle& style)
: INHERITED(gpu)
, fBounds(SkRect::MakeEmpty())
, fFillType(GrPathRendering::kWinding_FillType)
#ifdef SK_DEBUG
, fSkPath(skPath)
, fStyle(style)
#endif
{
}
static void ComputeKey(const GrStyledShape&, GrUniqueKey* key, bool* outIsVolatile);
const SkRect& getBounds() const { return fBounds; }
GrPathRendering::FillType getFillType() const { return fFillType; }
#ifdef SK_DEBUG
bool isEqualTo(const SkPath& path, const GrStyle& style) const;
#endif
protected:
// Subclass should init these.
SkRect fBounds;
GrPathRendering::FillType fFillType;
#ifdef SK_DEBUG
SkPath fSkPath;
GrStyle fStyle;
#endif
private:
const char* getResourceType() const override { return "Path Data"; }
using INHERITED = GrGpuResource;
};
#endif

View File

@ -1,129 +0,0 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/GrPathProcessor.h"
#include "include/private/SkTo.h"
#include "src/core/SkMatrixPriv.h"
#include "src/gpu/GrShaderCaps.h"
#include "src/gpu/gl/GrGLGpu.h"
#ifdef SK_GL
#include "src/gpu/gl/GrGLVaryingHandler.h"
#endif
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLPrimitiveProcessor.h"
#include "src/gpu/glsl/GrGLSLUniformHandler.h"
#include "src/gpu/glsl/GrGLSLVarying.h"
class GrGLPathProcessor : public GrGLSLPrimitiveProcessor {
public:
GrGLPathProcessor() : fColor(SK_PMColor4fILLEGAL) {}
static void GenKey(const GrPathProcessor& pathProc,
const GrShaderCaps&,
GrProcessorKeyBuilder* b) {
b->add32(SkToInt(pathProc.viewMatrix().hasPerspective()));
}
void emitCode(EmitArgs& args) override {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
const GrPathProcessor& pathProc = args.fGP.cast<GrPathProcessor>();
if (!pathProc.viewMatrix().hasPerspective()) {
args.fVaryingHandler->setNoPerspective();
}
// emit transforms
this->emitTransforms(args.fVaryingHandler, args.fUniformHandler,
args.fFPCoordTransformHandler);
// Setup uniform color
const char* stagedLocalVarName;
fColorUniform = args.fUniformHandler->addUniform(nullptr,
kFragment_GrShaderFlag,
kHalf4_GrSLType,
"Color",
&stagedLocalVarName);
fragBuilder->codeAppendf("half4 %s = %s;", args.fOutputColor, stagedLocalVarName);
// setup constant solid coverage
fragBuilder->codeAppendf("const half4 %s = half4(1);", args.fOutputCoverage);
}
void emitTransforms(GrGLSLVaryingHandler* varyingHandler,
GrGLSLUniformHandler* uniformHandler,
FPCoordTransformHandler* transformHandler) {
for (int i = 0; *transformHandler; ++*transformHandler, ++i) {
SkString strVaryingName;
strVaryingName.printf("TransformedCoord_%d", i);
GrGLSLVarying v(kFloat2_GrSLType);
#ifdef SK_GL
GrGLVaryingHandler* glVaryingHandler = (GrGLVaryingHandler*)varyingHandler;
fVaryingTransform.push_back().fHandle =
glVaryingHandler->addPathProcessingVarying(strVaryingName.c_str(), &v)
.toIndex();
#endif
GrShaderVar fragmentVar = {SkString(v.fsIn()), kFloat2_GrSLType};
transformHandler->specifyCoordsForCurrCoordTransform(fragmentVar);
}
}
void setData(const GrGLSLProgramDataManager& pd,
const GrPrimitiveProcessor& primProc) override {
const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
if (pathProc.color() != fColor) {
pd.set4fv(fColorUniform, 1, pathProc.color().vec());
fColor = pathProc.color();
}
for (int v = 0; v < fVaryingTransform.count(); ++v) {
if (fVaryingTransform[v].fHandle.isValid()) {
SkMatrix m = pathProc.localMatrix();
if (!SkMatrixPriv::CheapEqual(fVaryingTransform[v].fCurrentValue, m)) {
fVaryingTransform[v].fCurrentValue = m;
pd.setPathFragmentInputTransform(fVaryingTransform[v].fHandle, 2, m);
}
}
}
}
private:
using VaryingHandle = GrGLSLProgramDataManager::VaryingHandle;
// Varying transforms are used for non-explicitly sampled FPs. We provide a matrix
// to GL as fixed function state and it uses it to compute a varying that we pick up
// in the FS as the transformed local coords.
struct TransformVarying {
VaryingHandle fHandle;
SkMatrix fCurrentValue = SkMatrix::InvalidMatrix();
};
SkTArray<TransformVarying, true> fVaryingTransform;
UniformHandle fColorUniform;
SkPMColor4f fColor;
using INHERITED = GrGLSLPrimitiveProcessor;
};
GrPathProcessor::GrPathProcessor(const SkPMColor4f& color,
const SkMatrix& viewMatrix,
const SkMatrix& localMatrix)
: INHERITED(kGrPathProcessor_ClassID)
, fColor(color)
, fViewMatrix(viewMatrix)
, fLocalMatrix(localMatrix) {}
void GrPathProcessor::getGLSLProcessorKey(const GrShaderCaps& caps,
GrProcessorKeyBuilder* b) const {
GrGLPathProcessor::GenKey(*this, caps, b);
}
GrGLSLPrimitiveProcessor* GrPathProcessor::createGLSLInstance(const GrShaderCaps& caps) const {
SkASSERT(caps.pathRenderingSupport());
return new GrGLPathProcessor();
}

View File

@ -1,47 +0,0 @@
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrPathProcessor_DEFINED
#define GrPathProcessor_DEFINED
#include "src/gpu/GrPrimitiveProcessor.h"
/*
* The path equivalent of the GP. For now this just manages color. In the long term we plan on
* extending this class to handle all nvpr uniform / varying / program work.
*/
class GrPathProcessor : public GrPrimitiveProcessor {
public:
static GrPathProcessor* Create(const SkPMColor4f& color,
const SkMatrix& viewMatrix = SkMatrix::I(),
const SkMatrix& localMatrix = SkMatrix::I()) {
return new GrPathProcessor(color, viewMatrix, localMatrix);
}
const char* name() const override { return "PathProcessor"; }
const SkPMColor4f& color() const { return fColor; }
const SkMatrix& viewMatrix() const { return fViewMatrix; }
const SkMatrix& localMatrix() const { return fLocalMatrix; }
void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps& caps) const override;
bool isPathRendering() const override { return true; }
private:
GrPathProcessor(const SkPMColor4f&, const SkMatrix& viewMatrix, const SkMatrix& localMatrix);
SkPMColor4f fColor;
const SkMatrix fViewMatrix;
const SkMatrix fLocalMatrix;
using INHERITED = GrPrimitiveProcessor;
};
#endif

View File

@ -86,7 +86,7 @@ public:
GrAAType fAAType;
bool fTargetIsWrappedVkSecondaryCB;
// This is only used by GrStencilAndCoverPathRenderer
// This is only used by GrTessellationPathRenderer
bool fHasUserStencilSettings;
#ifdef SK_DEBUG

View File

@ -23,7 +23,6 @@
#include "src/gpu/ops/GrDashLinePathRenderer.h"
#include "src/gpu/ops/GrDefaultPathRenderer.h"
#include "src/gpu/ops/GrSmallPathRenderer.h"
#include "src/gpu/ops/GrStencilAndCoverPathRenderer.h"
#include "src/gpu/ops/GrTriangulatingPathRenderer.h"
#include "src/gpu/tessellate/GrTessellationPathRenderer.h"
@ -55,18 +54,6 @@ GrPathRendererChain::GrPathRendererChain(GrRecordingContext* context, const Opti
if (options.fGpuPathRenderers & GpuPathRenderers::kSmall) {
fChain.push_back(sk_make_sp<GrSmallPathRenderer>());
}
if (options.fGpuPathRenderers & GpuPathRenderers::kStencilAndCover) {
auto direct = context->asDirectContext();
if (direct) {
auto resourceProvider = direct->priv().resourceProvider();
sk_sp<GrPathRenderer> pr(
GrStencilAndCoverPathRenderer::Create(resourceProvider, caps));
if (pr) {
fChain.push_back(std::move(pr));
}
}
}
if (options.fGpuPathRenderers & GpuPathRenderers::kTriangulating) {
fChain.push_back(sk_make_sp<GrTriangulatingPathRenderer>());
}

View File

@ -1,64 +0,0 @@
/*
* 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 "include/core/SkMatrix.h"
#include "include/core/SkTypeface.h"
#include "src/core/SkDescriptor.h"
#include "src/core/SkGlyph.h"
#include "src/core/SkScalerContext.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrPathRendering.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrRenderTarget.h"
const GrUserStencilSettings& GrPathRendering::GetStencilPassSettings(FillType fill) {
switch (fill) {
default:
SK_ABORT("Unexpected path fill.");
case GrPathRendering::kWinding_FillType: {
constexpr static GrUserStencilSettings kWindingStencilPass(
GrUserStencilSettings::StaticInit<
0xffff,
GrUserStencilTest::kAlwaysIfInClip,
0xffff,
GrUserStencilOp::kIncWrap,
GrUserStencilOp::kIncWrap,
0xffff>()
);
return kWindingStencilPass;
}
case GrPathRendering::kEvenOdd_FillType: {
constexpr static GrUserStencilSettings kEvenOddStencilPass(
GrUserStencilSettings::StaticInit<
0xffff,
GrUserStencilTest::kAlwaysIfInClip,
0xffff,
GrUserStencilOp::kInvert,
GrUserStencilOp::kInvert,
0xffff>()
);
return kEvenOddStencilPass;
}
}
}
void GrPathRendering::stencilPath(const StencilPathArgs& args, const GrPath* path) {
fGpu->handleDirtyContext();
this->onStencilPath(args, path);
}
void GrPathRendering::drawPath(GrRenderTarget* renderTarget,
const GrProgramInfo& programInfo,
// Cover pass settings in pipeline.
const GrStencilSettings& stencilPassSettings,
const GrPath* path) {
fGpu->handleDirtyContext();
if (auto barrierType = programInfo.pipeline().xferBarrierType(*fGpu->caps())) {
fGpu->xferBarrier(renderTarget, barrierType);
}
this->onDrawPath(stencilPassSettings, path);
}

View File

@ -1,134 +0,0 @@
/*
* 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 GrPathRendering_DEFINED
#define GrPathRendering_DEFINED
#include "include/core/SkPath.h"
class GrGpu;
class GrPath;
class GrProgramInfo;
class GrRenderTarget;
class GrRenderTargetProxy;
class GrScissorState;
class GrStencilSettings;
class GrStyle;
struct GrUserStencilSettings;
struct SkScalerContextEffects;
class SkDescriptor;
class SkTypeface;
/**
* Abstract class wrapping HW path rendering API.
*
* The subclasses of this class use the possible HW API to render paths (as opposed to path
* rendering implemented in Skia on top of a "3d" HW API).
* The subclasses hold the global state needed to render paths, including shadow of the global HW
* API state. Similar to GrGpu.
*
* It is expected that the lifetimes of GrGpuXX and GrXXPathRendering are the same. The call context
* interface (eg. * the concrete instance of GrGpu subclass) should be provided to the instance
* during construction.
*/
class GrPathRendering {
public:
virtual ~GrPathRendering() { }
enum PathTransformType {
kNone_PathTransformType, //!< []
kTranslateX_PathTransformType, //!< [kMTransX]
kTranslateY_PathTransformType, //!< [kMTransY]
kTranslate_PathTransformType, //!< [kMTransX, kMTransY]
kAffine_PathTransformType, //!< [kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY]
kLast_PathTransformType = kAffine_PathTransformType
};
static inline int PathTransformSize(PathTransformType type) {
switch (type) {
case kNone_PathTransformType:
return 0;
case kTranslateX_PathTransformType:
case kTranslateY_PathTransformType:
return 1;
case kTranslate_PathTransformType:
return 2;
case kAffine_PathTransformType:
return 6;
default:
SK_ABORT("Unknown path transform type");
}
}
// No native support for inverse at this time
enum FillType {
/** Specifies that "inside" is computed by a non-zero sum of signed
edge crossings
*/
kWinding_FillType,
/** Specifies that "inside" is computed by an odd number of edge
crossings
*/
kEvenOdd_FillType,
};
static const GrUserStencilSettings& GetStencilPassSettings(FillType);
/**
* Creates a new gpu path, based on the specified path and stroke and returns it.
*
* @param SkPath the geometry.
* @param GrStyle the style applied to the path. Styles with non-dash path effects are not
* allowed.
* @return a new GPU path object.
*/
virtual sk_sp<GrPath> createPath(const SkPath&, const GrStyle&) = 0;
/** None of these params are optional, pointers used just to avoid making copies. */
struct StencilPathArgs {
StencilPathArgs(bool useHWAA,
GrRenderTargetProxy* proxy,
GrSurfaceOrigin origin,
const SkMatrix* viewMatrix,
const GrScissorState* scissor,
const GrStencilSettings* stencil)
: fUseHWAA(useHWAA)
, fProxy(proxy)
, fOrigin(origin)
, fViewMatrix(viewMatrix)
, fScissor(scissor)
, fStencil(stencil) {
}
bool fUseHWAA;
GrRenderTargetProxy* fProxy;
GrSurfaceOrigin fOrigin;
const SkMatrix* fViewMatrix;
const GrScissorState* fScissor;
const GrStencilSettings* fStencil;
};
void stencilPath(const StencilPathArgs& args, const GrPath* path);
void drawPath(GrRenderTarget*,
const GrProgramInfo&,
const GrStencilSettings& stencilPassSettings, // Cover pass settings in pipeline.
const GrPath* path);
protected:
GrPathRendering(GrGpu* gpu) : fGpu(gpu) { }
virtual void onStencilPath(const StencilPathArgs&, const GrPath*) = 0;
virtual void onDrawPath(const GrStencilSettings&, const GrPath*) = 0;
GrGpu* fGpu;
private:
GrPathRendering& operator=(const GrPathRendering&);
};
#endif

View File

@ -1,56 +0,0 @@
/*
* Copyright 2018 Google LLC.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkTypes.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrPath.h"
#include "src/gpu/GrPathRenderer.h"
#include "src/gpu/GrPathRendering.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/gl/GrGLGpu.h"
#include "src/gpu/gl/GrGLPathRendering.h"
#include "src/gpu/ops/GrStencilAndCoverPathRenderer.h"
#include "src/gpu/ops/GrStencilPathOp.h"
class GrRecordingContext;
GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrResourceProvider* resourceProvider,
const GrCaps& caps) {
return nullptr;
}
GrGLPathRendering::GrGLPathRendering(GrGLGpu* gpu)
: GrPathRendering(gpu)
, fPreallocatedPathCount(0) {}
GrGLPathRendering::~GrGLPathRendering() {}
void GrGLPathRendering::disconnect(GrGpu::DisconnectType) {}
void GrGLPathRendering::resetContext() {}
void GrGLPathRendering::setProgramPathFragmentInputTransform(GrGLuint, GrGLint,
GrGLenum, GrGLint,
const SkMatrix&) {}
void GrGLPathRendering::setProjectionMatrix(const SkMatrix&, const SkISize&, GrSurfaceOrigin) {}
sk_sp<GrPath> GrGLPathRendering::createPath(const SkPath&, const GrStyle&) { return nullptr; }
void GrGLPathRendering::onDrawPath(const GrStencilSettings&, const GrPath*) {}
void GrGLPathRendering::onStencilPath(const StencilPathArgs&, const GrPath*) {}
GrOp::Owner GrStencilPathOp::Make(GrRecordingContext*,
const SkMatrix&,
bool,
bool,
const GrScissorState&,
sk_sp<const GrPath>) { return nullptr; }
void GrPath::ComputeKey(const GrStyledShape&, GrUniqueKey*, bool*) {}

View File

@ -219,8 +219,6 @@ public:
the object. */
virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const = 0;
virtual bool isPathRendering() const { return false; }
// We use these methods as a temporary back door to inject OpenGL tessellation code. Once
// tessellation is supported by SkSL we can remove these.
virtual SkString getTessControlShaderGLSL(const GrGLSLPrimitiveProcessor*,

View File

@ -99,11 +99,6 @@ public:
void validate(bool flushTime) const;
void checkAllInstantiated() const;
void checkMSAAAndMIPSAreResolved() const;
bool isNVPR() const {
return fPrimProc->isPathRendering() && !fPrimProc->willUseGeoShader() &&
!fPrimProc->numVertexAttributes() && !fPrimProc->numInstanceAttributes();
}
#endif
private:

View File

@ -19,8 +19,6 @@
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrGpuBuffer.h"
#include "src/gpu/GrImageInfo.h"
#include "src/gpu/GrPath.h"
#include "src/gpu/GrPathRendering.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRenderTarget.h"
#include "src/gpu/GrResourceCache.h"
@ -449,15 +447,6 @@ int GrResourceProvider::NumVertsPerAAQuad() { return kVertsPerAAQuad; }
int GrResourceProvider::NumIndicesPerAAQuad() { return kIndicesPerAAQuad; }
///////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<GrPath> GrResourceProvider::createPath(const SkPath& path, const GrStyle& style) {
if (this->isAbandoned()) {
return nullptr;
}
SkASSERT(this->gpu()->pathRendering());
return this->gpu()->pathRendering()->createPath(path, style);
}
sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(size_t size, GrGpuBufferType intendedType,
GrAccessPattern accessPattern,
const void* data) {

View File

@ -238,12 +238,6 @@ public:
static int NumVertsPerAAQuad();
static int NumIndicesPerAAQuad();
/**
* Factories for GrPath objects. It's an error to call these if path rendering
* is not supported.
*/
sk_sp<GrPath> createPath(const SkPath&, const GrStyle&);
/**
* Returns a buffer.
*

View File

@ -18,7 +18,6 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
fShaderDerivativeSupport = false;
fGeometryShaderSupport = false;
fGSInvocationsSupport = false;
fPathRenderingSupport = false;
fDstReadInShaderSupport = false;
fDualSourceBlendingSupport = false;
fIntegerSupport = false;
@ -86,7 +85,6 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
writer->appendBool("Shader Derivative Support", fShaderDerivativeSupport);
writer->appendBool("Geometry Shader Support", fGeometryShaderSupport);
writer->appendBool("Geometry Shader Invocations Support", fGSInvocationsSupport);
writer->appendBool("Path Rendering Support", fPathRenderingSupport);
writer->appendBool("Dst Read In Shader Support", fDstReadInShaderSupport);
writer->appendBool("Dual Source Blending Support", fDualSourceBlendingSupport);
writer->appendBool("Integer Support", fIntegerSupport);

View File

@ -44,7 +44,6 @@ public:
bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; }
bool geometryShaderSupport() const { return fGeometryShaderSupport; }
bool gsInvocationsSupport() const { return fGSInvocationsSupport; }
bool pathRenderingSupport() const { return fPathRenderingSupport; }
bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; }
bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; }
bool integerSupport() const { return fIntegerSupport; }
@ -263,7 +262,6 @@ private:
bool fShaderDerivativeSupport : 1;
bool fGeometryShaderSupport : 1;
bool fGSInvocationsSupport : 1;
bool fPathRenderingSupport : 1;
bool fDstReadInShaderSupport : 1;
bool fDualSourceBlendingSupport : 1;
bool fIntegerSupport : 1;

View File

@ -43,6 +43,7 @@
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRenderTarget.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/GrStencilSettings.h"
#include "src/gpu/GrStyle.h"
#include "src/gpu/GrTracing.h"
#include "src/gpu/SkGr.h"
@ -64,7 +65,6 @@
#include "src/gpu/ops/GrOvalOpFactory.h"
#include "src/gpu/ops/GrRegionOp.h"
#include "src/gpu/ops/GrShadowRRectOp.h"
#include "src/gpu/ops/GrStencilPathOp.h"
#include "src/gpu/ops/GrStrokeRectOp.h"
#include "src/gpu/ops/GrTextureOp.h"
#include "src/gpu/text/GrSDFTControl.h"
@ -818,51 +818,6 @@ bool GrSurfaceDrawContext::stencilPath(const GrHardClip* clip,
return true;
}
void GrSurfaceDrawContext::stencilPath(const GrHardClip* clip,
GrAA doStencilMSAA,
const SkMatrix& viewMatrix,
sk_sp<const GrPath> path) {
ASSERT_SINGLE_OWNER
RETURN_IF_ABANDONED
SkDEBUGCODE(this->validate();)
GR_CREATE_TRACE_MARKER_CONTEXT("GrSurfaceDrawContext", "stencilPath", fContext);
// TODO: extract portions of checkDraw that are relevant to path stenciling.
SkASSERT(path);
SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
// FIXME: Use path bounds instead of this WAR once
// https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
SkIRect bounds = SkIRect::MakeSize(this->dimensions());
// Setup clip and reject offscreen paths; we do this explicitly instead of relying on addDrawOp
// because GrStencilPathOp is not a draw op as its state depends directly on the choices made
// during this clip application.
GrAppliedHardClip appliedClip(this->dimensions(),
this->asSurfaceProxy()->backingStoreDimensions());
if (clip && GrClip::Effect::kClippedOut == clip->apply(&appliedClip, &bounds)) {
return;
}
// else see FIXME above; we'd normally want to check path bounds with render target bounds,
// but as it is, we're just using the full render target so intersecting the two bounds would
// do nothing.
GrOp::Owner op = GrStencilPathOp::Make(fContext,
viewMatrix,
doStencilMSAA == GrAA::kYes,
appliedClip.hasStencilClip(),
appliedClip.scissorState(),
std::move(path));
if (!op) {
return;
}
op->setClippedBounds(SkRect::Make(bounds));
this->setNeedsStencil(GrAA::kYes == doStencilMSAA);
this->addOp(std::move(op));
}
void GrSurfaceDrawContext::drawTextureSet(const GrClip* clip,
TextureSetEntry set[],
int cnt,

View File

@ -592,12 +592,6 @@ public:
const SkMatrix& viewMatrix,
const SkPath&);
// Same as for stencilPath, but for an NVPR path object.
void stencilPath(const GrHardClip*,
GrAA doStencilMSAA,
const SkMatrix& viewMatrix,
sk_sp<const GrPath>);
/**
* Draws a path, either AA or not, and touches the stencil buffer with the user stencil settings
* for each color sample written.

View File

@ -48,12 +48,6 @@ public:
void setMatrix3fv(UniformHandle, int arrayCount, const float matrices[]) const override;
void setMatrix4fv(UniformHandle, int arrayCount, const float matrices[]) const override;
// for nvpr only
void setPathFragmentInputTransform(VaryingHandle u, int components,
const SkMatrix& matrix) const override {
SK_ABORT("Only supported in NVPR, which is only available in GL");
}
// For the uniform data to be dirty so that we will reupload on the next use.
void markDirty() { fUniformsDirty = true; }

View File

@ -354,8 +354,6 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
this->initGLSL(ctxInfo, gli);
GrShaderCaps* shaderCaps = fShaderCaps.get();
shaderCaps->fPathRenderingSupport = this->hasPathRenderingSupport(ctxInfo, gli);
// Enable supported shader-related caps
if (GR_IS_GR_GL(standard)) {
shaderCaps->fDualSourceBlendingSupport =
@ -993,42 +991,6 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli
}
}
bool GrGLCaps::hasPathRenderingSupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
bool hasChromiumPathRendering = ctxInfo.hasExtension("GL_CHROMIUM_path_rendering");
if (!(ctxInfo.hasExtension("GL_NV_path_rendering") || hasChromiumPathRendering)) {
return false;
}
if (GR_IS_GR_GL(ctxInfo.standard())) {
if (ctxInfo.version() < GR_GL_VER(4, 3) &&
!ctxInfo.hasExtension("GL_ARB_program_interface_query")) {
return false;
}
} else if (GR_IS_GR_GL_ES(ctxInfo.standard())) {
if (!hasChromiumPathRendering &&
ctxInfo.version() < GR_GL_VER(3, 1)) {
return false;
}
} else if (GR_IS_GR_WEBGL(ctxInfo.standard())) {
// No WebGL support
return false;
}
// We only support v1.3+ of GL_NV_path_rendering which allows us to
// set individual fragment inputs with ProgramPathFragmentInputGen. The API
// additions are detected by checking the existence of the function.
// We also use *Then* functions that not all drivers might have. Check
// them for consistency.
if (!gli->fFunctions.fStencilThenCoverFillPath ||
!gli->fFunctions.fStencilThenCoverStrokePath ||
!gli->fFunctions.fStencilThenCoverFillPathInstanced ||
!gli->fFunctions.fStencilThenCoverStrokePathInstanced ||
!gli->fFunctions.fProgramPathFragmentInputGen) {
return false;
}
return true;
}
void GrGLCaps::initFSAASupport(const GrContextOptions& contextOptions,
const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
if (ctxInfo.hasExtension("GL_NV_framebuffer_mixed_samples") ||
@ -3944,19 +3906,6 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
}
}
// Workaround NVIDIA bug related to glInvalidateFramebuffer and mixed samples.
if (fMultisampleDisableSupport &&
this->shaderCaps()->dualSourceBlendingSupport() &&
this->shaderCaps()->pathRenderingSupport() &&
fMixedSamplesSupport &&
#if GR_TEST_UTILS
(contextOptions.fGpuPathRenderers & GpuPathRenderers::kStencilAndCover) &&
#endif
(kNVIDIA_GrGLDriver == ctxInfo.driver() ||
kChromium_GrGLDriver == ctxInfo.driver())) {
fInvalidateFBType = kNone_InvalidateFBType;
}
// Many ES3 drivers only advertise the ES2 image_external extension, but support the _essl3
// extension, and require that it be enabled to work with ESSL3. Other devices require the ES2
// extension to be enabled, even when using ESSL3. Enabling both extensions fixes both cases.

View File

@ -479,7 +479,6 @@ private:
void init(const GrContextOptions&, const GrGLContextInfo&, const GrGLInterface*);
void initGLSL(const GrGLContextInfo&, const GrGLInterface*);
bool hasPathRenderingSupport(const GrGLContextInfo&, const GrGLInterface*);
struct FormatWorkarounds {
bool fDisableSRGBRenderWithMSAAForMacAMD = false;

View File

@ -372,10 +372,6 @@ GrGLGpu::GrGLGpu(std::unique_ptr<GrGLContext> ctx, GrDirectContext* dContext)
}
static_assert(kGrGpuBufferTypeCount == SK_ARRAY_COUNT(fHWBufferState));
if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
fPathRendering = std::make_unique<GrGLPathRendering>(this);
}
if (this->glCaps().useSamplerObjects()) {
fSamplerObjectCache = std::make_unique<SamplerObjectCache>(this);
}
@ -384,7 +380,6 @@ GrGLGpu::GrGLGpu(std::unique_ptr<GrGLContext> ctx, GrDirectContext* dContext)
GrGLGpu::~GrGLGpu() {
// Ensure any GrGpuResource objects get deleted first, since they may require a working GrGLGpu
// to release the resources held by the objects themselves.
fPathRendering.reset();
fCopyProgramArrayBuffer.reset();
fMipmapProgramArrayBuffer.reset();
if (fProgramCache) {
@ -480,9 +475,6 @@ void GrGLGpu::disconnect(DisconnectType type) {
fMipmapPrograms[i].fProgram = 0;
}
if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
this->glPathRendering()->disconnect(type);
}
fFinishCallbacks.callAll(/* doDelete */ DisconnectType::kCleanup == type);
}
@ -606,12 +598,6 @@ void GrGLGpu::onResetContext(uint32_t resetBits) {
fBoundDrawFramebuffer = 0;
}
if (resetBits & kPathRendering_GrGLBackendState) {
if (this->caps()->shaderCaps()->pathRenderingSupport()) {
this->glPathRendering()->resetContext();
}
}
// we assume these values
if (resetBits & kPixelStore_GrGLBackendState) {
if (this->caps()->writePixelsRowBytesSupport()) {

View File

@ -20,7 +20,6 @@
#include "src/gpu/GrXferProcessor.h"
#include "src/gpu/gl/GrGLAttachment.h"
#include "src/gpu/gl/GrGLContext.h"
#include "src/gpu/gl/GrGLPathRendering.h"
#include "src/gpu/gl/GrGLProgram.h"
#include "src/gpu/gl/GrGLRenderTarget.h"
#include "src/gpu/gl/GrGLTexture.h"
@ -50,11 +49,6 @@ public:
GrGLSLGeneration glslGeneration() const { return fGLContext->glslGeneration(); }
const GrGLCaps& glCaps() const { return *fGLContext->caps(); }
GrGLPathRendering* glPathRendering() {
SkASSERT(glCaps().shaderCaps()->pathRenderingSupport());
return static_cast<GrGLPathRendering*>(pathRendering());
}
// Used by GrGLProgram to configure OpenGL state.
void bindTexture(int unitIdx, GrSamplerState samplerState, const GrSwizzle&, GrGLTexture*);

View File

@ -1,347 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/core/SkPathPriv.h"
#include "src/gpu/GrStyle.h"
#include "src/gpu/gl/GrGLGpu.h"
#include "src/gpu/gl/GrGLPath.h"
#include "src/gpu/gl/GrGLPathRendering.h"
namespace {
inline GrGLubyte verb_to_gl_path_cmd(SkPath::Verb verb) {
static const GrGLubyte gTable[] = {
GR_GL_MOVE_TO,
GR_GL_LINE_TO,
GR_GL_QUADRATIC_CURVE_TO,
GR_GL_CONIC_CURVE_TO,
GR_GL_CUBIC_CURVE_TO,
GR_GL_CLOSE_PATH,
};
static_assert(0 == SkPath::kMove_Verb);
static_assert(1 == SkPath::kLine_Verb);
static_assert(2 == SkPath::kQuad_Verb);
static_assert(3 == SkPath::kConic_Verb);
static_assert(4 == SkPath::kCubic_Verb);
static_assert(5 == SkPath::kClose_Verb);
SkASSERT(verb >= 0 && (size_t)verb < SK_ARRAY_COUNT(gTable));
return gTable[verb];
}
#ifdef SK_DEBUG
inline int num_coords(SkPath::Verb verb) {
static const int gTable[] = {
2, // move
2, // line
4, // quad
5, // conic
6, // cubic
0, // close
};
static_assert(0 == SkPath::kMove_Verb);
static_assert(1 == SkPath::kLine_Verb);
static_assert(2 == SkPath::kQuad_Verb);
static_assert(3 == SkPath::kConic_Verb);
static_assert(4 == SkPath::kCubic_Verb);
static_assert(5 == SkPath::kClose_Verb);
SkASSERT(verb >= 0 && (size_t)verb < SK_ARRAY_COUNT(gTable));
return gTable[verb];
}
#endif
inline GrGLenum join_to_gl_join(SkPaint::Join join) {
static GrGLenum gSkJoinsToGrGLJoins[] = {
GR_GL_MITER_REVERT,
GR_GL_ROUND,
GR_GL_BEVEL
};
return gSkJoinsToGrGLJoins[join];
static_assert(0 == SkPaint::kMiter_Join);
static_assert(1 == SkPaint::kRound_Join);
static_assert(2 == SkPaint::kBevel_Join);
static_assert(SK_ARRAY_COUNT(gSkJoinsToGrGLJoins) == SkPaint::kJoinCount);
}
inline GrGLenum cap_to_gl_cap(SkPaint::Cap cap) {
static GrGLenum gSkCapsToGrGLCaps[] = {
GR_GL_FLAT,
GR_GL_ROUND,
GR_GL_SQUARE
};
return gSkCapsToGrGLCaps[cap];
static_assert(0 == SkPaint::kButt_Cap);
static_assert(1 == SkPaint::kRound_Cap);
static_assert(2 == SkPaint::kSquare_Cap);
static_assert(SK_ARRAY_COUNT(gSkCapsToGrGLCaps) == SkPaint::kCapCount);
}
#ifdef SK_DEBUG
inline void verify_floats(const float* floats, int count) {
for (int i = 0; i < count; ++i) {
SkASSERT(!SkScalarIsNaN(SkFloatToScalar(floats[i])));
}
}
#endif
inline void points_to_coords(const SkPoint points[], size_t first_point, size_t amount,
GrGLfloat coords[]) {
for (size_t i = 0; i < amount; ++i) {
coords[i * 2] = SkScalarToFloat(points[first_point + i].fX);
coords[i * 2 + 1] = SkScalarToFloat(points[first_point + i].fY);
}
}
template<bool checkForDegenerates>
inline bool init_path_object_for_general_path(GrGLGpu* gpu, GrGLuint pathID,
const SkPath& skPath) {
SkDEBUGCODE(int numCoords = 0);
int verbCnt = skPath.countVerbs();
int pointCnt = skPath.countPoints();
int minCoordCnt = pointCnt * 2;
SkSTArray<16, GrGLubyte, true> pathCommands(verbCnt);
SkSTArray<16, GrGLfloat, true> pathCoords(minCoordCnt);
bool lastVerbWasMove = true; // A path with just "close;" means "moveto(0,0); close;"
for (auto [verb, points, w] : SkPathPriv::Iterate(skPath)) {
pathCommands.push_back(verb_to_gl_path_cmd((SkPath::Verb)verb));
GrGLfloat coords[6];
int coordsForVerb;
switch (verb) {
case SkPathVerb::kMove:
if (checkForDegenerates) {
lastVerbWasMove = true;
}
points_to_coords(points, 0, 1, coords);
coordsForVerb = 2;
break;
case SkPathVerb::kLine:
if (checkForDegenerates) {
if (SkPath::IsLineDegenerate(points[0], points[1], true)) {
return false;
}
lastVerbWasMove = false;
}
points_to_coords(points, 1, 1, coords);
coordsForVerb = 2;
break;
case SkPathVerb::kConic:
if (checkForDegenerates) {
if (SkPath::IsQuadDegenerate(points[0], points[1], points[2], true)) {
return false;
}
lastVerbWasMove = false;
}
points_to_coords(points, 1, 2, coords);
coords[4] = SkScalarToFloat(*w);
coordsForVerb = 5;
break;
case SkPathVerb::kQuad:
if (checkForDegenerates) {
if (SkPath::IsQuadDegenerate(points[0], points[1], points[2], true)) {
return false;
}
lastVerbWasMove = false;
}
points_to_coords(points, 1, 2, coords);
coordsForVerb = 4;
break;
case SkPathVerb::kCubic:
if (checkForDegenerates) {
if (SkPath::IsCubicDegenerate(points[0], points[1], points[2], points[3],
true)) {
return false;
}
lastVerbWasMove = false;
}
points_to_coords(points, 1, 3, coords);
coordsForVerb = 6;
break;
case SkPathVerb::kClose:
if (checkForDegenerates) {
if (lastVerbWasMove) {
// Interpret "move(x,y);close;" as "move(x,y);lineto(x,y);close;".
// which produces a degenerate segment.
return false;
}
}
continue;
}
SkDEBUGCODE(numCoords += num_coords((SkPath::Verb)verb));
SkDEBUGCODE(verify_floats(coords, coordsForVerb));
pathCoords.push_back_n(coordsForVerb, coords);
}
SkASSERT(verbCnt == pathCommands.count());
SkASSERT(numCoords == pathCoords.count());
GR_GL_CALL(gpu->glInterface(),
PathCommands(pathID, pathCommands.count(), pathCommands.begin(),
pathCoords.count(), GR_GL_FLOAT, pathCoords.begin()));
return true;
}
/*
* For now paths only natively support winding and even odd fill types
*/
static GrPathRendering::FillType convert_skpath_filltype(SkPathFillType fill) {
switch (fill) {
default:
SK_ABORT("Incomplete Switch\n");
case SkPathFillType::kWinding:
case SkPathFillType::kInverseWinding:
return GrPathRendering::kWinding_FillType;
case SkPathFillType::kEvenOdd:
case SkPathFillType::kInverseEvenOdd:
return GrPathRendering::kEvenOdd_FillType;
}
}
} // namespace
bool GrGLPath::InitPathObjectPathDataCheckingDegenerates(GrGLGpu* gpu, GrGLuint pathID,
const SkPath& skPath) {
return init_path_object_for_general_path<true>(gpu, pathID, skPath);
}
void GrGLPath::InitPathObjectPathData(GrGLGpu* gpu,
GrGLuint pathID,
const SkPath& skPath) {
SkASSERT(!skPath.isEmpty());
#if 1 // SK_SCALAR_IS_FLOAT
// This branch does type punning, converting SkPoint* to GrGLfloat*.
if ((skPath.getSegmentMasks() & SkPath::kConic_SegmentMask) == 0) {
int verbCnt = skPath.countVerbs();
int pointCnt = skPath.countPoints();
int coordCnt = pointCnt * 2;
SkAutoSTArray<16, GrGLubyte> pathCommands(verbCnt);
SkAutoSTArray<16, GrGLfloat> pathCoords(coordCnt);
static_assert(sizeof(SkPoint) == sizeof(GrGLfloat) * 2, "sk_point_not_two_floats");
skPath.getPoints(reinterpret_cast<SkPoint*>(&pathCoords[0]), pointCnt);
skPath.getVerbs(&pathCommands[0], verbCnt);
SkDEBUGCODE(int verbCoordCnt = 0);
for (int i = 0; i < verbCnt; ++i) {
SkPath::Verb v = static_cast<SkPath::Verb>(pathCommands[i]);
pathCommands[i] = verb_to_gl_path_cmd(v);
SkDEBUGCODE(verbCoordCnt += num_coords(v));
}
SkASSERT(verbCnt == pathCommands.count());
SkASSERT(verbCoordCnt == pathCoords.count());
SkDEBUGCODE(verify_floats(&pathCoords[0], pathCoords.count()));
GR_GL_CALL(gpu->glInterface(), PathCommands(pathID, pathCommands.count(), &pathCommands[0],
pathCoords.count(), GR_GL_FLOAT,
&pathCoords[0]));
return;
}
#endif
SkAssertResult(init_path_object_for_general_path<false>(gpu, pathID, skPath));
}
void GrGLPath::InitPathObjectStroke(GrGLGpu* gpu, GrGLuint pathID, const SkStrokeRec& stroke) {
SkASSERT(!stroke.isHairlineStyle());
GR_GL_CALL(gpu->glInterface(),
PathParameterf(pathID, GR_GL_PATH_STROKE_WIDTH, SkScalarToFloat(stroke.getWidth())));
GR_GL_CALL(gpu->glInterface(),
PathParameterf(pathID, GR_GL_PATH_MITER_LIMIT, SkScalarToFloat(stroke.getMiter())));
GrGLenum join = join_to_gl_join(stroke.getJoin());
GR_GL_CALL(gpu->glInterface(), PathParameteri(pathID, GR_GL_PATH_JOIN_STYLE, join));
GrGLenum cap = cap_to_gl_cap(stroke.getCap());
GR_GL_CALL(gpu->glInterface(), PathParameteri(pathID, GR_GL_PATH_END_CAPS, cap));
GR_GL_CALL(gpu->glInterface(), PathParameterf(pathID, GR_GL_PATH_STROKE_BOUND, 0.02f));
}
void GrGLPath::InitPathObjectEmptyPath(GrGLGpu* gpu, GrGLuint pathID) {
GR_GL_CALL(gpu->glInterface(), PathCommands(pathID, 0, nullptr, 0, GR_GL_FLOAT, nullptr));
}
GrGLPath::GrGLPath(GrGLGpu* gpu, const SkPath& origSkPath, const GrStyle& style)
: INHERITED(gpu, origSkPath, style),
fPathID(gpu->glPathRendering()->genPaths(1)) {
if (origSkPath.isEmpty()) {
InitPathObjectEmptyPath(gpu, fPathID);
fShouldStroke = false;
fShouldFill = false;
} else {
const SkPath* skPath = &origSkPath;
SkTLazy<SkPath> tmpPath;
SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
if (style.pathEffect()) {
// Skia stroking and NVPR stroking differ with respect to dashing
// pattern.
// Convert a dashing (or other path effect) to either a stroke or a fill.
if (style.applyPathEffectToPath(tmpPath.init(), &stroke, *skPath, SK_Scalar1)) {
skPath = tmpPath.get();
}
} else {
stroke = style.strokeRec();
}
// applyPathEffectToPath could have generated an empty path
if (skPath->isEmpty()) {
InitPathObjectEmptyPath(gpu, fPathID);
fShouldStroke = false;
fShouldFill = false;
} else {
bool didInit = false;
if (stroke.needToApply() && stroke.getCap() != SkPaint::kButt_Cap) {
// Skia stroking and NVPR stroking differ with respect to stroking
// end caps of empty subpaths.
// Convert stroke to fill if path contains empty subpaths.
didInit = InitPathObjectPathDataCheckingDegenerates(gpu, fPathID, *skPath);
if (!didInit) {
if (!tmpPath.isValid()) {
tmpPath.init();
}
SkAssertResult(stroke.applyToPath(tmpPath.get(), *skPath));
skPath = tmpPath.get();
stroke.setFillStyle();
}
}
if (!didInit) {
InitPathObjectPathData(gpu, fPathID, *skPath);
}
fShouldStroke = stroke.needToApply();
fShouldFill = stroke.isFillStyle() ||
stroke.getStyle() == SkStrokeRec::kStrokeAndFill_Style;
fFillType = convert_skpath_filltype(skPath->getFillType());
fBounds = skPath->getBounds();
SkScalar radius = stroke.getInflationRadius();
fBounds.outset(radius, radius);
if (fShouldStroke) {
InitPathObjectStroke(gpu, fPathID, stroke);
}
}
}
this->registerWithCache(SkBudgeted::kYes);
}
void GrGLPath::onRelease() {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
if (0 != fPathID) {
static_cast<GrGLGpu*>(this->getGpu())->glPathRendering()->deletePaths(fPathID, 1);
fPathID = 0;
}
INHERITED::onRelease();
}
void GrGLPath::onAbandon() {
fPathID = 0;
INHERITED::onAbandon();
}

View File

@ -1,56 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrGLPath_DEFINED
#define GrGLPath_DEFINED
#include "include/gpu/gl/GrGLTypes.h"
#include "src/gpu/GrPath.h"
class GrGLGpu;
class GrStyle;
/**
* Currently this represents a path built using GL_NV_path_rendering. If we
* support other GL path extensions then this would have to have a type enum
* and/or be subclassed.
*/
class GrGLPath : public GrPath {
public:
static bool InitPathObjectPathDataCheckingDegenerates(GrGLGpu*,
GrGLuint pathID,
const SkPath&);
static void InitPathObjectPathData(GrGLGpu*,
GrGLuint pathID,
const SkPath&);
static void InitPathObjectStroke(GrGLGpu*, GrGLuint pathID, const SkStrokeRec&);
static void InitPathObjectEmptyPath(GrGLGpu*, GrGLuint pathID);
GrGLPath(GrGLGpu*, const SkPath&, const GrStyle&);
GrGLuint pathID() const { return fPathID; }
bool shouldStroke() const { return fShouldStroke; }
bool shouldFill() const { return fShouldFill; }
protected:
void onRelease() override;
void onAbandon() override;
private:
// TODO: Figure out how to get an approximate size of the path in Gpu memory.
size_t onGpuMemorySize() const override { return 100; }
GrGLuint fPathID;
bool fShouldStroke;
bool fShouldFill;
using INHERITED = GrPath;
};
#endif

View File

@ -1,259 +0,0 @@
/*
* 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 "include/core/SkStream.h"
#include "include/core/SkTypeface.h"
#include "src/core/SkMatrixPriv.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrRenderTargetProxy.h"
#include "src/gpu/gl/GrGLGpu.h"
#include "src/gpu/gl/GrGLPath.h"
#include "src/gpu/gl/GrGLPathRendering.h"
#include "src/gpu/gl/GrGLUtil.h"
#define GL_CALL(X) GR_GL_CALL(this->gpu()->glInterface(), X)
#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(this->gpu()->glInterface(), RET, X)
// Number of paths to allocate per glGenPaths call. The call can be overly slow on command buffer GL
// implementation. The call has a result value, and thus waiting for the call completion is needed.
static const GrGLsizei kPathIDPreallocationAmount = 65536;
static_assert(0 == GrPathRendering::kNone_PathTransformType);
static_assert(1 == GrPathRendering::kTranslateX_PathTransformType);
static_assert(2 == GrPathRendering::kTranslateY_PathTransformType);
static_assert(3 == GrPathRendering::kTranslate_PathTransformType);
static_assert(4 == GrPathRendering::kAffine_PathTransformType);
static_assert(GrPathRendering::kAffine_PathTransformType == GrPathRendering::kLast_PathTransformType);
#ifdef SK_DEBUG
static void verify_floats(const float* floats, int count) {
for (int i = 0; i < count; ++i) {
SkASSERT(!SkScalarIsNaN(SkFloatToScalar(floats[i])));
}
}
#endif
static GrGLenum gr_stencil_op_to_gl_path_rendering_fill_mode(GrStencilOp op) {
switch (op) {
default:
SK_ABORT("Unexpected path fill.");
/* fallthrough */
case GrStencilOp::kIncWrap:
return GR_GL_COUNT_UP;
case GrStencilOp::kInvert:
return GR_GL_INVERT;
}
}
GrGLPathRendering::GrGLPathRendering(GrGLGpu* gpu)
: GrPathRendering(gpu)
, fPreallocatedPathCount(0) {
const GrGLInterface* glInterface = gpu->glInterface();
fCaps.bindFragmentInputSupport = (bool)glInterface->fFunctions.fBindFragmentInputLocation;
}
GrGLPathRendering::~GrGLPathRendering() {
if (fPreallocatedPathCount > 0) {
this->deletePaths(fFirstPreallocatedPathID, fPreallocatedPathCount);
}
}
void GrGLPathRendering::disconnect(GrGpu::DisconnectType type) {
if (GrGpu::DisconnectType::kCleanup == type) {
this->deletePaths(fFirstPreallocatedPathID, fPreallocatedPathCount);
}
fPreallocatedPathCount = 0;
}
void GrGLPathRendering::resetContext() {
fHWProjectionMatrixState.invalidate();
// we don't use the model view matrix.
GL_CALL(MatrixLoadIdentity(GR_GL_PATH_MODELVIEW));
fHWPathStencilSettings.invalidate();
}
sk_sp<GrPath> GrGLPathRendering::createPath(const SkPath& inPath, const GrStyle& style) {
return sk_make_sp<GrGLPath>(this->gpu(), inPath, style);
}
void GrGLPathRendering::onStencilPath(const StencilPathArgs& args, const GrPath* path) {
GrGLGpu* gpu = this->gpu();
SkASSERT(gpu->caps()->shaderCaps()->pathRenderingSupport());
gpu->flushColorWrite(false);
GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(args.fProxy->peekRenderTarget());
SkISize dimensions = rt->dimensions();
this->setProjectionMatrix(*args.fViewMatrix, dimensions, args.fOrigin);
gpu->flushScissor(*args.fScissor, rt->height(), args.fOrigin);
gpu->flushHWAAState(rt, args.fUseHWAA);
gpu->flushRenderTarget(rt);
const GrGLPath* glPath = static_cast<const GrGLPath*>(path);
this->flushPathStencilSettings(*args.fStencil);
GrGLenum fillMode = gr_stencil_op_to_gl_path_rendering_fill_mode(
fHWPathStencilSettings.singleSidedFace().fPassOp);
GrGLint writeMask = fHWPathStencilSettings.singleSidedFace().fWriteMask;
if (glPath->shouldFill()) {
GL_CALL(StencilFillPath(glPath->pathID(), fillMode, writeMask));
}
if (glPath->shouldStroke()) {
GL_CALL(StencilStrokePath(glPath->pathID(), 0xffff, writeMask));
}
}
void GrGLPathRendering::onDrawPath(const GrStencilSettings& stencilPassSettings,
const GrPath* path) {
const GrGLPath* glPath = static_cast<const GrGLPath*>(path);
this->flushPathStencilSettings(stencilPassSettings);
GrGLenum fillMode = gr_stencil_op_to_gl_path_rendering_fill_mode(
fHWPathStencilSettings.singleSidedFace().fPassOp);
GrGLint writeMask = fHWPathStencilSettings.singleSidedFace().fWriteMask;
if (glPath->shouldStroke()) {
if (glPath->shouldFill()) {
GL_CALL(StencilFillPath(glPath->pathID(), fillMode, writeMask));
}
GL_CALL(StencilThenCoverStrokePath(glPath->pathID(), 0xffff, writeMask,
GR_GL_BOUNDING_BOX));
} else {
GL_CALL(StencilThenCoverFillPath(glPath->pathID(), fillMode, writeMask,
GR_GL_BOUNDING_BOX));
}
}
void GrGLPathRendering::setProgramPathFragmentInputTransform(GrGLuint program, GrGLint location,
GrGLenum genMode, GrGLint components,
const SkMatrix& matrix) {
float coefficients[3 * 3];
SkASSERT(components >= 1 && components <= 3);
coefficients[0] = SkScalarToFloat(matrix[SkMatrix::kMScaleX]);
coefficients[1] = SkScalarToFloat(matrix[SkMatrix::kMSkewX]);
coefficients[2] = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
if (components >= 2) {
coefficients[3] = SkScalarToFloat(matrix[SkMatrix::kMSkewY]);
coefficients[4] = SkScalarToFloat(matrix[SkMatrix::kMScaleY]);
coefficients[5] = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
}
if (components >= 3) {
coefficients[6] = SkScalarToFloat(matrix[SkMatrix::kMPersp0]);
coefficients[7] = SkScalarToFloat(matrix[SkMatrix::kMPersp1]);
coefficients[8] = SkScalarToFloat(matrix[SkMatrix::kMPersp2]);
}
SkDEBUGCODE(verify_floats(coefficients, components * 3));
GL_CALL(ProgramPathFragmentInputGen(program, location, genMode, components, coefficients));
}
void GrGLPathRendering::setProjectionMatrix(const SkMatrix& matrix,
const SkISize& renderTargetSize,
GrSurfaceOrigin renderTargetOrigin) {
SkASSERT(this->gpu()->glCaps().shaderCaps()->pathRenderingSupport());
if (renderTargetOrigin == fHWProjectionMatrixState.fRenderTargetOrigin &&
renderTargetSize == fHWProjectionMatrixState.fRenderTargetSize &&
SkMatrixPriv::CheapEqual(matrix, fHWProjectionMatrixState.fViewMatrix)) {
return;
}
fHWProjectionMatrixState.fViewMatrix = matrix;
fHWProjectionMatrixState.fRenderTargetSize = renderTargetSize;
fHWProjectionMatrixState.fRenderTargetOrigin = renderTargetOrigin;
float glMatrix[4 * 4];
fHWProjectionMatrixState.getRTAdjustedGLMatrix(glMatrix);
SkDEBUGCODE(verify_floats(glMatrix, SK_ARRAY_COUNT(glMatrix)));
GL_CALL(MatrixLoadf(GR_GL_PATH_PROJECTION, glMatrix));
}
GrGLuint GrGLPathRendering::genPaths(GrGLsizei range) {
SkASSERT(range > 0);
GrGLuint firstID;
if (fPreallocatedPathCount >= range) {
firstID = fFirstPreallocatedPathID;
fPreallocatedPathCount -= range;
fFirstPreallocatedPathID += range;
return firstID;
}
// Allocate range + the amount to fill up preallocation amount. If succeed, either join with
// the existing preallocation range or delete the existing and use the new (potentially partial)
// preallocation range.
GrGLsizei allocAmount = range + (kPathIDPreallocationAmount - fPreallocatedPathCount);
if (allocAmount >= range) {
GL_CALL_RET(firstID, GenPaths(allocAmount));
if (firstID != 0) {
if (fPreallocatedPathCount > 0 &&
firstID == fFirstPreallocatedPathID + fPreallocatedPathCount) {
firstID = fFirstPreallocatedPathID;
fPreallocatedPathCount += allocAmount - range;
fFirstPreallocatedPathID += range;
return firstID;
}
if (allocAmount > range) {
if (fPreallocatedPathCount > 0) {
this->deletePaths(fFirstPreallocatedPathID, fPreallocatedPathCount);
}
fFirstPreallocatedPathID = firstID + range;
fPreallocatedPathCount = allocAmount - range;
}
// Special case: if allocAmount == range, we have full preallocated range.
return firstID;
}
}
// Failed to allocate with preallocation. Remove existing preallocation and try to allocate just
// the range.
if (fPreallocatedPathCount > 0) {
this->deletePaths(fFirstPreallocatedPathID, fPreallocatedPathCount);
fPreallocatedPathCount = 0;
}
GL_CALL_RET(firstID, GenPaths(range));
if (firstID == 0) {
SkDebugf("Warning: Failed to allocate path\n");
}
return firstID;
}
void GrGLPathRendering::deletePaths(GrGLuint path, GrGLsizei range) {
GL_CALL(DeletePaths(path, range));
}
void GrGLPathRendering::flushPathStencilSettings(const GrStencilSettings& stencilSettings) {
SkASSERT(!stencilSettings.isTwoSided());
if (fHWPathStencilSettings != stencilSettings) {
SkASSERT(stencilSettings.isValid());
// Just the func, ref, and mask is set here. The op and write mask are params to the call
// that draws the path to the SB (glStencilFillPath)
uint16_t ref = stencilSettings.singleSidedFace().fRef;
GrStencilTest test = stencilSettings.singleSidedFace().fTest;
uint16_t testMask = stencilSettings.singleSidedFace().fTestMask;
if (!fHWPathStencilSettings.isValid() ||
ref != fHWPathStencilSettings.singleSidedFace().fRef ||
test != fHWPathStencilSettings.singleSidedFace().fTest ||
testMask != fHWPathStencilSettings.singleSidedFace().fTestMask) {
GL_CALL(PathStencilFunc(GrToGLStencilFunc(test), ref, testMask));
}
fHWPathStencilSettings = stencilSettings;
}
}
inline GrGLGpu* GrGLPathRendering::gpu() {
return static_cast<GrGLGpu*>(fGpu);
}

View File

@ -1,120 +0,0 @@
/*
* 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 GrGLPathRendering_DEFINED
#define GrGLPathRendering_DEFINED
#include "include/core/SkM44.h"
#include "include/core/SkRefCnt.h"
#include "include/gpu/gl/GrGLTypes.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrPathRendering.h"
#include "src/gpu/GrStencilSettings.h"
class GrGLGpu;
class GrStyle;
/**
* This class wraps the NV_path_rendering extension and manages its various
* API versions. If a method is not present in the GrGLInterface of the GrGLGpu
* (because the driver version is old), it tries to provide a backup
* implementation. But if a backup implementation is not practical, it marks the
* method as not supported.
*/
class GrGLPathRendering : public GrPathRendering {
public:
/**
* Create a new GrGLPathRendering object from a given GrGLGpu.
*/
GrGLPathRendering(GrGLGpu* gpu);
~GrGLPathRendering() override;
// GrPathRendering implementations.
sk_sp<GrPath> createPath(const SkPath&, const GrStyle&) override;
/* Called when the 3D context state is unknown. */
void resetContext();
/**
* Called when the context either is about to be lost or is lost. DisconnectType indicates
* whether GPU resources should be cleaned up or abandoned when this is called.
*/
void disconnect(GrGpu::DisconnectType);
bool shouldBindFragmentInputs() const {
return fCaps.bindFragmentInputSupport;
}
// Functions for "separable shader" texturing support.
void setProgramPathFragmentInputTransform(GrGLuint program, GrGLint location,
GrGLenum genMode, GrGLint components,
const SkMatrix&);
/* Sets the projection matrix for path rendering */
void setProjectionMatrix(const SkMatrix& matrix,
const SkISize& renderTargetSize,
GrSurfaceOrigin renderTargetOrigin);
GrGLuint genPaths(GrGLsizei range);
GrGLvoid deletePaths(GrGLuint path, GrGLsizei range);
protected:
void onStencilPath(const StencilPathArgs&, const GrPath*) override;
void onDrawPath(const GrStencilSettings&, const GrPath*) override;
private:
/**
* Mark certain functionality as not supported.
*/
struct Caps {
bool bindFragmentInputSupport : 1;
};
void flushPathStencilSettings(const GrStencilSettings&);
struct MatrixState {
SkMatrix fViewMatrix;
SkISize fRenderTargetSize;
GrSurfaceOrigin fRenderTargetOrigin;
MatrixState() { this->invalidate(); }
void invalidate() {
fViewMatrix = SkMatrix::InvalidMatrix();
fRenderTargetSize.fWidth = -1;
fRenderTargetSize.fHeight = -1;
fRenderTargetOrigin = (GrSurfaceOrigin) -1;
}
/**
* Gets a matrix that goes from local coordinates to GL normalized device coords.
*/
void getRTAdjustedGLMatrix(float* destMatrix) {
SkMatrix combined;
if (kBottomLeft_GrSurfaceOrigin == fRenderTargetOrigin) {
combined.setAll(SkIntToScalar(2) / fRenderTargetSize.fWidth, 0, -SK_Scalar1,
0, -SkIntToScalar(2) / fRenderTargetSize.fHeight, SK_Scalar1,
0, 0, 1);
} else {
combined.setAll(SkIntToScalar(2) / fRenderTargetSize.fWidth, 0, -SK_Scalar1,
0, SkIntToScalar(2) / fRenderTargetSize.fHeight, -SK_Scalar1,
0, 0, 1);
}
combined.preConcat(fViewMatrix);
SkM44 combined44(combined);
combined44.getColMajor(destMatrix);
}
};
GrGLGpu* gpu();
GrGLuint fFirstPreallocatedPathID;
GrGLsizei fPreallocatedPathCount;
MatrixState fHWProjectionMatrixState;
GrStencilSettings fHWPathStencilSettings;
Caps fCaps;
};
#endif

View File

@ -7,7 +7,6 @@
#include "src/gpu/gl/GrGLProgram.h"
#include "src/gpu/GrPathProcessor.h"
#include "src/gpu/GrPipeline.h"
#include "src/gpu/GrProcessor.h"
#include "src/gpu/GrProgramInfo.h"
@ -15,7 +14,6 @@
#include "src/gpu/GrXferProcessor.h"
#include "src/gpu/gl/GrGLBuffer.h"
#include "src/gpu/gl/GrGLGpu.h"
#include "src/gpu/gl/GrGLPathRendering.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
#include "src/gpu/glsl/GrGLSLXferProcessor.h"
@ -31,7 +29,6 @@ sk_sp<GrGLProgram> GrGLProgram::Make(
GrGLuint programID,
const UniformInfoArray& uniforms,
const UniformInfoArray& textureSamplers,
const VaryingInfoArray& pathProcVaryings,
std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
std::vector<std::unique_ptr<GrGLSLFragmentProcessor>> fpImpls,
@ -45,7 +42,6 @@ sk_sp<GrGLProgram> GrGLProgram::Make(
programID,
uniforms,
textureSamplers,
pathProcVaryings,
std::move(geometryProcessor),
std::move(xferProcessor),
std::move(fpImpls),
@ -60,21 +56,19 @@ sk_sp<GrGLProgram> GrGLProgram::Make(
return program;
}
GrGLProgram::GrGLProgram(
GrGLGpu* gpu,
const GrGLSLBuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
const UniformInfoArray& textureSamplers,
const VaryingInfoArray& pathProcVaryings,
std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
std::vector<std::unique_ptr<GrGLSLFragmentProcessor>> fpImpls,
std::unique_ptr<Attribute[]> attributes,
int vertexAttributeCnt,
int instanceAttributeCnt,
int vertexStride,
int instanceStride)
GrGLProgram::GrGLProgram(GrGLGpu* gpu,
const GrGLSLBuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
const UniformInfoArray& textureSamplers,
std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
std::vector<std::unique_ptr<GrGLSLFragmentProcessor>> fpImpls,
std::unique_ptr<Attribute[]> attributes,
int vertexAttributeCnt,
int instanceAttributeCnt,
int vertexStride,
int instanceStride)
: fBuiltinUniformHandles(builtinUniforms)
, fProgramID(programID)
, fPrimitiveProcessor(std::move(geometryProcessor))
@ -86,7 +80,7 @@ GrGLProgram::GrGLProgram(
, fVertexStride(vertexStride)
, fInstanceStride(instanceStride)
, fGpu(gpu)
, fProgramDataManager(gpu, programID, uniforms, pathProcVaryings)
, fProgramDataManager(gpu, uniforms)
, fNumTextureSamplers(textureSamplers.count()) {
}
@ -169,19 +163,13 @@ void GrGLProgram::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin
// set RT adjustment
SkISize dimensions = rt->dimensions();
if (!primProc.isPathRendering()) {
if (fRenderTargetState.fRenderTargetOrigin != origin ||
fRenderTargetState.fRenderTargetSize != dimensions) {
fRenderTargetState.fRenderTargetSize = dimensions;
fRenderTargetState.fRenderTargetOrigin = origin;
if (fRenderTargetState.fRenderTargetOrigin != origin ||
fRenderTargetState.fRenderTargetSize != dimensions) {
fRenderTargetState.fRenderTargetSize = dimensions;
fRenderTargetState.fRenderTargetOrigin = origin;
float rtAdjustmentVec[4];
fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
}
} else {
SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport());
const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
fGpu->glPathRendering()->setProjectionMatrix(pathProc.viewMatrix(), dimensions, origin);
float rtAdjustmentVec[4];
fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
}
}

View File

@ -55,7 +55,6 @@ public:
GrGLuint programID,
const UniformInfoArray& uniforms,
const UniformInfoArray& textureSamplers,
const VaryingInfoArray&, // used for NVPR only currently
std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
std::vector<std::unique_ptr<GrGLSLFragmentProcessor>> fps,
@ -147,7 +146,6 @@ private:
GrGLuint programID,
const UniformInfoArray& uniforms,
const UniformInfoArray& textureSamplers,
const VaryingInfoArray&, // used for NVPR only currently
std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
std::vector<std::unique_ptr<GrGLSLFragmentProcessor>> fpImpls,

View File

@ -14,11 +14,8 @@
SkASSERT((COUNT) <= (UNI).fArrayCount || \
(1 == (COUNT) && GrShaderVar::kNonArray == (UNI).fArrayCount))
GrGLProgramDataManager::GrGLProgramDataManager(GrGLGpu* gpu, GrGLuint programID,
const UniformInfoArray& uniforms,
const VaryingInfoArray& pathProcVaryings)
: fGpu(gpu)
, fProgramID(programID) {
GrGLProgramDataManager::GrGLProgramDataManager(GrGLGpu* gpu, const UniformInfoArray& uniforms)
: fGpu(gpu) {
fUniforms.push_back_n(uniforms.count());
int i = 0;
for (const GLUniformInfo& builderUniform : uniforms.items()) {
@ -31,21 +28,6 @@ GrGLProgramDataManager::GrGLProgramDataManager(GrGLGpu* gpu, GrGLuint programID,
)
uniform.fLocation = builderUniform.fLocation;
}
// NVPR programs have separable varyings
fPathProcVaryings.push_back_n(pathProcVaryings.count());
i = 0;
for (const VaryingInfo& builderPathProcVarying : pathProcVaryings.items()) {
SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport());
PathProcVarying& pathProcVarying = fPathProcVaryings[i++];
SkASSERT(GrShaderVar::kNonArray == builderPathProcVarying.fVariable.getArrayCount() ||
builderPathProcVarying.fVariable.getArrayCount() > 0);
SkDEBUGCODE(
pathProcVarying.fArrayCount = builderPathProcVarying.fVariable.getArrayCount();
pathProcVarying.fType = builderPathProcVarying.fVariable.getType();
)
pathProcVarying.fLocation = builderPathProcVarying.fLocation;
}
}
void GrGLProgramDataManager::setSamplerUniforms(const UniformInfoArray& samplers,
@ -296,21 +278,3 @@ template<> struct set_uniform_matrix<4> {
GR_GL_CALL(gli, UniformMatrix4fv(loc, cnt, false, m));
}
};
void GrGLProgramDataManager::setPathFragmentInputTransform(VaryingHandle u,
int components,
const SkMatrix& matrix) const {
SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport());
const PathProcVarying& fragmentInput = fPathProcVaryings[u.toIndex()];
SkASSERT((components == 2 && (fragmentInput.fType == kFloat2_GrSLType ||
fragmentInput.fType == kHalf2_GrSLType)) ||
(components == 3 && (fragmentInput.fType == kFloat3_GrSLType ||
fragmentInput.fType == kHalf3_GrSLType)));
fGpu->glPathRendering()->setProgramPathFragmentInputTransform(fProgramID,
fragmentInput.fLocation,
GR_GL_OBJECT_LINEAR,
components,
matrix);
}

View File

@ -41,8 +41,7 @@ public:
typedef GrTBlockList<GLUniformInfo> UniformInfoArray;
typedef GrTBlockList<VaryingInfo> VaryingInfoArray;
GrGLProgramDataManager(GrGLGpu*, GrGLuint programID, const UniformInfoArray&,
const VaryingInfoArray&);
GrGLProgramDataManager(GrGLGpu*, const UniformInfoArray&);
void setSamplerUniforms(const UniformInfoArray& samplers, int startUnit) const;
@ -74,10 +73,6 @@ public:
void setMatrix3fv(UniformHandle, int arrayCount, const float matrices[]) const override;
void setMatrix4fv(UniformHandle, int arrayCount, const float matrices[]) const override;
// for nvpr only
void setPathFragmentInputTransform(VaryingHandle u, int components,
const SkMatrix& matrix) const override;
private:
enum {
kUnusedUniform = -1,
@ -91,24 +86,11 @@ private:
#endif
};
enum {
kUnusedPathProcVarying = -1,
};
struct PathProcVarying {
GrGLint fLocation;
SkDEBUGCODE(
GrSLType fType;
int fArrayCount;
);
};
template<int N> inline void setMatrices(UniformHandle, int arrayCount,
const float matrices[]) const;
SkTArray<Uniform, true> fUniforms;
SkTArray<PathProcVarying, true> fPathProcVaryings;
GrGLGpu* fGpu;
GrGLuint fProgramID;
using INHERITED = GrGLSLProgramDataManager;
};

View File

@ -1,36 +0,0 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/gl/GrGLVaryingHandler.h"
#include "src/gpu/gl/GrGLGpu.h"
#include "src/gpu/gl/builders/GrGLProgramBuilder.h"
GrGLSLVaryingHandler::VaryingHandle GrGLVaryingHandler::addPathProcessingVarying(
const char* name,
GrGLSLVarying* v) {
#ifdef SK_DEBUG
GrGLProgramBuilder* glPB = (GrGLProgramBuilder*) fProgramBuilder;
// This call is not used for non-NVPR backends.
SkASSERT(glPB->gpu()->glCaps().shaderCaps()->pathRenderingSupport() &&
fProgramBuilder->fProgramInfo.isNVPR());
#endif
this->addVarying(name, v);
auto varyingInfo = fPathProcVaryingInfos.push_back();
varyingInfo.fLocation = fPathProcVaryingInfos.count() - 1;
return VaryingHandle(varyingInfo.fLocation);
}
void GrGLVaryingHandler::onFinalize() {
SkASSERT(fPathProcVaryingInfos.empty() || fPathProcVaryingInfos.count() == fFragInputs.count());
VarArray::Iter::Item fragInputIter = fFragInputs.items().begin();
for (auto& varyingInfo : fPathProcVaryingInfos.items()) {
varyingInfo.fVariable = *fragInputIter;
++fragInputIter;
}
}

View File

@ -14,18 +14,10 @@
class GrGLVaryingHandler : public GrGLSLVaryingHandler {
public:
GrGLVaryingHandler(GrGLSLProgramBuilder* program)
: INHERITED(program),
fPathProcVaryingInfos(kVaryingsPerBlock) {}
// This function is used by the NVPR PathProcessor to add a varying directly into the fragment
// shader since there is no vertex shader.
VaryingHandle addPathProcessingVarying(const char* name, GrGLSLVarying*);
GrGLVaryingHandler(GrGLSLProgramBuilder* program) : INHERITED(program) {}
private:
void onFinalize() override;
GrGLProgramDataManager::VaryingInfoArray fPathProcVaryingInfos;
void onFinalize() override {}
friend class GrGLProgramBuilder;

View File

@ -378,11 +378,8 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::finalize(const GrGLPrecompiledProgram* pr
return nullptr;
}
// This also binds vertex attribute locations. NVPR doesn't really use vertices,
// even though it requires a vertex shader in the program.
if (!primProc.isPathRendering()) {
this->computeCountsAndStrides(programID, primProc, true);
}
// This also binds vertex attribute locations.
this->computeCountsAndStrides(programID, primProc, true);
/*
Tessellation Shaders
@ -493,18 +490,6 @@ void GrGLProgramBuilder::bindProgramResourceLocations(GrGLuint programID) {
GL_CALL(BindFragDataLocationIndexed(programID, 0, 1,
GrGLSLFragmentShaderBuilder::DeclaredSecondaryColorOutputName()));
}
// handle NVPR separable varyings
if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
!fGpu->glPathRendering()->shouldBindFragmentInputs()) {
return;
}
int i = 0;
for (auto& varying : fVaryingHandler.fPathProcVaryingInfos.items()) {
GL_CALL(BindFragmentInputLocation(programID, i, varying.fVariable.c_str()));
varying.fLocation = i;
++i;
}
}
bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID,
@ -544,20 +529,6 @@ bool GrGLProgramBuilder::checkLinkStatus(GrGLuint programID,
void GrGLProgramBuilder::resolveProgramResourceLocations(GrGLuint programID, bool force) {
fUniformHandler.getUniformLocations(programID, fGpu->glCaps(), force);
// handle NVPR separable varyings
if (!fGpu->glCaps().shaderCaps()->pathRenderingSupport() ||
fGpu->glPathRendering()->shouldBindFragmentInputs()) {
return;
}
for (auto& varying : fVaryingHandler.fPathProcVaryingInfos.items()) {
GrGLint location;
GL_CALL_RET(location, GetProgramResourceLocation(
programID,
GR_GL_FRAGMENT_INPUT,
varying.fVariable.c_str()));
varying.fLocation = location;
}
}
sk_sp<GrGLProgram> GrGLProgramBuilder::createProgram(GrGLuint programID) {
@ -566,7 +537,6 @@ sk_sp<GrGLProgram> GrGLProgramBuilder::createProgram(GrGLuint programID) {
programID,
fUniformHandler.fUniforms,
fUniformHandler.fSamplers,
fVaryingHandler.fPathProcVaryingInfos,
std::move(fGeometryProcessor),
std::move(fXferProcessor),
std::move(fFPImpls),

View File

@ -58,11 +58,6 @@ public:
// convenience method for uploading a SkMatrix to a 4x4 matrix uniform
void setSkM44(UniformHandle, const SkM44&) const;
// for nvpr only
GR_DEFINE_RESOURCE_HANDLE_CLASS(VaryingHandle);
virtual void setPathFragmentInputTransform(VaryingHandle u, int components,
const SkMatrix& matrix) const = 0;
protected:
GrGLSLProgramDataManager() {}

View File

@ -151,7 +151,6 @@ protected:
typedef GrTBlockList<VaryingInfo> VaryingList;
typedef GrTBlockList<GrShaderVar> VarArray;
typedef GrGLSLProgramDataManager::VaryingHandle VaryingHandle;
VaryingList fVaryings;
VarArray fVertexInputs;

View File

@ -33,12 +33,6 @@ public:
void setMatrix2f(UniformHandle, const float matrix[]) const override;
void setMatrix2fv(UniformHandle, int arrayCount, const float matrices[]) const override;
// for nvpr only
void setPathFragmentInputTransform(VaryingHandle u, int components,
const SkMatrix& matrix) const override {
SK_ABORT("Only supported in NVPR, which is not in Metal");
}
void uploadAndBindUniformBuffers(GrMtlGpu* gpu,
id<MTLRenderCommandEncoder> renderCmdEncoder) const;
void resetDirtyBits();

View File

@ -1,151 +0,0 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/ops/GrDrawPathOp.h"
#include "include/gpu/GrRecordingContext.h"
#include "include/private/SkTemplates.h"
#include "src/gpu/GrAppliedClip.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrMemoryPool.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTarget.h"
#include "src/gpu/GrSurfaceDrawContext.h"
#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
static constexpr GrUserStencilSettings kCoverPass{
GrUserStencilSettings::StaticInit<
0x0000,
GrUserStencilTest::kNotEqual,
0xffff,
GrUserStencilOp::kZero,
GrUserStencilOp::kKeep,
0xffff>()
};
GrDrawPathOpBase::GrDrawPathOpBase(uint32_t classID, const SkMatrix& viewMatrix, GrPaint&& paint,
GrPathRendering::FillType fill, GrAA aa)
: INHERITED(classID)
, fViewMatrix(viewMatrix)
, fInputColor(paint.getColor4f())
, fFillType(fill)
, fDoAA(GrAA::kYes == aa)
, fProcessorSet(std::move(paint)) {}
#if GR_TEST_UTILS
SkString GrDrawPathOp::onDumpInfo() const {
return SkStringPrintf("PATH: 0x%p", fPath.get());
}
#endif
const GrProcessorSet::Analysis& GrDrawPathOpBase::doProcessorAnalysis(
const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
GrClampType clampType) {
fAnalysis = fProcessorSet.finalize(
fInputColor, GrProcessorAnalysisCoverage::kNone, clip, &kCoverPass,
hasMixedSampledCoverage, caps, clampType, &fInputColor);
return fAnalysis;
}
//////////////////////////////////////////////////////////////////////////////
void init_stencil_pass_settings(const GrOpFlushState& flushState,
GrPathRendering::FillType fillType, GrStencilSettings* stencil) {
const GrAppliedClip* appliedClip = flushState.drawOpArgs().appliedClip();
bool stencilClip = appliedClip && appliedClip->hasStencilClip();
GrRenderTarget* rt = flushState.drawOpArgs().rtProxy()->peekRenderTarget();
stencil->reset(GrPathRendering::GetStencilPassSettings(fillType), stencilClip,
rt->numStencilBits());
}
//////////////////////////////////////////////////////////////////////////////
GrOp::Owner GrDrawPathOp::Make(GrRecordingContext* context,
const SkMatrix& viewMatrix,
GrPaint&& paint,
GrAA aa,
sk_sp<const GrPath> path) {
return GrOp::Make<GrDrawPathOp>(context, viewMatrix, std::move(paint), aa, std::move(path));
}
void GrDrawPathOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
GrPipeline::InputFlags pipelineFlags = GrPipeline::InputFlags::kNone;
if (this->doAA()) {
pipelineFlags |= GrPipeline::InputFlags::kHWAntialias;
}
auto pipeline = GrSimpleMeshDrawOpHelper::CreatePipeline(flushState,
this->detachProcessorSet(),
pipelineFlags);
sk_sp<GrPathProcessor> pathProc(GrPathProcessor::Create(this->color(), this->viewMatrix()));
GrProgramInfo programInfo(flushState->writeView(),
pipeline,
&kCoverPass,
pathProc.get(),
GrPrimitiveType::kPath,
0,
flushState->renderPassBarriers(),
flushState->colorLoadOp());
flushState->bindPipelineAndScissorClip(programInfo, this->bounds());
flushState->bindTextures(programInfo.primProc(), nullptr, programInfo.pipeline());
GrStencilSettings stencil;
init_stencil_pass_settings(*flushState, this->fillType(), &stencil);
flushState->gpu()->pathRendering()->drawPath(flushState->rtProxy()->peekRenderTarget(),
programInfo, stencil, fPath.get());
}
//////////////////////////////////////////////////////////////////////////////
inline void pre_translate_transform_values(const float* xforms,
GrPathRendering::PathTransformType type, int count,
SkScalar x, SkScalar y, float* dst) {
if (0 == x && 0 == y) {
memcpy(dst, xforms, count * GrPathRendering::PathTransformSize(type) * sizeof(float));
return;
}
switch (type) {
case GrPathRendering::kNone_PathTransformType:
SK_ABORT("Cannot pre-translate kNone_PathTransformType.");
break;
case GrPathRendering::kTranslateX_PathTransformType:
SkASSERT(0 == y);
for (int i = 0; i < count; i++) {
dst[i] = xforms[i] + x;
}
break;
case GrPathRendering::kTranslateY_PathTransformType:
SkASSERT(0 == x);
for (int i = 0; i < count; i++) {
dst[i] = xforms[i] + y;
}
break;
case GrPathRendering::kTranslate_PathTransformType:
for (int i = 0; i < 2 * count; i += 2) {
dst[i] = xforms[i] + x;
dst[i + 1] = xforms[i + 1] + y;
}
break;
case GrPathRendering::kAffine_PathTransformType:
for (int i = 0; i < 6 * count; i += 6) {
dst[i] = xforms[i];
dst[i + 1] = xforms[i + 1];
dst[i + 2] = xforms[i] * x + xforms[i + 1] * y + xforms[i + 2];
dst[i + 3] = xforms[i + 3];
dst[i + 4] = xforms[i + 4];
dst[i + 5] = xforms[i + 3] * x + xforms[i + 4] * y + xforms[i + 5];
}
break;
default:
SK_ABORT("Unknown transform type.");
break;
}
}

View File

@ -1,106 +0,0 @@
/*
* 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 GrDrawPathOp_DEFINED
#define GrDrawPathOp_DEFINED
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrPath.h"
#include "src/gpu/GrPathProcessor.h"
#include "src/gpu/GrPathRendering.h"
#include "src/gpu/GrProcessorSet.h"
#include "src/gpu/GrStencilSettings.h"
#include "src/gpu/ops/GrDrawOp.h"
class GrPaint;
class GrRecordingContext;
class GrDrawPathOpBase : public GrDrawOp {
protected:
GrDrawPathOpBase(uint32_t classID, const SkMatrix& viewMatrix, GrPaint&&,
GrPathRendering::FillType, GrAA);
FixedFunctionFlags fixedFunctionFlags() const override {
return (fDoAA)
? FixedFunctionFlags::kUsesHWAA | FixedFunctionFlags::kUsesStencil
: FixedFunctionFlags::kUsesStencil;
}
GrProcessorSet::Analysis finalize(
const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
GrClampType clampType) override {
return this->doProcessorAnalysis(caps, clip, hasMixedSampledCoverage, clampType);
}
void visitProxies(const VisitProxyFunc& func) const override {
fProcessorSet.visitProxies(func);
}
protected:
const SkMatrix& viewMatrix() const { return fViewMatrix; }
const SkPMColor4f& color() const { return fInputColor; }
GrPathRendering::FillType fillType() const { return fFillType; }
bool doAA() const { return fDoAA; }
const GrProcessorSet& processors() const { return fProcessorSet; }
GrProcessorSet detachProcessorSet() { return std::move(fProcessorSet); }
const GrProcessorSet::Analysis& doProcessorAnalysis(
const GrCaps&, const GrAppliedClip*, bool hasMixedSampledCoverage, GrClampType);
const GrProcessorSet::Analysis& processorAnalysis() const {
SkASSERT(fAnalysis.isInitialized());
return fAnalysis;
}
private:
void onPrePrepare(GrRecordingContext*,
const GrSurfaceProxyView& writeView,
GrAppliedClip*,
const GrXferProcessor::DstProxyView&,
GrXferBarrierFlags renderPassXferBarriers,
GrLoadOp colorLoadOp) final {}
void onPrepare(GrOpFlushState*) final {}
SkMatrix fViewMatrix;
SkPMColor4f fInputColor;
GrProcessorSet::Analysis fAnalysis;
GrPathRendering::FillType fFillType;
bool fDoAA;
GrProcessorSet fProcessorSet;
using INHERITED = GrDrawOp;
};
class GrDrawPathOp final : public GrDrawPathOpBase {
public:
DEFINE_OP_CLASS_ID
static GrOp::Owner Make(
GrRecordingContext*, const SkMatrix& viewMatrix, GrPaint&&, GrAA, sk_sp<const GrPath>);
const char* name() const override { return "DrawPath"; }
private:
friend class GrOp; // for ctor
GrDrawPathOp(const SkMatrix& viewMatrix, GrPaint&& paint, GrAA aa, sk_sp<const GrPath> path)
: GrDrawPathOpBase(
ClassID(), viewMatrix, std::move(paint), path->getFillType(), aa)
, fPath(std::move(path)) {
this->setTransformedBounds(fPath->getBounds(), viewMatrix, HasAABloat::kNo,
IsHairline::kNo);
}
void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
#if GR_TEST_UTILS
SkString onDumpInfo() const override;
#endif
sk_sp<const GrPath> fPath;
using INHERITED = GrDrawPathOpBase;
};
#endif

View File

@ -1,189 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/gpu/GrRecordingContext.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrPath.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/GrStencilClip.h"
#include "src/gpu/GrStyle.h"
#include "src/gpu/geometry/GrStyledShape.h"
#include "src/gpu/ops/GrDrawPathOp.h"
#include "src/gpu/ops/GrStencilAndCoverPathRenderer.h"
#include "src/gpu/ops/GrStencilPathOp.h"
GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrResourceProvider* resourceProvider,
const GrCaps& caps) {
if (caps.shaderCaps()->pathRenderingSupport() && !caps.avoidStencilBuffers()) {
return new GrStencilAndCoverPathRenderer(resourceProvider);
} else {
return nullptr;
}
}
GrStencilAndCoverPathRenderer::GrStencilAndCoverPathRenderer(GrResourceProvider* resourceProvider)
: fResourceProvider(resourceProvider) {
}
static bool has_matrix(const GrFragmentProcessor& fp) {
if (fp.sampleUsage().hasMatrix()) {
return true;
}
for (int i = fp.numChildProcessors() - 1; i >= 0; --i) {
if (fp.childProcessor(i) && has_matrix(*fp.childProcessor(i))) {
return true;
}
}
return false;
}
GrPathRenderer::CanDrawPath
GrStencilAndCoverPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
SkASSERT(!args.fTargetIsWrappedVkSecondaryCB);
// GrPath doesn't support hairline paths. An arbitrary path effect could produce a hairline
// path.
if (args.fShape->style().strokeRec().isHairlineStyle() ||
args.fShape->style().hasNonDashPathEffect() ||
args.fHasUserStencilSettings ||
!args.fShape->hasUnstyledKey()) {
return CanDrawPath::kNo;
}
if (GrAAType::kCoverage == args.fAAType && !args.fProxy->canUseMixedSamples(*args.fCaps)) {
// We rely on a mixed sampled stencil buffer to implement coverage AA.
return CanDrawPath::kNo;
}
// The lack of vertex shaders means we can't move transform matrices into the vertex shader. We
// could do the transform in the fragment processor, but that would be very slow, so instead we
// just avoid using this path renderer in the face of transformed FPs.
if (args.fPaint && args.fPaint->hasColorFragmentProcessor()) {
if (has_matrix(*args.fPaint->getColorFragmentProcessor())) {
return CanDrawPath::kNo;
}
}
return CanDrawPath::kYes;
}
static sk_sp<GrPath> get_gr_path(GrResourceProvider* resourceProvider, const GrStyledShape& shape) {
GrUniqueKey key;
bool isVolatile;
GrPath::ComputeKey(shape, &key, &isVolatile);
sk_sp<GrPath> path;
if (!isVolatile) {
path = resourceProvider->findByUniqueKey<GrPath>(key);
}
if (!path) {
SkPath skPath;
shape.asPath(&skPath);
path = resourceProvider->createPath(skPath, shape.style());
if (!isVolatile) {
resourceProvider->assignUniqueKeyToResource(key, path.get());
}
} else {
#ifdef SK_DEBUG
SkPath skPath;
shape.asPath(&skPath);
SkASSERT(path->isEqualTo(skPath, shape.style()));
#endif
}
return path;
}
void GrStencilAndCoverPathRenderer::onStencilPath(const StencilPathArgs& args) {
GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
"GrStencilAndCoverPathRenderer::onStencilPath");
sk_sp<GrPath> p(get_gr_path(fResourceProvider, *args.fShape));
args.fRenderTargetContext->stencilPath(args.fClip, args.fDoStencilMSAA, *args.fViewMatrix,
std::move(p));
}
bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) {
GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
"GrStencilAndCoverPathRenderer::onDrawPath");
SkASSERT(!args.fShape->style().strokeRec().isHairlineStyle());
const SkMatrix& viewMatrix = *args.fViewMatrix;
// Any AA will use stencil MSAA
GrAAType stencilAAType = GrAAType::kNone != args.fAAType ? GrAAType::kMSAA : GrAAType::kNone;
sk_sp<GrPath> path(get_gr_path(fResourceProvider, *args.fShape));
if (args.fShape->inverseFilled()) {
SkMatrix vmi;
if (!viewMatrix.invert(&vmi)) {
return true;
}
SkRect devBounds = SkRect::MakeIWH(args.fRenderTargetContext->width(),
args.fRenderTargetContext->height()); // Inverse fill.
// fake inverse with a stencil and cover
GrAppliedClip appliedClip(args.fRenderTargetContext->dimensions());
if (args.fClip && args.fClip->apply(
args.fContext, args.fRenderTargetContext, stencilAAType, true, &appliedClip,
&devBounds) == GrClip::Effect::kClippedOut) {
return true;
}
GrStencilClip stencilClip(args.fRenderTargetContext->dimensions(),
appliedClip.stencilStackID());
if (appliedClip.scissorState().enabled()) {
SkAssertResult(stencilClip.fixedClip().setScissor(appliedClip.scissorState().rect()));
}
if (appliedClip.windowRectsState().enabled()) {
stencilClip.fixedClip().setWindowRectangles(appliedClip.windowRectsState().windows(),
appliedClip.windowRectsState().mode());
}
// Just ignore the analytic FPs (if any) during the stencil pass. They will still clip the
// final draw and it is meaningless to multiply by coverage when drawing to stencil.
args.fRenderTargetContext->stencilPath(&stencilClip, GrAA(stencilAAType == GrAAType::kMSAA),
viewMatrix, std::move(path));
{
static constexpr GrUserStencilSettings kInvertedCoverPass(
GrUserStencilSettings::StaticInit<
0x0000,
// We know our rect will hit pixels outside the clip and the user bits will
// be 0 outside the clip. So we can't just fill where the user bits are 0. We
// also need to check that the clip bit is set.
GrUserStencilTest::kEqualIfInClip,
0xffff,
GrUserStencilOp::kKeep,
GrUserStencilOp::kZero,
0xffff>()
);
SkRect coverBounds;
// mapRect through persp matrix may not be correct
if (!viewMatrix.hasPerspective()) {
vmi.mapRect(&coverBounds, devBounds);
// theoretically could set bloat = 0, instead leave it because of matrix inversion
// precision.
SkScalar bloat = viewMatrix.getMaxScale() * SK_ScalarHalf;
coverBounds.outset(bloat, bloat);
} else {
coverBounds = devBounds;
}
const SkMatrix& coverMatrix = !viewMatrix.hasPerspective() ? viewMatrix : SkMatrix::I();
const SkMatrix& localMatrix = !viewMatrix.hasPerspective() ? SkMatrix::I() : vmi;
// We have to suppress enabling MSAA for mixed samples or we will get seams due to
// coverage modulation along the edge where two triangles making up the rect meet.
GrAA coverAA = GrAA(args.fAAType == GrAAType::kMSAA);
args.fRenderTargetContext->stencilRect(args.fClip, &kInvertedCoverPass,
std::move(args.fPaint), coverAA, coverMatrix,
coverBounds, &localMatrix);
}
} else {
GrOp::Owner op = GrDrawPathOp::Make(
args.fContext, viewMatrix, std::move(args.fPaint),
GrAA(stencilAAType == GrAAType::kMSAA), std::move(path));
args.fRenderTargetContext->addDrawOp(args.fClip, std::move(op));
}
return true;
}

View File

@ -1,45 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrBuiltInPathRenderer_DEFINED
#define GrBuiltInPathRenderer_DEFINED
#include "src/gpu/GrPathRenderer.h"
class GrGpu;
class GrResourceProvider;
/**
* Uses GrGpu::stencilPath followed by a cover rectangle. This subclass doesn't apply AA; it relies
* on the target having MSAA if AA is desired.
*/
class GrStencilAndCoverPathRenderer : public GrPathRenderer {
public:
const char* name() const final { return "NVPR"; }
static GrPathRenderer* Create(GrResourceProvider*, const GrCaps&);
private:
StencilSupport onGetStencilSupport(const GrStyledShape&) const override {
return GrPathRenderer::kStencilOnly_StencilSupport;
}
CanDrawPath onCanDrawPath(const CanDrawPathArgs&) const override;
bool onDrawPath(const DrawPathArgs&) override;
void onStencilPath(const StencilPathArgs&) override;
GrStencilAndCoverPathRenderer(GrResourceProvider*);
GrResourceProvider* fResourceProvider;
using INHERITED = GrPathRenderer;
};
#endif

View File

@ -1,39 +0,0 @@
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/ops/GrStencilPathOp.h"
#include "include/gpu/GrRecordingContext.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrMemoryPool.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTarget.h"
GrOp::Owner GrStencilPathOp::Make(GrRecordingContext* context,
const SkMatrix& viewMatrix,
bool useHWAA,
bool hasStencilClip,
const GrScissorState& scissor,
sk_sp<const GrPath> path) {
return GrOp::Make<GrStencilPathOp>(context, viewMatrix, useHWAA,
hasStencilClip, scissor, std::move(path));
}
void GrStencilPathOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
GrRenderTarget* rt = state->drawOpArgs().rtProxy()->peekRenderTarget();
SkASSERT(rt);
int numStencilBits = rt->numStencilBits();
GrStencilSettings stencil(GrPathRendering::GetStencilPassSettings(fPath->getFillType()),
fHasStencilClip, numStencilBits);
GrPathRendering::StencilPathArgs args(fUseHWAA, state->drawOpArgs().rtProxy(),
state->drawOpArgs().writeView().origin(),
&fViewMatrix, &fScissor, &stencil);
state->gpu()->pathRendering()->stencilPath(args, fPath.get());
}

View File

@ -1,76 +0,0 @@
/*
* 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 GrStencilPathOp_DEFINED
#define GrStencilPathOp_DEFINED
#include "src/gpu/GrPath.h"
#include "src/gpu/GrPathRendering.h"
#include "src/gpu/GrScissorState.h"
#include "src/gpu/GrStencilSettings.h"
#include "src/gpu/ops/GrOp.h"
class GrOpFlushState;
class GrRecordingContext;
class GrStencilPathOp final : public GrOp {
public:
DEFINE_OP_CLASS_ID
static GrOp::Owner Make(GrRecordingContext* context,
const SkMatrix& viewMatrix,
bool useHWAA,
bool hasStencilClip,
const GrScissorState& scissor,
sk_sp<const GrPath> path);
const char* name() const override { return "StencilPathOp"; }
private:
friend class GrOp; // for ctor
GrStencilPathOp(const SkMatrix& viewMatrix,
bool useHWAA,
bool hasStencilClip,
const GrScissorState& scissor,
sk_sp<const GrPath> path)
: INHERITED(ClassID())
, fViewMatrix(viewMatrix)
, fUseHWAA(useHWAA)
, fHasStencilClip(hasStencilClip)
, fScissor(scissor)
, fPath(std::move(path)) {
this->setBounds(fPath->getBounds(), HasAABloat::kNo, IsHairline::kNo);
}
void onPrePrepare(GrRecordingContext*,
const GrSurfaceProxyView& writeView,
GrAppliedClip*,
const GrXferProcessor::DstProxyView&,
GrXferBarrierFlags renderPassXferBarriers,
GrLoadOp colorLoadOp) override {}
void onPrepare(GrOpFlushState*) override {}
void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
#if GR_TEST_UTILS
SkString onDumpInfo() const override {
return SkStringPrintf("Path: 0x%p, AA: %d", fPath.get(), fUseHWAA);
}
#endif
SkMatrix fViewMatrix;
bool fUseHWAA;
bool fHasStencilClip;
GrScissorState fScissor;
sk_sp<const GrPath> fPath;
using INHERITED = GrOp;
};
#endif

View File

@ -17,7 +17,6 @@
#include "include/core/SkSurface.h"
#include "include/effects/SkDashPathEffect.h"
#include "include/gpu/GrDirectContext.h"
#include "src/gpu/GrPath.h"
#include "src/gpu/geometry/GrStyledShape.h"
#include "tests/Test.h"
@ -113,76 +112,3 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(GrDrawCollapsedPath, reporter, ctxInfo) {
surface->getCanvas()->drawPath(path, paint);
surface->flushAndSubmit();
}
DEF_GPUTEST(GrPathKeys, reporter, /* options */) {
SkPaint strokePaint;
strokePaint.setStyle(SkPaint::kStroke_Style);
strokePaint.setStrokeWidth(10.f);
GrStyle styles[] = {
GrStyle::SimpleFill(),
GrStyle::SimpleHairline(),
GrStyle(strokePaint)
};
for (const GrStyle& style : styles) {
// Keys should not ignore conic weights.
SkPath path1, path2;
SkPoint p0 = SkPoint::Make(100, 0);
SkPoint p1 = SkPoint::Make(100, 100);
path1.conicTo(p0, p1, .5f);
path2.conicTo(p0, p1, .7f);
GrUniqueKey key1, key2;
// We expect these small paths to be keyed based on their data.
bool isVolatile;
GrPath::ComputeKey(GrStyledShape(path1, GrStyle::SimpleFill()), &key1, &isVolatile);
REPORTER_ASSERT(reporter, !isVolatile);
REPORTER_ASSERT(reporter, key1.isValid());
GrPath::ComputeKey(GrStyledShape(path2, GrStyle::SimpleFill()), &key2, &isVolatile);
REPORTER_ASSERT(reporter, !isVolatile);
REPORTER_ASSERT(reporter, key1.isValid());
REPORTER_ASSERT(reporter, key1 != key2);
{
GrUniqueKey tempKey;
path1.setIsVolatile(true);
GrPath::ComputeKey(GrStyledShape(path1, style), &key1, &isVolatile);
REPORTER_ASSERT(reporter, isVolatile);
REPORTER_ASSERT(reporter, !tempKey.isValid());
}
// Ensure that recreating the GrStyledShape doesn't change the key.
{
GrUniqueKey tempKey;
GrPath::ComputeKey(GrStyledShape(path2, GrStyle::SimpleFill()), &tempKey, &isVolatile);
REPORTER_ASSERT(reporter, key2 == tempKey);
}
// Try a large path that is too big to be keyed off its data.
SkPath path3;
SkPath path4;
for (int i = 0; i < 1000; ++i) {
SkScalar s = SkIntToScalar(i);
path3.conicTo(s, 3.f * s / 4, s + 1.f, s, 0.5f + s / 2000.f);
path4.conicTo(s, 3.f * s / 4, s + 1.f, s, 0.3f + s / 2000.f);
}
GrUniqueKey key3, key4;
// These aren't marked volatile and so should have keys
GrPath::ComputeKey(GrStyledShape(path3, style), &key3, &isVolatile);
REPORTER_ASSERT(reporter, !isVolatile);
REPORTER_ASSERT(reporter, key3.isValid());
GrPath::ComputeKey(GrStyledShape(path4, style), &key4, &isVolatile);
REPORTER_ASSERT(reporter, !isVolatile);
REPORTER_ASSERT(reporter, key4.isValid());
REPORTER_ASSERT(reporter, key3 != key4);
{
GrUniqueKey tempKey;
path3.setIsVolatile(true);
GrPath::ComputeKey(GrStyledShape(path3, style), &key1, &isVolatile);
REPORTER_ASSERT(reporter, isVolatile);
REPORTER_ASSERT(reporter, !tempKey.isValid());
}
}
}

View File

@ -44,8 +44,6 @@ static GpuPathRenderers get_named_pathrenderers_flags(const char* name) {
return GpuPathRenderers::kNone;
} else if (!strcmp(name, "dashline")) {
return GpuPathRenderers::kDashLine;
} else if (!strcmp(name, "nvpr")) {
return GpuPathRenderers::kStencilAndCover;
} else if (!strcmp(name, "ccpr")) {
return GpuPathRenderers::kCoverageCounting;
} else if (!strcmp(name, "aahairline")) {

View File

@ -531,27 +531,42 @@
],
},
{
"GL": [{"ext": "GL_NV_path_rendering"}],
"GLES": [{"ext": "GL_CHROMIUM_path_rendering"},
{"ext": "GL_NV_path_rendering"}],
"GL": [ { "ext": "GL_NV_path_rendering" } ],
"GLES": [
{ "ext": "GL_CHROMIUM_path_rendering" },
{ "ext": "GL_NV_path_rendering" }
],
"WebGL": null,
"functions": [
"CoverFillPath", "CoverFillPathInstanced", "CoverStrokePath",
"CoverStrokePathInstanced", "DeletePaths", "GenPaths",
"IsPath", "PathCommands", "PathParameterf", "PathParameteri",
"PathStencilFunc", "ProgramPathFragmentInputGen", "StencilFillPath",
"StencilFillPathInstanced", "StencilStrokePath", "StencilStrokePathInstanced",
"StencilThenCoverFillPath", "StencilThenCoverFillPathInstanced",
"StencilThenCoverStrokePath", "StencilThenCoverStrokePathInstanced",
"CoverFillPath",
"CoverFillPathInstanced",
"CoverStrokePath",
"CoverStrokePathInstanced",
"DeletePaths",
"GenPaths",
"IsPath",
"PathCommands",
"PathParameterf",
"PathParameteri",
"PathStencilFunc",
"ProgramPathFragmentInputGen",
"StencilFillPath",
"StencilFillPathInstanced",
"StencilStrokePath",
"StencilStrokePathInstanced",
"StencilThenCoverFillPath",
"StencilThenCoverFillPathInstanced",
"StencilThenCoverStrokePath",
"StencilThenCoverStrokePathInstanced",
],
// List of functions that Skia uses, but which have been added since the initial release
// of NV_path_rendering driver. We do not want to fail interface validation due to
// missing features, we will just not use the extension.
// If one updates this list, then update GrGLCaps::hasPathRenderingSupport too.
// TODO: remove these functions. Since Skia no longer supports NV_path_rendering
// these will never be used.
"optional": [
"ProgramPathFragmentInputGen", "StencilThenCoverFillPath",
"StencilThenCoverFillPathInstanced", "StencilThenCoverStrokePath",
"ProgramPathFragmentInputGen",
"StencilThenCoverFillPath",
"StencilThenCoverFillPathInstanced",
"StencilThenCoverStrokePath",
"StencilThenCoverStrokePathInstanced",
],
},

View File

@ -341,7 +341,6 @@ Viewer::Viewer(int argc, char** argv, void* platformData)
gPathRendererNames[GpuPathRenderers::kDefault] = "Default Path Renderers";
gPathRendererNames[GpuPathRenderers::kTessellation] = "Tessellation";
gPathRendererNames[GpuPathRenderers::kStencilAndCover] = "NV_path_rendering";
gPathRendererNames[GpuPathRenderers::kSmall] = "Small paths (cached sdf or alpha masks)";
gPathRendererNames[GpuPathRenderers::kCoverageCounting] = "CCPR";
gPathRendererNames[GpuPathRenderers::kTriangulating] = "Triangulating";
@ -1913,9 +1912,6 @@ void Viewer::drawImGui() {
if (GrTessellationPathRenderer::IsSupported(*caps)) {
prButton(GpuPathRenderers::kTessellation);
}
if (caps->shaderCaps()->pathRenderingSupport()) {
prButton(GpuPathRenderers::kStencilAndCover);
}
}
if (1 == fWindow->sampleCount()) {
if (GrCoverageCountingPathRenderer::IsSupported(*caps)) {
@ -2738,10 +2734,6 @@ void Viewer::updateUIState() {
writer.appendString(
gPathRendererNames[GpuPathRenderers::kTessellation].c_str());
}
if (caps->shaderCaps()->pathRenderingSupport()) {
writer.appendString(
gPathRendererNames[GpuPathRenderers::kStencilAndCover].c_str());
}
}
if (1 == fWindow->sampleCount()) {
if(GrCoverageCountingPathRenderer::IsSupported(*caps)) {