diff options
Diffstat (limited to 'dm')
-rw-r--r-- | dm/DM.cpp | 19 | ||||
-rw-r--r-- | dm/DMSrcSink.cpp | 65 | ||||
-rw-r--r-- | dm/DMSrcSink.h | 21 |
3 files changed, 98 insertions, 7 deletions
@@ -18,6 +18,7 @@ #include "SkColorSpacePriv.h" #include "SkCommonFlags.h" #include "SkCommonFlagsConfig.h" +#include "SkCommonFlagsGpuThreads.h" #include "SkCommonFlagsPathRenderer.h" #include "SkData.h" #include "SkDocument.h" @@ -858,10 +859,19 @@ static Sink* create_sink(const GrContextOptions& grCtxOptions, const SkCommandLi "GM tests will be skipped.\n", gpuConfig->getTag().c_str()); return nullptr; } - return new GPUSink(contextType, contextOverrides, gpuConfig->getSamples(), - gpuConfig->getUseDIText(), gpuConfig->getColorType(), - gpuConfig->getAlphaType(), sk_ref_sp(gpuConfig->getColorSpace()), - FLAGS_gpu_threading, grCtxOptions); + if (gpuConfig->getTestThreading()) { + return new GPUThreadTestingSink(contextType, contextOverrides, + gpuConfig->getSamples(), gpuConfig->getUseDIText(), + gpuConfig->getColorType(), + gpuConfig->getAlphaType(), + sk_ref_sp(gpuConfig->getColorSpace()), + FLAGS_gpu_threading, grCtxOptions); + } else { + return new GPUSink(contextType, contextOverrides, gpuConfig->getSamples(), + gpuConfig->getUseDIText(), gpuConfig->getColorType(), + gpuConfig->getAlphaType(), sk_ref_sp(gpuConfig->getColorSpace()), + FLAGS_gpu_threading, grCtxOptions); + } } } #endif @@ -1320,6 +1330,7 @@ int main(int argc, char** argv) { GrContextOptions grCtxOptions; #if SK_SUPPORT_GPU grCtxOptions.fGpuPathRenderers = CollectGpuPathRenderersFromFlags(); + grCtxOptions.fExecutor = GpuExecutorForTools(); #endif JsonWriter::DumpJson(); // It's handy for the bots to assume this is ~never missing. diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp index f9e5fd3d21..47b10e42bf 100644 --- a/dm/DMSrcSink.cpp +++ b/dm/DMSrcSink.cpp @@ -20,6 +20,7 @@ #include "SkDebugCanvas.h" #include "SkDeferredCanvas.h" #include "SkDocument.h" +#include "SkExecutor.h" #include "SkImageGenerator.h" #include "SkImageGeneratorCG.h" #include "SkImageGeneratorWIC.h" @@ -61,6 +62,7 @@ DEFINE_bool(multiPage, false, "For document-type backends, render the source" " into multiple pages"); DEFINE_bool(RAW_threading, true, "Allow RAW decodes to run on multiple threads?"); +DECLARE_int32(gpuThreads); using sk_gpu_test::GrContextFactory; @@ -1315,8 +1317,13 @@ GPUSink::GPUSink(GrContextFactory::ContextType ct, DEFINE_bool(drawOpClip, false, "Clip each GrDrawOp to its device bounds for testing."); -Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log) const { - GrContextOptions grOptions = fBaseContextOptions; +Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream* dstStream, SkString* log) const { + return this->onDraw(src, dst, dstStream, log, fBaseContextOptions); +} + +Error GPUSink::onDraw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log, + const GrContextOptions& baseOptions) const { + GrContextOptions grOptions = baseOptions; src.modifyGrContextOptions(&grOptions); @@ -1368,6 +1375,58 @@ Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log) co /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ +GPUThreadTestingSink::GPUThreadTestingSink(GrContextFactory::ContextType ct, + GrContextFactory::ContextOverrides overrides, + int samples, + bool diText, + SkColorType colorType, + SkAlphaType alphaType, + sk_sp<SkColorSpace> colorSpace, + bool threaded, + const GrContextOptions& grCtxOptions) + : INHERITED(ct, overrides, samples, diText, colorType, alphaType, std::move(colorSpace), + threaded, grCtxOptions) + , fExecutor(SkExecutor::MakeThreadPool(FLAGS_gpuThreads)) { + SkASSERT(fExecutor); +} + +Error GPUThreadTestingSink::draw(const Src& src, SkBitmap* dst, SkWStream* wStream, + SkString* log) const { + // Draw twice, once with worker threads, and once without. Verify that we get the same result. + // Also, force us to only use the software path renderer, so we really stress-test the threaded + // version of that code. + GrContextOptions contextOptions = this->baseContextOptions(); + contextOptions.fGpuPathRenderers = GrContextOptions::GpuPathRenderers::kNone; + + contextOptions.fExecutor = fExecutor.get(); + Error err = this->onDraw(src, dst, wStream, log, contextOptions); + if (!err.isEmpty() || !dst) { + return err; + } + + SkBitmap reference; + SkString refLog; + SkDynamicMemoryWStream refStream; + contextOptions.fExecutor = nullptr; + Error refErr = this->onDraw(src, &reference, &refStream, &refLog, contextOptions); + if (!refErr.isEmpty()) { + return refErr; + } + + // The dimensions are a property of the Src only, and so should be identical. + SkASSERT(reference.getSize() == dst->getSize()); + if (reference.getSize() != dst->getSize()) { + return "Dimensions don't match reference"; + } + // All SkBitmaps in DM are tight, so this comparison is easy. + if (0 != memcmp(reference.getPixels(), dst->getPixels(), reference.getSize())) { + return "Pixels don't match reference"; + } + return ""; +} + +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ + static Error draw_skdocument(const Src& src, SkDocument* doc, SkWStream* dst) { if (src.size().isEmpty()) { return "Source has empty dimensions"; @@ -1558,7 +1617,7 @@ static Error check_against_reference(const SkBitmap* bitmap, const Src& src, Sin if (reference.getSize() != bitmap->getSize()) { return "Dimensions don't match reference"; } - // All SkBitmaps in DM are pre-locked and tight, so this comparison is easy. + // All SkBitmaps in DM are tight, so this comparison is easy. if (0 != memcmp(reference.getPixels(), bitmap->getPixels(), reference.getSize())) { return "Pixels don't match reference"; } diff --git a/dm/DMSrcSink.h b/dm/DMSrcSink.h index 117514995a..8b6ee0e5f4 100644 --- a/dm/DMSrcSink.h +++ b/dm/DMSrcSink.h @@ -310,6 +310,9 @@ public: bool threaded, const GrContextOptions& grCtxOptions); Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; + Error onDraw(const Src&, SkBitmap*, SkWStream*, SkString*, + const GrContextOptions& baseOptions) const; + bool serial() const override { return !fThreaded; } const char* fileExtension() const override { return "png"; } SinkFlags flags() const override { @@ -317,6 +320,8 @@ public: : SinkFlags::kNotMultisampled; return SinkFlags{ SinkFlags::kGPU, SinkFlags::kDirect, ms }; } + const GrContextOptions& baseContextOptions() const { return fBaseContextOptions; } + private: sk_gpu_test::GrContextFactory::ContextType fContextType; sk_gpu_test::GrContextFactory::ContextOverrides fContextOverrides; @@ -329,6 +334,22 @@ private: GrContextOptions fBaseContextOptions; }; +class GPUThreadTestingSink : public GPUSink { +public: + GPUThreadTestingSink(sk_gpu_test::GrContextFactory::ContextType, + sk_gpu_test::GrContextFactory::ContextOverrides, int samples, bool diText, + SkColorType colorType, SkAlphaType alphaType, + sk_sp<SkColorSpace> colorSpace, bool threaded, + const GrContextOptions& grCtxOptions); + + Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override; + +private: + std::unique_ptr<SkExecutor> fExecutor; + + typedef GPUSink INHERITED; +}; + class PDFSink : public Sink { public: PDFSink(bool pdfa, SkScalar rasterDpi) : fPDFA(pdfa), fRasterDpi(rasterDpi) {} |