[graphite] Set up unit testing system
Bug: skia:12466
Change-Id: I401a185d818a964327d323b9ebcd0850ec0b1c9b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/457318
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 865a7c6..47e8d8c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -2001,6 +2001,9 @@
if (skia_use_gl) {
sources += gl_tests_sources
}
+ if (skia_enable_graphite) {
+ sources += graphite_tests_sources
+ }
if (!skia_enable_skgpu_v1) {
sources -= skgpu_v1_tests_sources
}
diff --git a/dm/DMGpuTestProcs.cpp b/dm/DMGpuTestProcs.cpp
index b6e880b..ffb5f0e 100644
--- a/dm/DMGpuTestProcs.cpp
+++ b/dm/DMGpuTestProcs.cpp
@@ -9,6 +9,9 @@
#include "include/gpu/GrDirectContext.h"
+#include "experimental/graphite/include/Context.h"
+#include "tools/graphite/ContextFactory.h"
+
using sk_gpu_test::GrContextFactory;
using sk_gpu_test::GLTestContext;
using sk_gpu_test::ContextInfo;
@@ -76,4 +79,24 @@
}
}
}
+
+#ifdef SK_GRAPHITE_ENABLED
+
+namespace graphite {
+
+void RunWithGraphiteTestContexts(GraphiteTestFn* test, Reporter* reporter) {
+ ContextFactory factory;
+
+ auto [_, context] = factory.getContextInfo(ContextFactory::ContextType::kMetal);
+ if (!context) {
+ return;
+ }
+
+ (*test)(reporter, context.get());
+}
+
+} // namespace graphite
+
+#endif // SK_GRAPHITE_ENABLED
+
} // namespace skiatest
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 495a6aa..8e44a52 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -2125,11 +2125,11 @@
SkBitmap* dst,
SkWStream* dstStream,
SkString* log) const {
- using ContextType = sk_graphite_test::ContextFactory::ContextType;
+ using ContextType = skiatest::graphite::ContextFactory::ContextType;
SkImageInfo ii = SkImageInfo::Make(src.size(), kRGBA_8888_SkColorType, kPremul_SkAlphaType);
- sk_graphite_test::ContextFactory factory;
+ skiatest::graphite::ContextFactory factory;
auto [_, context] = factory.getContextInfo(ContextType::kMetal);
sk_sp<SkSurface> surface = MakeGraphite(std::move(context), ii);
diff --git a/experimental/graphite/include/Context.h b/experimental/graphite/include/Context.h
index 719e175..905eead 100644
--- a/experimental/graphite/include/Context.h
+++ b/experimental/graphite/include/Context.h
@@ -12,6 +12,7 @@
namespace skgpu {
+class ContextPriv;
class Gpu;
namespace mtl { struct BackendContext; }
@@ -23,14 +24,19 @@
static sk_sp<Context> MakeMetal(const skgpu::mtl::BackendContext&);
#endif
+ // Provides access to functions that aren't part of the public API.
+ ContextPriv priv();
+ const ContextPriv priv() const; // NOLINT(readability-const-return-type)
+
protected:
Context(sk_sp<Gpu>);
private:
+ friend class ContextPriv;
+
sk_sp<Gpu> fGpu;
};
} // namespace skgpu
#endif // skgpu_Context_DEFINED
-
diff --git a/experimental/graphite/src/ContextPriv.cpp b/experimental/graphite/src/ContextPriv.cpp
new file mode 100644
index 0000000..6395a0f
--- /dev/null
+++ b/experimental/graphite/src/ContextPriv.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "experimental/graphite/src/ContextPriv.h"
+
+#include "experimental/graphite/src/Caps.h"
+#include "experimental/graphite/src/Gpu.h"
+
+namespace skgpu {
+
+const Caps* ContextPriv::caps() {
+ return fContext->fGpu->caps();
+}
+
+} // namespace skgpu
diff --git a/experimental/graphite/src/ContextPriv.h b/experimental/graphite/src/ContextPriv.h
new file mode 100644
index 0000000..f7746f2
--- /dev/null
+++ b/experimental/graphite/src/ContextPriv.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef skgpu_ContextPriv_DEFINED
+#define skgpu_ContextPriv_DEFINED
+
+#include "experimental/graphite/include/Context.h"
+
+namespace skgpu {
+
+class Caps;
+
+/** Class that adds methods to Context that are only intended for use internal to Skia.
+ This class is purely a privileged window into Context. It should never have additional
+ data members or virtual methods. */
+class ContextPriv {
+public:
+ const Caps* caps();
+
+private:
+ friend class Context; // to construct/copy this type.
+
+ explicit ContextPriv(Context* context) : fContext(context) {}
+
+ ContextPriv(const ContextPriv&) = delete;
+ ContextPriv& operator=(const ContextPriv&) = delete;
+
+ // No taking addresses of this type.
+ const ContextPriv* operator&() const;
+ ContextPriv *operator&();
+
+ Context* fContext;
+};
+
+inline ContextPriv Context::priv() { return ContextPriv(this); }
+
+// NOLINTNEXTLINE(readability-const-return-type)
+inline const ContextPriv Context::priv() const {
+ return ContextPriv(const_cast<Context *>(this));
+}
+
+} // namespace skgpu
+
+#endif // skgpu_ContextPriv_DEFINED
diff --git a/experimental/graphite/src/geom/Shape.h b/experimental/graphite/src/geom/Shape.h
index db4cfea..18e4565 100644
--- a/experimental/graphite/src/geom/Shape.h
+++ b/experimental/graphite/src/geom/Shape.h
@@ -24,6 +24,7 @@
* point containment, or iteration.
*/
class Shape {
+public:
enum class Type : uint8_t {
kEmpty, kRect, kRRect, kPath
};
diff --git a/gn/graphite.gni b/gn/graphite.gni
index 96d01ed..a7dfcdc 100644
--- a/gn/graphite.gni
+++ b/gn/graphite.gni
@@ -22,6 +22,8 @@
"$_src/CommandBuffer.cpp",
"$_src/CommandBuffer.h",
"$_src/Context.cpp",
+ "$_src/ContextPriv.cpp",
+ "$_src/ContextPriv.h",
"$_src/Device.cpp",
"$_src/Device.h",
"$_src/DrawContext.cpp",
diff --git a/gn/tests.gni b/gn/tests.gni
index 9a4ef2e..75894c8 100644
--- a/gn/tests.gni
+++ b/gn/tests.gni
@@ -325,6 +325,11 @@
"$_tests/MtlCopySurfaceTest.mm",
]
+graphite_tests_sources = [
+ "$_tests/graphite/CapsTest.cpp",
+ "$_tests/graphite/ShapeTest.cpp",
+]
+
pathops_tests_sources = [
"$_tests/PathOpsAngleIdeas.cpp",
"$_tests/PathOpsAngleTest.cpp",
diff --git a/tests/Test.h b/tests/Test.h
index f02b751..7aedde9 100644
--- a/tests/Test.h
+++ b/tests/Test.h
@@ -13,6 +13,8 @@
#include "tools/Registry.h"
#include "tools/gpu/GrContextFactory.h"
+namespace skgpu { class Context; }
+
namespace skiatest {
SkString GetTmpDir();
@@ -124,6 +126,14 @@
void RunWithGPUTestContexts(GrContextTestFn*, GrContextTypeFilterFn*, Reporter*,
const GrContextOptions&);
+namespace graphite {
+
+typedef void GraphiteTestFn(Reporter*, skgpu::Context*);
+
+void RunWithGraphiteTestContexts(GraphiteTestFn*, Reporter*);
+
+} // namespace graphite
+
/** Timer provides wall-clock duration since its creation. */
class Timer {
public:
@@ -178,13 +188,33 @@
skiatest::TestRegistry name##TestRegistry(skiatest::Test(#name, false, test_##name)); \
void test_##name(skiatest::Reporter* reporter, const GrContextOptions&)
+#define DEF_GRAPHITE_TEST(name, reporter) \
+ static void test_##name(skiatest::Reporter*); \
+ static void test_graphite_##name(skiatest::Reporter* reporter, \
+ const GrContextOptions& /*unused*/) { \
+ test_##name(reporter); \
+ } \
+ skiatest::TestRegistry name##TestRegistry( \
+ skiatest::Test(#name, true, test_graphite_##name)); \
+ void test_##name(skiatest::Reporter* reporter)
+
+#define DEF_GRAPHITE_TEST_FOR_CONTEXTS(name, reporter, graphite_context) \
+ static void test_##name(skiatest::Reporter*, skgpu::Context*); \
+ static void test_graphite_contexts_##name(skiatest::Reporter* _reporter, \
+ const GrContextOptions& /*unused*/) { \
+ skiatest::graphite::RunWithGraphiteTestContexts(test_##name, _reporter); \
+ } \
+ skiatest::TestRegistry name##TestRegistry( \
+ skiatest::Test(#name, true, test_graphite_contexts_##name)); \
+ void test_##name(skiatest::Reporter* reporter, skgpu::Context* graphite_context)
+
#define DEF_GPUTEST(name, reporter, options) \
static void test_##name(skiatest::Reporter*, const GrContextOptions&); \
skiatest::TestRegistry name##TestRegistry(skiatest::Test(#name, true, test_##name)); \
void test_##name(skiatest::Reporter* reporter, const GrContextOptions& options)
#define DEF_GPUTEST_FOR_CONTEXTS(name, context_filter, reporter, context_info, options_filter) \
- static void test_##name(skiatest::Reporter*, const sk_gpu_test::ContextInfo& context_info); \
+ static void test_##name(skiatest::Reporter*, const sk_gpu_test::ContextInfo&); \
static void test_gpu_contexts_##name(skiatest::Reporter* reporter, \
const GrContextOptions& options) { \
skiatest::RunWithGPUTestContexts(test_##name, context_filter, reporter, options); \
diff --git a/tests/graphite/CapsTest.cpp b/tests/graphite/CapsTest.cpp
new file mode 100644
index 0000000..ff13f6f
--- /dev/null
+++ b/tests/graphite/CapsTest.cpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tests/Test.h"
+
+#include "experimental/graphite/include/Context.h"
+#include "experimental/graphite/src/ContextPriv.h"
+
+DEF_GRAPHITE_TEST_FOR_CONTEXTS(CapsTest, reporter, context) {
+ // TODO: Jim takes this over
+ auto caps = context->priv().caps();
+ REPORTER_ASSERT(reporter, caps);
+}
diff --git a/tests/graphite/ShapeTest.cpp b/tests/graphite/ShapeTest.cpp
new file mode 100644
index 0000000..09b5a05
--- /dev/null
+++ b/tests/graphite/ShapeTest.cpp
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "tests/Test.h"
+
+#include "experimental/graphite/src/geom/Shape.h"
+
+DEF_GRAPHITE_TEST(ShapeTest, reporter) {
+ // TODO: Michael takes this over
+ skgpu::geom::Shape s;
+ REPORTER_ASSERT(reporter, s.type() == skgpu::geom::Shape::Type::kEmpty);
+}
diff --git a/tools/graphite/ContextFactory.cpp b/tools/graphite/ContextFactory.cpp
index 0bc2c54..a1e7fb3 100644
--- a/tools/graphite/ContextFactory.cpp
+++ b/tools/graphite/ContextFactory.cpp
@@ -13,7 +13,7 @@
#include "tools/graphite/mtl/GraphiteMtlTestContext.h"
#endif
-namespace sk_graphite_test {
+namespace skiatest::graphite {
std::tuple<GraphiteTestContext*, sk_sp<skgpu::Context>> ContextFactory::getContextInfo(
ContextType type) {
@@ -51,4 +51,4 @@
return { fContexts.back().testContext(), fContexts.back().refContext() };
}
-} // namespace sk_graphite_test
+} // namespace skiatest::graphite
diff --git a/tools/graphite/ContextFactory.h b/tools/graphite/ContextFactory.h
index 46f0121..4acdd36 100644
--- a/tools/graphite/ContextFactory.h
+++ b/tools/graphite/ContextFactory.h
@@ -5,8 +5,8 @@
* found in the LICENSE file.
*/
-#ifndef sk_graphite_test_ContextFactory_DEFINED
-#define sk_graphite_test_ContextFactory_DEFINED
+#ifndef skiatest_graphite_ContextFactory_DEFINED
+#define skiatest_graphite_ContextFactory_DEFINED
#include <vector>
#include "experimental/graphite/include/GraphiteTypes.h"
@@ -17,7 +17,7 @@
class Context;
};
-namespace sk_graphite_test {
+namespace skiatest::graphite {
class ContextFactory {
public:
@@ -71,6 +71,6 @@
std::vector<ContextInfo> fContexts;
};
-} // namespace sk_graphite_test
+} // namespace skiatest::graphite
-#endif // sk_graphite_test_ContextFactory_DEFINED
+#endif // skiatest_graphite_ContextFactory_DEFINED
diff --git a/tools/graphite/GraphiteTestContext.cpp b/tools/graphite/GraphiteTestContext.cpp
index 44100c3..8b76482 100644
--- a/tools/graphite/GraphiteTestContext.cpp
+++ b/tools/graphite/GraphiteTestContext.cpp
@@ -7,10 +7,10 @@
#include "tools/graphite/GraphiteTestContext.h"
-namespace sk_graphite_test {
+namespace skiatest::graphite {
GraphiteTestContext::GraphiteTestContext() {}
GraphiteTestContext::~GraphiteTestContext() {}
-} // namespace sk_graphite_test
+} // namespace skiatest::graphite
diff --git a/tools/graphite/GraphiteTestContext.h b/tools/graphite/GraphiteTestContext.h
index 0d97fb7..642945a 100644
--- a/tools/graphite/GraphiteTestContext.h
+++ b/tools/graphite/GraphiteTestContext.h
@@ -5,15 +5,15 @@
* found in the LICENSE file.
*/
-#ifndef sk_graphite_test_GraphiteTestContext_DEFINED
-#define sk_graphite_test_GraphiteTestContext_DEFINED
+#ifndef skiatest_graphite_GraphiteTestContext_DEFINED
+#define skiatest_graphite_GraphiteTestContext_DEFINED
#include "experimental/graphite/include/GraphiteTypes.h"
#include "include/core/SkRefCnt.h"
namespace skgpu { class Context; }
-namespace sk_graphite_test {
+namespace skiatest::graphite {
/**
* An offscreen 3D context. This class is intended for Skia's internal testing needs and not
@@ -35,6 +35,6 @@
};
-} // namespace sk_graphite_test
+} // namespace skiatest::graphite
-#endif // sk_graphite_test_GraphiteTestContext_DEFINED
+#endif // skiatest_graphite_GraphiteTestContext_DEFINED
diff --git a/tools/graphite/mtl/GraphiteMtlTestContext.h b/tools/graphite/mtl/GraphiteMtlTestContext.h
index ea06ad9..5acd2dc 100644
--- a/tools/graphite/mtl/GraphiteMtlTestContext.h
+++ b/tools/graphite/mtl/GraphiteMtlTestContext.h
@@ -5,8 +5,8 @@
* found in the LICENSE file.
*/
-#ifndef skgpu_MtlTestContext_DEFINED
-#define skgpu_MtlTestContext_DEFINED
+#ifndef skiatest_graphite_MtlTestContext_DEFINED
+#define skiatest_graphite_MtlTestContext_DEFINED
#include "tools/graphite/GraphiteTestContext.h"
@@ -14,7 +14,7 @@
#include "experimental/graphite/include/mtl/MtlBackendContext.h"
-namespace sk_graphite_test::mtl {
+namespace skiatest::graphite::mtl {
class TestContext : public GraphiteTestContext {
public:
@@ -36,8 +36,8 @@
skgpu::mtl::BackendContext fMtl;
};
-} // namespace sk_graphite_test::mtl
+} // namespace skiatest::graphite::mtl
#endif // SK_METAL
-#endif // skgpu_MtlTestContext_DEFINED
+#endif // skiatest_graphite_MtlTestContext_DEFINED
diff --git a/tools/graphite/mtl/MtlTestContext.mm b/tools/graphite/mtl/MtlTestContext.mm
index ea8f263..7085f28 100644
--- a/tools/graphite/mtl/MtlTestContext.mm
+++ b/tools/graphite/mtl/MtlTestContext.mm
@@ -14,7 +14,7 @@
#import <Metal/Metal.h>
-namespace sk_graphite_test::mtl {
+namespace skiatest::graphite::mtl {
std::unique_ptr<GraphiteTestContext> TestContext::Make() {
sk_cfp<id<MTLDevice>> device;
@@ -51,6 +51,6 @@
return skgpu::Context::MakeMetal(fMtl);
}
-} // namespace sk_graphite_test::mtl
+} // namespace skiatest::graphite::mtl
#endif // SK_METAL