aboutsummaryrefslogtreecommitdiffhomepage
path: root/dm
diff options
context:
space:
mode:
Diffstat (limited to 'dm')
-rw-r--r--dm/DM.cpp19
-rw-r--r--dm/DMSrcSink.cpp65
-rw-r--r--dm/DMSrcSink.h21
3 files changed, 98 insertions, 7 deletions
diff --git a/dm/DM.cpp b/dm/DM.cpp
index a442e09050..1e02d25b7b 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -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) {}