Update SkOpts namespaces.
If we make sure all SkOpts functions are static, we can give the namespaces any
name we like. This lets us drop the sk_ prefix and give a real indication of
the default SIMD instruction set rather than just saying sk_default.
Both of these changes help debugger, profiler, and crash report readability.
Perhaps more importantly, keeping these functions static helps prevent
accidentally linking in unused versions of functions, as you see here with
sk_avx::srcover_srgb_srgb().
This requires we update SkBlend_opts tests and benches to call SkOpts functions
through SkOpts rather than declaring the methods externally. In practice this
drops testing of the SSE2 version on machines with SSE4. If we still really
need to test/bench the compile time best SIMD level version of this method
against the runtime detected best, we can include SkBlend_opts.h into the tests
or benches directly, similar to what we do for the trivial, brute-force, or best
non-SIMD versions.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2145833002
CQ_INCLUDE_TRYBOTS=client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot
Review-Url: https://codereview.chromium.org/2145833002
diff --git a/bench/SkBlend_optsBench.cpp b/bench/SkBlend_optsBench.cpp
index 4dfaaef..c290714 100644
--- a/bench/SkBlend_optsBench.cpp
+++ b/bench/SkBlend_optsBench.cpp
@@ -83,7 +83,6 @@
class SrcOverVSkOptsBruteForce {
public:
static SkString Name() { return SkString{"VSkOptsBruteForce"}; }
- static bool WorksOnCpu() { return true; }
static void BlendN(uint32_t* dst, const uint32_t* src, int count) {
brute_force_srcover_srgb_srgb(dst, src, count, count);
}
@@ -92,7 +91,6 @@
class SrcOverVSkOptsTrivial {
public:
static SkString Name() { return SkString{"VSkOptsTrivial"}; }
- static bool WorksOnCpu() { return true; }
static void BlendN(uint32_t* dst, const uint32_t* src, int count) {
trivial_srcover_srgb_srgb(dst, src, count, count);
}
@@ -101,37 +99,16 @@
class SrcOverVSkOptsNonSimdCore {
public:
static SkString Name() { return SkString{"VSkOptsNonSimdCore"}; }
- static bool WorksOnCpu() { return true; }
static void BlendN(uint32_t* dst, const uint32_t* src, int count) {
best_non_simd_srcover_srgb_srgb(dst, src, count, count);
}
};
-namespace sk_default {
-extern void srcover_srgb_srgb(
- uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc);
-}
-
class SrcOverVSkOptsDefault {
public:
static SkString Name() { return SkString{"VSkOptsDefault"}; }
- static bool WorksOnCpu() { return true; }
static void BlendN(uint32_t* dst, const uint32_t* src, int count) {
- sk_default::srcover_srgb_srgb(dst, src, count, count);
- }
-};
-
-namespace sk_sse41 {
- extern void srcover_srgb_srgb(
- uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc);
-}
-
-class SrcOverVSkOptsSSE41 {
-public:
- static SkString Name() { return SkString{"VSkOptsSSE41"}; }
- static bool WorksOnCpu() { return SkCpu::Supports(SkCpu::SSE41); }
- static void BlendN(uint32_t* dst, const uint32_t* src, int count) {
- sk_sse41::srcover_srgb_srgb(dst, src, count, count);
+ SkOpts::srcover_srgb_srgb(dst, src, count, count);
}
};
@@ -147,9 +124,7 @@
}
protected:
- bool isSuitableFor(Backend backend) override {
- return backend == kNonRendering_Backend && Blender::WorksOnCpu();
- }
+ bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
const char* onGetName() override { return fName.c_str(); }
void onPreDraw(SkCanvas*) override {
@@ -198,20 +173,11 @@
typedef Benchmark INHERITED;
};
-#if defined(SK_CPU_X86) && !defined(SK_BUILD_NO_OPTS)
-#define BENCHES(fileName) \
-DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsBruteForce>(fileName); ) \
-DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsTrivial>(fileName); ) \
-DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsNonSimdCore>(fileName); ) \
-DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsDefault>(fileName); ) \
-DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsSSE41>(fileName); )
-#else
-#define BENCHES(fileName) \
-DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsBruteForce>(fileName); ) \
-DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsTrivial>(fileName); ) \
-DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsNonSimdCore>(fileName); ) \
-DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsDefault>(fileName); )
-#endif
+#define BENCHES(fileName) \
+ DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsBruteForce>(fileName); ) \
+ DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsTrivial>(fileName); ) \
+ DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsNonSimdCore>(fileName); ) \
+ DEF_BENCH( return new LinearSrcOverBench<SrcOverVSkOptsDefault>(fileName); )
BENCHES("yellow_rose.png")
BENCHES("baby_tux.png")
diff --git a/src/core/SkOpts.cpp b/src/core/SkOpts.cpp
index 9e03632..be716a9 100644
--- a/src/core/SkOpts.cpp
+++ b/src/core/SkOpts.cpp
@@ -10,7 +10,18 @@
#include "SkOnce.h"
#include "SkOpts.h"
-#define SK_OPTS_NS sk_default
+#if defined(SK_ARM_HAS_NEON)
+ #define SK_OPTS_NS neon
+#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSSE3
+ #define SK_OPTS_NS ssse3
+#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE3
+ #define SK_OPTS_NS sse3
+#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
+ #define SK_OPTS_NS sse2
+#else
+ #define SK_OPTS_NS portable
+#endif
+
#include "SkBlend_opts.h"
#include "SkBlitMask_opts.h"
#include "SkBlitRow_opts.h"
@@ -36,53 +47,51 @@
}
namespace SkOpts {
-
// Define default function pointer values here...
// If our global compile options are set high enough, these defaults might even be
// CPU-specialized, e.g. a typical x86-64 machine might start with SSE2 defaults.
// They'll still get a chance to be replaced with even better ones, e.g. using SSE4.1.
- decltype(create_xfermode) create_xfermode = sk_default::create_xfermode;
- decltype(color_cube_filter_span) color_cube_filter_span = sk_default::color_cube_filter_span;
+#define DEFINE_DEFAULT(name) decltype(name) name = SK_OPTS_NS::name
+ DEFINE_DEFAULT(create_xfermode);
+ DEFINE_DEFAULT(color_cube_filter_span);
- decltype(box_blur_xx) box_blur_xx = sk_default::box_blur_xx;
- decltype(box_blur_xy) box_blur_xy = sk_default::box_blur_xy;
- decltype(box_blur_yx) box_blur_yx = sk_default::box_blur_yx;
+ DEFINE_DEFAULT(box_blur_xx);
+ DEFINE_DEFAULT(box_blur_xy);
+ DEFINE_DEFAULT(box_blur_yx);
- decltype(dilate_x) dilate_x = sk_default::dilate_x;
- decltype(dilate_y) dilate_y = sk_default::dilate_y;
- decltype( erode_x) erode_x = sk_default::erode_x;
- decltype( erode_y) erode_y = sk_default::erode_y;
+ DEFINE_DEFAULT(dilate_x);
+ DEFINE_DEFAULT(dilate_y);
+ DEFINE_DEFAULT( erode_x);
+ DEFINE_DEFAULT( erode_y);
- decltype(texture_compressor) texture_compressor = sk_default::texture_compressor;
- decltype(fill_block_dimensions) fill_block_dimensions = sk_default::fill_block_dimensions;
+ DEFINE_DEFAULT(texture_compressor);
+ DEFINE_DEFAULT(fill_block_dimensions);
- decltype(blit_mask_d32_a8) blit_mask_d32_a8 = sk_default::blit_mask_d32_a8;
+ DEFINE_DEFAULT(blit_mask_d32_a8);
- decltype(blit_row_color32) blit_row_color32 = sk_default::blit_row_color32;
- decltype(blit_row_s32a_opaque) blit_row_s32a_opaque = sk_default::blit_row_s32a_opaque;
+ DEFINE_DEFAULT(blit_row_color32);
+ DEFINE_DEFAULT(blit_row_s32a_opaque);
- decltype(RGBA_to_BGRA) RGBA_to_BGRA = sk_default::RGBA_to_BGRA;
- decltype(RGBA_to_rgbA) RGBA_to_rgbA = sk_default::RGBA_to_rgbA;
- decltype(RGBA_to_bgrA) RGBA_to_bgrA = sk_default::RGBA_to_bgrA;
- decltype(RGB_to_RGB1) RGB_to_RGB1 = sk_default::RGB_to_RGB1;
- decltype(RGB_to_BGR1) RGB_to_BGR1 = sk_default::RGB_to_BGR1;
- decltype(gray_to_RGB1) gray_to_RGB1 = sk_default::gray_to_RGB1;
- decltype(grayA_to_RGBA) grayA_to_RGBA = sk_default::grayA_to_RGBA;
- decltype(grayA_to_rgbA) grayA_to_rgbA = sk_default::grayA_to_rgbA;
- decltype(inverted_CMYK_to_RGB1) inverted_CMYK_to_RGB1 = sk_default::inverted_CMYK_to_RGB1;
- decltype(inverted_CMYK_to_BGR1) inverted_CMYK_to_BGR1 = sk_default::inverted_CMYK_to_BGR1;
+ DEFINE_DEFAULT(RGBA_to_BGRA);
+ DEFINE_DEFAULT(RGBA_to_rgbA);
+ DEFINE_DEFAULT(RGBA_to_bgrA);
+ DEFINE_DEFAULT(RGB_to_RGB1);
+ DEFINE_DEFAULT(RGB_to_BGR1);
+ DEFINE_DEFAULT(gray_to_RGB1);
+ DEFINE_DEFAULT(grayA_to_RGBA);
+ DEFINE_DEFAULT(grayA_to_rgbA);
+ DEFINE_DEFAULT(inverted_CMYK_to_RGB1);
+ DEFINE_DEFAULT(inverted_CMYK_to_BGR1);
- decltype(half_to_float) half_to_float = sk_default::half_to_float;
- decltype(float_to_half) float_to_half = sk_default::float_to_half;
+ DEFINE_DEFAULT(half_to_float);
+ DEFINE_DEFAULT(float_to_half);
- decltype(srcover_srgb_srgb) srcover_srgb_srgb = sk_default::srcover_srgb_srgb;
+ DEFINE_DEFAULT(srcover_srgb_srgb);
- decltype(color_xform_RGB1_to_2dot2) color_xform_RGB1_to_2dot2 =
- sk_default::color_xform_RGB1_to_2dot2;
- decltype(color_xform_RGB1_to_srgb) color_xform_RGB1_to_srgb =
- sk_default::color_xform_RGB1_to_srgb;
- decltype(color_xform_RGB1_to_table) color_xform_RGB1_to_table =
- sk_default::color_xform_RGB1_to_table;
+ DEFINE_DEFAULT(color_xform_RGB1_to_2dot2);
+ DEFINE_DEFAULT(color_xform_RGB1_to_srgb);
+ DEFINE_DEFAULT(color_xform_RGB1_to_table);
+#undef DEFINE_DEFAULT
// Each Init_foo() is defined in src/opts/SkOpts_foo.cpp.
void Init_ssse3();
diff --git a/src/opts/SkBlend_opts.h b/src/opts/SkBlend_opts.h
index 39cbbe8..4f6d1e9 100644
--- a/src/opts/SkBlend_opts.h
+++ b/src/opts/SkBlend_opts.h
@@ -48,7 +48,7 @@
#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE41
- void srcover_srgb_srgb(
+ static void srcover_srgb_srgb(
uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc) {
const __m128i alphaMask = _mm_set1_epi32(0xFF000000);
while (ndst > 0) {
@@ -123,7 +123,7 @@
return mask == 0;
}
- void srcover_srgb_srgb(
+ static void srcover_srgb_srgb(
uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc) {
while (ndst > 0) {
int count = SkTMin(ndst, nsrc);
@@ -166,7 +166,7 @@
#endif
#else
- void srcover_srgb_srgb(
+ static void srcover_srgb_srgb(
uint32_t* dst, const uint32_t* const src, int ndst, const int nsrc) {
while (ndst > 0) {
int n = SkTMin(ndst, nsrc);
diff --git a/src/opts/SkBlurImageFilter_opts.h b/src/opts/SkBlurImageFilter_opts.h
index f62604c..497bcde 100644
--- a/src/opts/SkBlurImageFilter_opts.h
+++ b/src/opts/SkBlurImageFilter_opts.h
@@ -88,8 +88,9 @@
// Fast path for kernel sizes between 2 and 127, working on two rows at a time.
template<BlurDirection srcDirection, BlurDirection dstDirection>
-int box_blur_double(const SkPMColor** src, int srcStride, const SkIRect& srcBounds, SkPMColor** dst, int kernelSize,
- int leftOffset, int rightOffset, int width, int height) {
+static int box_blur_double(const SkPMColor** src, int srcStride, const SkIRect& srcBounds,
+ SkPMColor** dst, int kernelSize,
+ int leftOffset, int rightOffset, int width, int height) {
// Load 2 pixels from adjacent rows.
auto load_2_pixels = [&](const SkPMColor* s) {
if (srcDirection == BlurDirection::kX) {
diff --git a/src/opts/SkColorCubeFilter_opts.h b/src/opts/SkColorCubeFilter_opts.h
index e0c4c4a..12acd78 100644
--- a/src/opts/SkColorCubeFilter_opts.h
+++ b/src/opts/SkColorCubeFilter_opts.h
@@ -11,13 +11,13 @@
namespace SK_OPTS_NS {
-void color_cube_filter_span(const SkPMColor src[],
- int count,
- SkPMColor dst[],
- const int* colorToIndex[2],
- const SkScalar* colorToFactors[2],
- int dim,
- const SkColor* colorCube) {
+static void color_cube_filter_span(const SkPMColor src[],
+ int count,
+ SkPMColor dst[],
+ const int* colorToIndex[2],
+ const SkScalar* colorToFactors[2],
+ int dim,
+ const SkColor* colorCube) {
uint8_t r, g, b, a;
for (int i = 0; i < count; ++i) {
diff --git a/src/opts/SkOpts_avx.cpp b/src/opts/SkOpts_avx.cpp
index 835e0c0..b5df2b6 100644
--- a/src/opts/SkOpts_avx.cpp
+++ b/src/opts/SkOpts_avx.cpp
@@ -7,8 +7,7 @@
#include "SkOpts.h"
-#define SK_OPTS_NS sk_avx
-#include "SkBlend_opts.h"
+#define SK_OPTS_NS avx
namespace SkOpts {
void Init_avx() { }
diff --git a/src/opts/SkOpts_sse41.cpp b/src/opts/SkOpts_sse41.cpp
index 408602e..56ac386 100644
--- a/src/opts/SkOpts_sse41.cpp
+++ b/src/opts/SkOpts_sse41.cpp
@@ -7,7 +7,7 @@
#include "SkOpts.h"
-#define SK_OPTS_NS sk_sse41
+#define SK_OPTS_NS sse41
#include "SkBlurImageFilter_opts.h"
#include "SkBlitRow_opts.h"
#include "SkBlend_opts.h"
@@ -15,14 +15,14 @@
namespace SkOpts {
void Init_sse41() {
- box_blur_xx = sk_sse41::box_blur_xx;
- box_blur_xy = sk_sse41::box_blur_xy;
- box_blur_yx = sk_sse41::box_blur_yx;
- srcover_srgb_srgb = sk_sse41::srcover_srgb_srgb;
- blit_row_s32a_opaque = sk_sse41::blit_row_s32a_opaque;
+ box_blur_xx = sse41::box_blur_xx;
+ box_blur_xy = sse41::box_blur_xy;
+ box_blur_yx = sse41::box_blur_yx;
+ srcover_srgb_srgb = sse41::srcover_srgb_srgb;
+ blit_row_s32a_opaque = sse41::blit_row_s32a_opaque;
- color_xform_RGB1_to_2dot2 = sk_sse41::color_xform_RGB1_to_2dot2;
- color_xform_RGB1_to_srgb = sk_sse41::color_xform_RGB1_to_srgb;
- color_xform_RGB1_to_table = sk_sse41::color_xform_RGB1_to_table;
+ color_xform_RGB1_to_2dot2 = sse41::color_xform_RGB1_to_2dot2;
+ color_xform_RGB1_to_srgb = sse41::color_xform_RGB1_to_srgb;
+ color_xform_RGB1_to_table = sse41::color_xform_RGB1_to_table;
}
}
diff --git a/src/opts/SkOpts_ssse3.cpp b/src/opts/SkOpts_ssse3.cpp
index 94a26a1..ec96833 100644
--- a/src/opts/SkOpts_ssse3.cpp
+++ b/src/opts/SkOpts_ssse3.cpp
@@ -6,7 +6,7 @@
*/
#include "SkOpts.h"
-#define SK_OPTS_NS sk_ssse3
+#define SK_OPTS_NS ssse3
#include "SkBlitMask_opts.h"
#include "SkColorCubeFilter_opts.h"
#include "SkSwizzler_opts.h"
@@ -14,19 +14,19 @@
namespace SkOpts {
void Init_ssse3() {
- create_xfermode = sk_ssse3::create_xfermode;
- blit_mask_d32_a8 = sk_ssse3::blit_mask_d32_a8;
- color_cube_filter_span = sk_ssse3::color_cube_filter_span;
+ create_xfermode = ssse3::create_xfermode;
+ blit_mask_d32_a8 = ssse3::blit_mask_d32_a8;
+ color_cube_filter_span = ssse3::color_cube_filter_span;
- RGBA_to_BGRA = sk_ssse3::RGBA_to_BGRA;
- RGBA_to_rgbA = sk_ssse3::RGBA_to_rgbA;
- RGBA_to_bgrA = sk_ssse3::RGBA_to_bgrA;
- RGB_to_RGB1 = sk_ssse3::RGB_to_RGB1;
- RGB_to_BGR1 = sk_ssse3::RGB_to_BGR1;
- gray_to_RGB1 = sk_ssse3::gray_to_RGB1;
- grayA_to_RGBA = sk_ssse3::grayA_to_RGBA;
- grayA_to_rgbA = sk_ssse3::grayA_to_rgbA;
- inverted_CMYK_to_RGB1 = sk_ssse3::inverted_CMYK_to_RGB1;
- inverted_CMYK_to_BGR1 = sk_ssse3::inverted_CMYK_to_BGR1;
+ RGBA_to_BGRA = ssse3::RGBA_to_BGRA;
+ RGBA_to_rgbA = ssse3::RGBA_to_rgbA;
+ RGBA_to_bgrA = ssse3::RGBA_to_bgrA;
+ RGB_to_RGB1 = ssse3::RGB_to_RGB1;
+ RGB_to_BGR1 = ssse3::RGB_to_BGR1;
+ gray_to_RGB1 = ssse3::gray_to_RGB1;
+ grayA_to_RGBA = ssse3::grayA_to_RGBA;
+ grayA_to_rgbA = ssse3::grayA_to_rgbA;
+ inverted_CMYK_to_RGB1 = ssse3::inverted_CMYK_to_RGB1;
+ inverted_CMYK_to_BGR1 = ssse3::inverted_CMYK_to_BGR1;
}
}
diff --git a/tests/SkBlend_optsTest.cpp b/tests/SkBlend_optsTest.cpp
index caabc60..7665a2d 100644
--- a/tests/SkBlend_optsTest.cpp
+++ b/tests/SkBlend_optsTest.cpp
@@ -31,36 +31,14 @@
}
}
-namespace sk_default {
-extern void srcover_srgb_srgb(
- uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc);
-}
-
-#if defined(SK_CPU_X86) && !defined(SK_BUILD_NO_OPTS)
-namespace sk_sse41 {
-extern void srcover_srgb_srgb(
- uint32_t* dst, const uint32_t* const srcStart, int ndst, const int nsrc);
-}
-#endif
-
-static SkString missmatch_message(std::string resourceName, std::string name, int x, int y,
+static SkString mismatch_message(std::string resourceName, int x, int y,
uint32_t src, uint32_t good, uint32_t bad) {
return SkStringPrintf(
- "%s - %s missmatch at %d, %d src: %08x good: %08x bad: %08x",
- resourceName.c_str(), name.c_str(), x, y, src, good, bad);
+ "%s - missmatch at %d, %d src: %08x good: %08x bad: %08x",
+ resourceName.c_str(), x, y, src, good, bad);
}
-using Spec = std::tuple<Blender, std::string>;
-
-static void test_blender(
- Spec spec,
- std::string resourceName,
- skiatest::Reporter* reporter)
-{
- Blender blender;
- std::string name;
- std::tie(blender, name) = spec;
-
+static void test_blender(std::string resourceName, skiatest::Reporter* reporter) {
std::string fileName = resourceName + ".png";
sk_sp<SkImage> image = GetResourceAsImage(fileName.c_str());
if (image == nullptr) {
@@ -88,11 +66,11 @@
sk_bzero(correctDst.get(), width * sizeof(uint32_t));
sk_bzero(testDst.get(), width * sizeof(uint32_t));
brute_force_srcover_srgb_srgb(correctDst.get(), src, width, width);
- blender(testDst.get(), src, width, width);
+ SkOpts:: srcover_srgb_srgb( testDst.get(), src, width, width);
for (int x = 0; x < width; x++) {
REPORTER_ASSERT_MESSAGE(
reporter, correctDst[x] == testDst[x],
- missmatch_message(resourceName, name, x, y, src[x], correctDst[x], testDst[x]));
+ mismatch_message(resourceName, x, y, src[x], correctDst[x], testDst[x]));
if (correctDst[x] != testDst[x]) break;
}
src += width;
@@ -100,23 +78,12 @@
}
DEF_TEST(SkBlend_optsCheck, reporter) {
- std::vector<Spec> specs = {
- Spec{sk_default::srcover_srgb_srgb, "default"},
- };
- #if defined(SK_CPU_X86) && !defined(SK_BUILD_NO_OPTS)
- if (SkCpu::Supports(SkCpu::SSE41)) {
- specs.push_back(Spec{sk_sse41::srcover_srgb_srgb, "sse41", });
- }
- #endif
-
std::vector<std::string> testResources = {
"yellow_rose", "baby_tux", "plane", "mandrill_512", "iconstrip"
};
- for (auto& spec : specs) {
- for (auto& resourceName : testResources) {
- test_blender(spec, resourceName, reporter);
- }
+ for (auto& resourceName : testResources) {
+ test_blender(resourceName, reporter);
}
}