diff options
-rw-r--r-- | bench/nanobench.cpp | 6 | ||||
-rw-r--r-- | dm/DM.cpp | 28 | ||||
-rw-r--r-- | example/SkiaSDLExample.cpp | 4 | ||||
-rw-r--r-- | gm/pathmaskcache.cpp | 2 | ||||
-rw-r--r-- | include/gpu/GrContextOptions.h | 40 | ||||
-rw-r--r-- | include/gpu/gl/GrGLInterface.h | 4 | ||||
-rw-r--r-- | samplecode/SampleApp.cpp | 46 | ||||
-rw-r--r-- | samplecode/SampleApp.h | 18 | ||||
-rw-r--r-- | src/gpu/GrContext.cpp | 3 | ||||
-rw-r--r-- | src/gpu/GrPathRendererChain.cpp | 69 | ||||
-rw-r--r-- | src/gpu/GrPathRendererChain.h | 12 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGLInterface.cpp | 31 | ||||
-rw-r--r-- | tools/flags/SkCommonFlagsPathRenderer.h | 74 | ||||
-rw-r--r-- | tools/gpu/GrContextFactory.cpp | 9 | ||||
-rw-r--r-- | tools/skpbench/skpbench.cpp | 6 | ||||
-rw-r--r-- | tools/viewer/Viewer.cpp | 3 | ||||
-rw-r--r-- | tools/viewer/sk_app/GLWindowContext.cpp | 12 | ||||
-rw-r--r-- | tools/viewer/sk_app/VulkanWindowContext.cpp | 6 |
19 files changed, 236 insertions, 141 deletions
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp index e97e9a0bf3..f73ae464cc 100644 --- a/bench/nanobench.cpp +++ b/bench/nanobench.cpp @@ -33,6 +33,7 @@ #include "SkCodec.h" #include "SkCommonFlags.h" #include "SkCommonFlagsConfig.h" +#include "SkCommonFlagsPathRenderer.h" #include "SkData.h" #include "SkGraphics.h" #include "SkLeanWindows.h" @@ -128,6 +129,10 @@ DEFINE_string(sourceType, "", DEFINE_string(benchType, "", "Apply usual --match rules to bench type: micro, recording, piping, playback, skcodec, etc."); +#if SK_SUPPORT_GPU +DEFINE_pathrenderer_flag; +#endif + static double now_ms() { return SkTime::GetNSecs() * 1e-6; } static SkString humanize(double ms) { @@ -1106,6 +1111,7 @@ int main(int argc, char** argv) { #if SK_SUPPORT_GPU GrContextOptions grContextOpts; + grContextOpts.fGpuPathRenderers = CollectGpuPathRenderersFromFlags(); gGrFactory.reset(new GrContextFactory(grContextOpts)); #endif @@ -16,6 +16,7 @@ #include "SkColorSpace.h" #include "SkCommonFlags.h" #include "SkCommonFlagsConfig.h" +#include "SkCommonFlagsPathRenderer.h" #include "SkData.h" #include "SkFontMgr.h" #include "SkGraphics.h" @@ -77,6 +78,10 @@ DEFINE_int32(shard, 0, "Which shard do I run?"); DEFINE_string(mskps, "", "Directory to read mskps from, or a single mskp file."); +#if SK_SUPPORT_GPU +DEFINE_pathrenderer_flag; +#endif + using namespace DM; using sk_gpu_test::GrContextFactory; using sk_gpu_test::GLTestContext; @@ -838,13 +843,13 @@ static bool gpu_supported() { #endif } -static Sink* create_sink(const SkCommandLineConfig* config) { +static Sink* create_sink(const GrContextOptions& grCtxOptions, const SkCommandLineConfig* config) { #if SK_SUPPORT_GPU if (gpu_supported()) { if (const SkCommandLineConfigGpu* gpuConfig = config->asConfigGpu()) { GrContextFactory::ContextType contextType = gpuConfig->getContextType(); GrContextFactory::ContextOverrides contextOverrides = gpuConfig->getContextOverrides(); - GrContextFactory testFactory; + GrContextFactory testFactory(grCtxOptions); if (!testFactory.get(contextType, contextOverrides)) { info("WARNING: can not create GPU context for config '%s'. " "GM tests will be skipped.\n", gpuConfig->getTag().c_str()); @@ -911,12 +916,12 @@ static Sink* create_via(const SkString& tag, Sink* wrapped) { return nullptr; } -static bool gather_sinks() { +static bool gather_sinks(const GrContextOptions& grCtxOptions) { SkCommandLineConfigArray configs; ParseConfigs(FLAGS_config, &configs); for (int i = 0; i < configs.count(); i++) { const SkCommandLineConfig& config = *configs[i]; - Sink* sink = create_sink(&config); + Sink* sink = create_sink(grCtxOptions, &config); if (sink == nullptr) { info("Skipping config %s: Don't understand '%s'.\n", config.getTag().c_str(), config.getTag().c_str()); @@ -1233,7 +1238,7 @@ static void gather_tests() { } } -static void run_test(skiatest::Test test) { +static void run_test(skiatest::Test test, const GrContextOptions& grCtxOptions) { struct : public skiatest::Reporter { void reportFailed(const skiatest::Failure& failure) override { fail(failure.toString()); @@ -1247,7 +1252,7 @@ static void run_test(skiatest::Test test) { if (!FLAGS_dryRun && !is_blacklisted("_", "tests", "_", test.name)) { start("unit", "test", "", test.name); - GrContextFactory factory; + GrContextFactory factory(grCtxOptions); test.proc(&reporter, &factory); } done("unit", "test", "", test.name); @@ -1307,6 +1312,11 @@ int main(int argc, char** argv) { gVLog = fopen(SkOSPath::Join(FLAGS_writePath[0], "verbose.log").c_str(), "w"); } + GrContextOptions grCtxOptions; +#if SK_SUPPORT_GPU + grCtxOptions.fGpuPathRenderers = CollectGpuPathRenderersFromFlags(); +#endif + JsonWriter::DumpJson(); // It's handy for the bots to assume this is ~never missing. SkAutoGraphics ag; SkTaskGroup::Enabler enabled(FLAGS_threads); @@ -1325,7 +1335,7 @@ int main(int argc, char** argv) { if (!gather_srcs()) { return 1; } - if (!gather_sinks()) { + if (!gather_sinks(grCtxOptions)) { return 1; } gather_tests(); @@ -1356,12 +1366,12 @@ int main(int argc, char** argv) { } } for (auto test : gParallelTests) { - parallel.add([test] { run_test(test); }); + parallel.add([test, grCtxOptions] { run_test(test, grCtxOptions); }); } // With the parallel work running, run serial tasks and tests here on main thread. for (auto task : serial) { Task::Run(task); } - for (auto test : gSerialTests) { run_test(test); } + for (auto test : gSerialTests) { run_test(test, grCtxOptions); } // Wait for any remaining parallel work to complete (including any spun off of serial tasks). parallel.wait(); diff --git a/example/SkiaSDLExample.cpp b/example/SkiaSDLExample.cpp index 3aa42b3518..abd198afe9 100644 --- a/example/SkiaSDLExample.cpp +++ b/example/SkiaSDLExample.cpp @@ -185,10 +185,6 @@ int main(int argc, char** argv) { // setup GrContext sk_sp<const GrGLInterface> interface(GrGLCreateNativeInterface()); - // To use NVPR, comment this out - interface.reset(GrGLInterfaceRemoveNVPR(interface)); - SkASSERT(interface); - // setup contexts sk_sp<GrContext> grContext(GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)interface.get())); diff --git a/gm/pathmaskcache.cpp b/gm/pathmaskcache.cpp index 21397f077d..5e3232b6bd 100644 --- a/gm/pathmaskcache.cpp +++ b/gm/pathmaskcache.cpp @@ -104,7 +104,7 @@ protected: } void modifyGrContextOptions(GrContextOptions* options) override { - options->fForceSWPathMasks = true; + options->fGpuPathRenderers = GrContextOptions::GpuPathRenderers::kNone; options->fAllowPathMaskCaching = true; } diff --git a/include/gpu/GrContextOptions.h b/include/gpu/GrContextOptions.h index a2e4288c66..6c42ec66ad 100644 --- a/include/gpu/GrContextOptions.h +++ b/include/gpu/GrContextOptions.h @@ -9,6 +9,7 @@ #define GrContextOptions_DEFINED #include "SkTypes.h" +#include "GrTypes.h" struct GrContextOptions { GrContextOptions() {} @@ -61,10 +62,6 @@ struct GrContextOptions { Instanced rendering is still experimental at this point and disabled by default. */ bool fEnableInstancedRendering = false; - /** Disables distance field rendering for paths. Distance field computation can be expensive - and yields no benefit if a path is not rendered multiple times with different transforms */ - bool fDisableDistanceFieldPaths = false; - /** * If true this allows path mask textures to be cached. This is only really useful if paths * are commonly rendered at the same scale and fractional translation. @@ -72,13 +69,6 @@ struct GrContextOptions { bool fAllowPathMaskCaching = false; /** - * Force all path draws to go through through the sw-rasterize-to-texture code path (assuming - * the path is not recognized as a simpler shape (e.g. a rrect). This is intended for testing - * purposes. - */ - bool fForceSWPathMasks = false; - - /** * If true, sRGB support will not be enabled unless sRGB decoding can be disabled (via an * extension). If mixed use of "legacy" mode and sRGB/color-correct mode is not required, this * can be set to false, which will significantly expand the number of devices that qualify for @@ -91,6 +81,34 @@ struct GrContextOptions { * textures from codec-backed images. */ bool fDisableGpuYUVConversion = false; + + /** + * If true, the caps will never report driver support for path rendering. + */ + bool fSuppressPathRendering = false; + + /** + * Allows the client to include or exclude specific GPU path renderers. + */ + enum class GpuPathRenderers { + kNone = 0, // Always use sofware masks. + kDashLine = 1 << 0, + kStencilAndCover = 1 << 1, + kMSAA = 1 << 2, + kAAHairline = 1 << 3, + kAAConvex = 1 << 4, + kAALinearizing = 1 << 5, + kPLS = 1 << 6, + kDistanceField = 1 << 7, + kTesselating = 1 << 8, + kDefault = 1 << 9, + + kAll = kDefault | (kDefault - 1) + }; + + GpuPathRenderers fGpuPathRenderers = GpuPathRenderers::kAll; }; +GR_MAKE_BITFIELD_CLASS_OPS(GrContextOptions::GpuPathRenderers) + #endif diff --git a/include/gpu/gl/GrGLInterface.h b/include/gpu/gl/GrGLInterface.h index 3afa6be9fd..cce1cb546b 100644 --- a/include/gpu/gl/GrGLInterface.h +++ b/include/gpu/gl/GrGLInterface.h @@ -55,10 +55,6 @@ typedef intptr_t GrGLInterfaceCallbackData; */ const SK_API GrGLInterface* GrGLCreateNullInterface(bool enableNVPR = false); -/** Function that returns a new interface identical to "interface" but without support for - GL_NV_path_rendering. */ -const GrGLInterface* GrGLInterfaceRemoveNVPR(const GrGLInterface*); - /** Function that returns a new interface identical to "interface" but with support for test version of GL_EXT_debug_marker. */ const GrGLInterface* GrGLInterfaceAddTestDebugMarker(const GrGLInterface*, diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp index 8b5e074173..1aac794ddd 100644 --- a/samplecode/SampleApp.cpp +++ b/samplecode/SampleApp.cpp @@ -14,6 +14,7 @@ #include "SkCanvas.h" #include "SkColorSpace_XYZ.h" #include "SkCommandLineFlags.h" +#include "SkCommonFlagsPathRenderer.h" #include "SkData.h" #include "SkDocument.h" #include "SkGraphics.h" @@ -208,7 +209,7 @@ public: #endif } - void setUpBackend(SampleWindow* win, int msaaSampleCount, bool deepColor) override { + void setUpBackend(SampleWindow* win, const BackendOptions& backendOptions) override { SkASSERT(kNone_BackEndType == fBackend); fBackend = kNone_BackEndType; @@ -231,27 +232,27 @@ public: break; } AttachmentInfo attachmentInfo; - bool result = win->attach(fBackend, msaaSampleCount, deepColor, &attachmentInfo); + bool result = win->attach(fBackend, backendOptions.fMSAASampleCount, + backendOptions.fDeepColor, &attachmentInfo); if (!result) { SkDebugf("Failed to initialize GL"); return; } - fMSAASampleCount = msaaSampleCount; - fDeepColor = deepColor; + fMSAASampleCount = backendOptions.fMSAASampleCount; + fDeepColor = backendOptions.fDeepColor; // Assume that we have at least 24-bit output, for backends that don't supply this data fActualColorBits = SkTMax(attachmentInfo.fColorBits, 24); SkASSERT(nullptr == fCurIntf); - sk_sp<const GrGLInterface> glInterface; switch (win->getDeviceType()) { case kRaster_DeviceType: // fallthrough case kGPU_DeviceType: // all these guys use the native interface - glInterface.reset(GrGLCreateNativeInterface()); + fCurIntf = GrGLCreateNativeInterface(); break; #if SK_ANGLE case kANGLE_DeviceType: - glInterface.reset(sk_gpu_test::CreateANGLEGLInterface()); + fCurIntf = sk_gpu_test::CreateANGLEGLInterface(); break; #endif // SK_ANGLE default: @@ -259,12 +260,9 @@ public: break; } - // Currently SampleApp does not use NVPR. TODO: Provide an NVPR device type that is skipped - // when the driver doesn't support NVPR. - fCurIntf = GrGLInterfaceRemoveNVPR(glInterface.get()); - SkASSERT(nullptr == fCurContext); - fCurContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext) fCurIntf); + fCurContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext) fCurIntf, + backendOptions.fGrContextOptions); if (nullptr == fCurContext || nullptr == fCurIntf) { // We need some context and interface to see results @@ -723,8 +721,6 @@ static void restrict_samples(SkTDArray<const SkViewFactory*>& factories, const S } DEFINE_string(slide, "", "Start on this sample."); -DEFINE_int32(msaa, 0, "Request multisampling with this count."); -DEFINE_bool(deepColor, false, "Request deep color (10-bit/channel or more) display buffer."); DEFINE_string(pictureDir, "", "Read pictures from here."); DEFINE_string(picture, "", "Path to single picture."); DEFINE_string(svg, "", "Path to single SVG file."); @@ -737,6 +733,11 @@ DEFINE_bool(redraw, false, "Force continuous redrawing, for profiling or debuggi #ifdef SAMPLE_PDF_FILE_VIEWER DEFINE_string(pdfPath, "", "Path to direcotry of pdf files."); #endif +#if SK_SUPPORT_GPU +DEFINE_pathrenderer_flag; +DEFINE_int32(msaa, 0, "Request multisampling with this count."); +DEFINE_bool(deepColor, false, "Request deep color (10-bit/channel or more) display buffer."); +#endif #include "SkTaskGroup.h" @@ -826,8 +827,11 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev } } - fMSAASampleCount = FLAGS_msaa; - fDeepColor = FLAGS_deepColor; +#if SK_SUPPORT_GPU + fBackendOptions.fGrContextOptions.fGpuPathRenderers = CollectGpuPathRenderersFromFlags(); + fBackendOptions.fMSAASampleCount = FLAGS_msaa; + fBackendOptions.fDeepColor = FLAGS_deepColor; +#endif fColorConfigIndex = 0; if (FLAGS_list) { @@ -996,7 +1000,7 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev devManager->ref(); fDevManager = devManager; } - fDevManager->setUpBackend(this, fMSAASampleCount, fDeepColor); + fDevManager->setUpBackend(this, fBackendOptions); // If another constructor set our dimensions, ensure that our // onSizeChange gets called. @@ -1916,7 +1920,7 @@ void SampleWindow::setDeviceType(DeviceType type) { fDevManager->tearDownBackend(this); fDeviceType = type; - fDevManager->setUpBackend(this, fMSAASampleCount, fDeepColor); + fDevManager->setUpBackend(this, fBackendOptions); this->updateTitle(); this->inval(nullptr); @@ -1926,7 +1930,7 @@ void SampleWindow::setDeviceColorType(SkColorType ct, sk_sp<SkColorSpace> cs) { this->setColorType(ct, std::move(cs)); fDevManager->tearDownBackend(this); - fDevManager->setUpBackend(this, fMSAASampleCount, fDeepColor); + fDevManager->setUpBackend(this, fBackendOptions); this->updateTitle(); this->inval(nullptr); @@ -1953,7 +1957,7 @@ void SampleWindow::toggleFPS() { void SampleWindow::toggleDistanceFieldFonts() { // reset backend fDevManager->tearDownBackend(this); - fDevManager->setUpBackend(this, fMSAASampleCount, fDeepColor); + fDevManager->setUpBackend(this, fBackendOptions); SkSurfaceProps props = this->getSurfaceProps(); uint32_t flags = props.flags() ^ SkSurfaceProps::kUseDeviceIndependentFonts_Flag; @@ -1966,7 +1970,7 @@ void SampleWindow::toggleDistanceFieldFonts() { void SampleWindow::setPixelGeometry(int pixelGeometryIndex) { // reset backend fDevManager->tearDownBackend(this); - fDevManager->setUpBackend(this, fMSAASampleCount, fDeepColor); + fDevManager->setUpBackend(this, fBackendOptions); const SkSurfaceProps& oldProps = this->getSurfaceProps(); SkSurfaceProps newProps(oldProps.flags(), SkSurfaceProps::kLegacyFontHost_InitType); diff --git a/samplecode/SampleApp.h b/samplecode/SampleApp.h index c52541d409..7b0dbf4942 100644 --- a/samplecode/SampleApp.h +++ b/samplecode/SampleApp.h @@ -22,6 +22,10 @@ #include "SkPipe.h" +#if SK_SUPPORT_GPU +#include "GrContextOptions.h" +#endif + class GrContext; class GrRenderTarget; @@ -70,9 +74,15 @@ public: */ class DeviceManager : public SkRefCnt { public: + struct BackendOptions { +#if SK_SUPPORT_GPU + GrContextOptions fGrContextOptions; + int fMSAASampleCount; + bool fDeepColor; +#endif + }; - - virtual void setUpBackend(SampleWindow* win, int msaaSampleCount, bool deepColor) = 0; + virtual void setUpBackend(SampleWindow* win, const BackendOptions&) = 0; virtual void tearDownBackend(SampleWindow* win) = 0; @@ -219,8 +229,8 @@ private: int fFilterQualityIndex; unsigned fFlipAxis; - int fMSAASampleCount; - bool fDeepColor; + DeviceManager::BackendOptions fBackendOptions; + int fColorConfigIndex; SkScalar fZoomCenterX, fZoomCenterY; diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 8460702a44..4b1324e33e 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -99,9 +99,8 @@ void GrContext::initCommon(const GrContextOptions& options) { rtOpListOptions.fMaxOpCombineLookback = options.fMaxOpCombineLookback; rtOpListOptions.fMaxOpCombineLookahead = options.fMaxOpCombineLookahead; GrPathRendererChain::Options prcOptions; - prcOptions.fDisableDistanceFieldRenderer = options.fDisableDistanceFieldPaths; prcOptions.fAllowPathMaskCaching = options.fAllowPathMaskCaching; - prcOptions.fDisableAllPathRenderers = options.fForceSWPathMasks; + prcOptions.fGpuPathRenderers = options.fGpuPathRenderers; fDrawingManager.reset(new GrDrawingManager(this, rtOpListOptions, prcOptions, options.fImmediateMode, &fSingleOwner)); diff --git a/src/gpu/GrPathRendererChain.cpp b/src/gpu/GrPathRendererChain.cpp index c0cac80dff..4b4ae26d6a 100644 --- a/src/gpu/GrPathRendererChain.cpp +++ b/src/gpu/GrPathRendererChain.cpp @@ -26,44 +26,49 @@ #include "ops/GrTessellatingPathRenderer.h" GrPathRendererChain::GrPathRendererChain(GrContext* context, const Options& options) { - if (!options.fDisableAllPathRenderers) { - const GrCaps& caps = *context->caps(); - this->addPathRenderer(new GrDashLinePathRenderer)->unref(); - - if (GrPathRenderer* pr = GrStencilAndCoverPathRenderer::Create(context->resourceProvider(), - caps)) { - this->addPathRenderer(pr)->unref(); + using GpuPathRenderers = GrContextOptions::GpuPathRenderers; + const GrCaps& caps = *context->caps(); + if (options.fGpuPathRenderers & GpuPathRenderers::kDashLine) { + fChain.push_back(sk_make_sp<GrDashLinePathRenderer>()); + } + if (options.fGpuPathRenderers & GpuPathRenderers::kStencilAndCover) { + sk_sp<GrPathRenderer> pr( + GrStencilAndCoverPathRenderer::Create(context->resourceProvider(), caps)); + if (pr) { + fChain.push_back(std::move(pr)); } - #ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK + } +#ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK + if (options.fGpuPathRenderers & GpuPathRenderers::kMSAA) { if (caps.sampleShadingSupport()) { - this->addPathRenderer(new GrMSAAPathRenderer)->unref(); + fChain.push_back(sk_make_sp<GrMSAAPathRenderer>()); } - #endif - this->addPathRenderer(new GrAAHairLinePathRenderer)->unref(); - this->addPathRenderer(new GrAAConvexPathRenderer)->unref(); - this->addPathRenderer(new GrAALinearizingConvexPathRenderer)->unref(); + } +#endif + if (options.fGpuPathRenderers & GpuPathRenderers::kAAHairline) { + fChain.push_back(sk_make_sp<GrAAHairLinePathRenderer>()); + } + if (options.fGpuPathRenderers & GpuPathRenderers::kAAConvex) { + fChain.push_back(sk_make_sp<GrAAConvexPathRenderer>()); + } + if (options.fGpuPathRenderers & GpuPathRenderers::kAALinearizing) { + fChain.push_back(sk_make_sp<GrAALinearizingConvexPathRenderer>()); + } + if (options.fGpuPathRenderers & GpuPathRenderers::kPLS) { if (caps.shaderCaps()->plsPathRenderingSupport()) { - this->addPathRenderer(new GrPLSPathRenderer)->unref(); - } - if (!options.fDisableDistanceFieldRenderer) { - this->addPathRenderer(new GrAADistanceFieldPathRenderer)->unref(); + fChain.push_back(sk_make_sp<GrPLSPathRenderer>()); } - this->addPathRenderer(new GrTessellatingPathRenderer)->unref(); - this->addPathRenderer(new GrDefaultPathRenderer(caps.twoSidedStencilSupport(), - caps.stencilWrapOpsSupport()))->unref(); } -} - -GrPathRendererChain::~GrPathRendererChain() { - for (int i = 0; i < fChain.count(); ++i) { - fChain[i]->unref(); + if (options.fGpuPathRenderers & GpuPathRenderers::kDistanceField) { + fChain.push_back(sk_make_sp<GrAADistanceFieldPathRenderer>()); + } + if (options.fGpuPathRenderers & GpuPathRenderers::kTesselating) { + fChain.push_back(sk_make_sp<GrTessellatingPathRenderer>()); + } + if (options.fGpuPathRenderers & GpuPathRenderers::kDefault) { + fChain.push_back(sk_make_sp<GrDefaultPathRenderer>(caps.twoSidedStencilSupport(), + caps.stencilWrapOpsSupport())); } -} - -GrPathRenderer* GrPathRendererChain::addPathRenderer(GrPathRenderer* pr) { - fChain.push_back() = pr; - pr->ref(); - return pr; } GrPathRenderer* GrPathRendererChain::getPathRenderer( @@ -99,7 +104,7 @@ GrPathRenderer* GrPathRendererChain::getPathRenderer( *stencilSupport = support; } } - return fChain[i]; + return fChain[i].get(); } } return nullptr; diff --git a/src/gpu/GrPathRendererChain.h b/src/gpu/GrPathRendererChain.h index 9a1a8fe108..c0a0ee39f5 100644 --- a/src/gpu/GrPathRendererChain.h +++ b/src/gpu/GrPathRendererChain.h @@ -10,6 +10,7 @@ #include "GrPathRenderer.h" +#include "GrContextOptions.h" #include "SkTypes.h" #include "SkTArray.h" @@ -24,14 +25,12 @@ class GrContext; class GrPathRendererChain : public SkNoncopyable { public: struct Options { - bool fDisableDistanceFieldRenderer = false; + using GpuPathRenderers = GrContextOptions::GpuPathRenderers; bool fAllowPathMaskCaching = false; - bool fDisableAllPathRenderers = false; + GpuPathRenderers fGpuPathRenderers = GpuPathRenderers::kAll; }; GrPathRendererChain(GrContext* context, const Options&); - ~GrPathRendererChain(); - /** Documents how the caller plans to use a GrPathRenderer to draw a path. It affects the PR returned by getPathRenderer */ enum class DrawType { @@ -49,13 +48,10 @@ public: GrPathRenderer::StencilSupport* stencilSupport); private: - // takes a ref and unrefs in destructor - GrPathRenderer* addPathRenderer(GrPathRenderer* pr); - enum { kPreAllocCount = 8, }; - SkSTArray<kPreAllocCount, GrPathRenderer*, true> fChain; + SkSTArray<kPreAllocCount, sk_sp<GrPathRenderer>> fChain; }; #endif diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index 4c252215a9..370fb0713b 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -258,7 +258,9 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, this->initGLSL(ctxInfo); GrShaderCaps* shaderCaps = fShaderCaps.get(); - shaderCaps->fPathRenderingSupport = this->hasPathRenderingSupport(ctxInfo, gli); + if (!contextOptions.fSuppressPathRendering) { + shaderCaps->fPathRenderingSupport = this->hasPathRenderingSupport(ctxInfo, gli); + } // For now these two are equivalent but we could have dst read in shader via some other method. // Before setting this, initGLSL() must have been called. diff --git a/src/gpu/gl/GrGLInterface.cpp b/src/gpu/gl/GrGLInterface.cpp index 45d84add8d..3714dcb86e 100644 --- a/src/gpu/gl/GrGLInterface.cpp +++ b/src/gpu/gl/GrGLInterface.cpp @@ -29,37 +29,6 @@ const GrGLInterface* GrGLInterfaceAddTestDebugMarker(const GrGLInterface* interf return newInterface; } -const GrGLInterface* GrGLInterfaceRemoveNVPR(const GrGLInterface* interface) { - GrGLInterface* newInterface = GrGLInterface::NewClone(interface); - - newInterface->fExtensions.remove("GL_NV_path_rendering"); - newInterface->fExtensions.remove("GL_CHROMIUM_path_rendering"); - newInterface->fFunctions.fMatrixLoadf = nullptr; - newInterface->fFunctions.fMatrixLoadIdentity = nullptr; - newInterface->fFunctions.fPathCommands = nullptr; - newInterface->fFunctions.fPathParameteri = nullptr; - newInterface->fFunctions.fPathParameterf = nullptr; - newInterface->fFunctions.fGenPaths = nullptr; - newInterface->fFunctions.fDeletePaths = nullptr; - newInterface->fFunctions.fIsPath = nullptr; - newInterface->fFunctions.fPathStencilFunc = nullptr; - newInterface->fFunctions.fStencilFillPath = nullptr; - newInterface->fFunctions.fStencilStrokePath = nullptr; - newInterface->fFunctions.fStencilFillPathInstanced = nullptr; - newInterface->fFunctions.fStencilStrokePathInstanced = nullptr; - newInterface->fFunctions.fCoverFillPath = nullptr; - newInterface->fFunctions.fCoverStrokePath = nullptr; - newInterface->fFunctions.fCoverFillPathInstanced = nullptr; - newInterface->fFunctions.fCoverStrokePathInstanced = nullptr; - newInterface->fFunctions.fStencilThenCoverFillPath = nullptr; - newInterface->fFunctions.fStencilThenCoverStrokePath = nullptr; - newInterface->fFunctions.fStencilThenCoverFillPathInstanced = nullptr; - newInterface->fFunctions.fStencilThenCoverStrokePathInstanced = nullptr; - newInterface->fFunctions.fProgramPathFragmentInputGen = nullptr; - newInterface->fFunctions.fBindFragmentInputLocation = nullptr; - return newInterface; -} - GrGLInterface::GrGLInterface() { fStandard = kNone_GrGLStandard; } diff --git a/tools/flags/SkCommonFlagsPathRenderer.h b/tools/flags/SkCommonFlagsPathRenderer.h new file mode 100644 index 0000000000..d3b80f545f --- /dev/null +++ b/tools/flags/SkCommonFlagsPathRenderer.h @@ -0,0 +1,74 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SK_COMMON_FLAGS_PATH_RENDERER_H +#define SK_COMMON_FLAGS_PATH_RENDERER_H + +#if SK_SUPPORT_GPU + +#include "GrContextFactory.h" +#include "SkCommandLineFlags.h" +#include "SkTypes.h" + +DECLARE_string(pr); + +#define DEFINE_pathrenderer_flag \ + DEFINE_string(pr, "all", \ + "Set of enabled gpu path renderers. Defined as a list of: " \ + "[[~]all [~]dashline [~]nvpr [~]msaa [~]aahairline [~]aaconvex " \ + "[~]aalinearizing [~]pls [~]sdf [~]tess [~]grdefault]") + +inline GrContextOptions::GpuPathRenderers get_named_pathrenderers_flags(const char* name) { + using GpuPathRenderers = GrContextOptions::GpuPathRenderers; + if (!strcmp(name, "all")) { + return GpuPathRenderers::kAll; + } else if (!strcmp(name, "dashline")) { + return GpuPathRenderers::kDashLine; + } else if (!strcmp(name, "nvpr")) { + return GpuPathRenderers::kStencilAndCover; + } else if (!strcmp(name, "msaa")) { + return GpuPathRenderers::kMSAA; + } else if (!strcmp(name, "aahairline")) { + return GpuPathRenderers::kAAHairline; + } else if (!strcmp(name, "aaconvex")) { + return GpuPathRenderers::kAAConvex; + } else if (!strcmp(name, "aalinearizing")) { + return GpuPathRenderers::kAALinearizing; + } else if (!strcmp(name, "pls")) { + return GpuPathRenderers::kPLS; + } else if (!strcmp(name, "sdf")) { + return GpuPathRenderers::kDistanceField; + } else if (!strcmp(name, "tess")) { + return GpuPathRenderers::kTesselating; + } else if (!strcmp(name, "grdefault")) { + return GpuPathRenderers::kDefault; + } + SK_ABORT(SkStringPrintf("error: unknown named path renderer \"%s\"\n", name).c_str()); + return GpuPathRenderers::kNone; +} + +inline GrContextOptions::GpuPathRenderers CollectGpuPathRenderersFromFlags() { + using GpuPathRenderers = GrContextOptions::GpuPathRenderers; + if (FLAGS_pr.isEmpty()) { + return GpuPathRenderers::kAll; + } + GpuPathRenderers gpuPathRenderers = '~' == FLAGS_pr[0][0] ? + GpuPathRenderers::kAll : GpuPathRenderers::kNone; + for (int i = 0; i < FLAGS_pr.count(); ++i) { + const char* name = FLAGS_pr[i]; + if (name[0] == '~') { + gpuPathRenderers &= ~get_named_pathrenderers_flags(&name[1]); + } else { + gpuPathRenderers |= get_named_pathrenderers_flags(name); + } + } + return gpuPathRenderers; +} + +#endif // SK_SUPPORT_GPU + +#endif diff --git a/tools/gpu/GrContextFactory.cpp b/tools/gpu/GrContextFactory.cpp index 965e646e59..637c569f89 100644 --- a/tools/gpu/GrContextFactory.cpp +++ b/tools/gpu/GrContextFactory.cpp @@ -196,12 +196,6 @@ ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOverrides } testCtx.reset(glCtx); glInterface.reset(SkRef(glCtx->gl())); - if (ContextOverrides::kDisableNVPR & overrides) { - glInterface.reset(GrGLInterfaceRemoveNVPR(glInterface.get())); - if (!glInterface) { - return ContextInfo(); - } - } backendContext = reinterpret_cast<GrBackendContext>(glInterface.get()); break; } @@ -238,6 +232,9 @@ ContextInfo GrContextFactory::getContextInfo(ContextType type, ContextOverrides testCtx->makeCurrent(); SkASSERT(testCtx && testCtx->backend() == backend); GrContextOptions grOptions = fGlobalOptions; + if (ContextOverrides::kDisableNVPR & overrides) { + grOptions.fSuppressPathRendering = true; + } if (ContextOverrides::kUseInstanced & overrides) { grOptions.fEnableInstancedRendering = true; } diff --git a/tools/skpbench/skpbench.cpp b/tools/skpbench/skpbench.cpp index 3887c5ea88..569c204a72 100644 --- a/tools/skpbench/skpbench.cpp +++ b/tools/skpbench/skpbench.cpp @@ -8,6 +8,7 @@ #include "GpuTimer.h" #include "GrContextFactory.h" #include "SkCanvas.h" +#include "SkCommonFlagsPathRenderer.h" #include "SkOSFile.h" #include "SkOSPath.h" #include "SkPerlinNoiseShader.h" @@ -46,6 +47,7 @@ DEFINE_string(skp, "", "path to a single .skp file, or 'warmup' for a builtin wa DEFINE_string(png, "", "if set, save a .png proof to disk at this file location"); DEFINE_int32(verbosity, 4, "level of verbosity (0=none to 5=debug)"); DEFINE_bool(suppressHeader, false, "don't print a header row before the results"); +DEFINE_pathrenderer_flag; static const char* header = " accum median max min stddev samples sample_ms clock metric config bench"; @@ -271,7 +273,9 @@ int main(int argc, char** argv) { } // Create a context. - sk_gpu_test::GrContextFactory factory; + GrContextOptions ctxOptions; + ctxOptions.fGpuPathRenderers = CollectGpuPathRenderersFromFlags(); + sk_gpu_test::GrContextFactory factory(ctxOptions); sk_gpu_test::ContextInfo ctxInfo = factory.getContextInfo(config->getContextType(), config->getContextOverrides()); GrContext* ctx = ctxInfo.grContext(); diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp index 57185d2c3b..092910a724 100644 --- a/tools/viewer/Viewer.cpp +++ b/tools/viewer/Viewer.cpp @@ -16,6 +16,7 @@ #include "SkATrace.h" #include "SkCanvas.h" #include "SkCommandLineFlags.h" +#include "SkCommonFlagsPathRenderer.h" #include "SkDashPathEffect.h" #include "SkGraphics.h" #include "SkImagePriv.h" @@ -134,6 +135,8 @@ static DEFINE_string2(backend, b, "sw", "Backend to use. Allowed values are " BA static DEFINE_bool(atrace, false, "Enable support for using ATrace. ATrace is only supported on Android."); +DEFINE_pathrenderer_flag; + const char *kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = { " [OpenGL]", #ifdef SK_VULKAN diff --git a/tools/viewer/sk_app/GLWindowContext.cpp b/tools/viewer/sk_app/GLWindowContext.cpp index 501f272a3e..fac0c328c4 100644 --- a/tools/viewer/sk_app/GLWindowContext.cpp +++ b/tools/viewer/sk_app/GLWindowContext.cpp @@ -7,6 +7,7 @@ */ #include "GrContext.h" +#include "SkCommonFlagsPathRenderer.h" #include "SkSurface.h" #include "GLWindowContext.h" @@ -30,12 +31,13 @@ GLWindowContext::GLWindowContext(const DisplayParams& params) void GLWindowContext::initializeContext() { this->onInitializeContext(); - sk_sp<const GrGLInterface> glInterface; - glInterface.reset(GrGLCreateNativeInterface()); - fBackendContext.reset(GrGLInterfaceRemoveNVPR(glInterface.get())); - SkASSERT(nullptr == fContext); - fContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fBackendContext.get()); + + GrContextOptions ctxOptions; + ctxOptions.fGpuPathRenderers = CollectGpuPathRenderersFromFlags(); + fBackendContext.reset(GrGLCreateNativeInterface()); + fContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fBackendContext.get(), + ctxOptions); // We may not have real sRGB support (ANGLE, in particular), so check for // that, and fall back to L32: diff --git a/tools/viewer/sk_app/VulkanWindowContext.cpp b/tools/viewer/sk_app/VulkanWindowContext.cpp index b4e6676335..65273b05d0 100644 --- a/tools/viewer/sk_app/VulkanWindowContext.cpp +++ b/tools/viewer/sk_app/VulkanWindowContext.cpp @@ -8,6 +8,7 @@ #include "GrContext.h" #include "GrRenderTarget.h" +#include "SkCommonFlagsPathRenderer.h" #include "SkAutoMalloc.h" #include "SkSurface.h" #include "VulkanWindowContext.h" @@ -61,7 +62,10 @@ VulkanWindowContext::VulkanWindowContext(const DisplayParams& params, GET_DEV_PROC(AcquireNextImageKHR); GET_DEV_PROC(QueuePresentKHR); - fContext = GrContext::Create(kVulkan_GrBackend, (GrBackendContext) fBackendContext.get()); + GrContextOptions ctxOptions; + ctxOptions.fGpuPathRenderers = CollectGpuPathRenderersFromFlags(); + fContext = GrContext::Create(kVulkan_GrBackend, (GrBackendContext) fBackendContext.get(), + ctxOptions); fSurface = createVkSurface(instance); if (VK_NULL_HANDLE == fSurface) { |