aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/SkRasterPipeline.cpp6
-rw-r--r--src/core/SkRasterPipeline.h2
-rw-r--r--src/opts/SkXbyak.cpp97
3 files changed, 105 insertions, 0 deletions
diff --git a/src/core/SkRasterPipeline.cpp b/src/core/SkRasterPipeline.cpp
index 7b3d49d413..8d0840f7fb 100644
--- a/src/core/SkRasterPipeline.cpp
+++ b/src/core/SkRasterPipeline.cpp
@@ -27,6 +27,12 @@ void SkRasterPipeline::run(size_t x, size_t y, size_t n) const {
}
std::function<void(size_t, size_t, size_t)> SkRasterPipeline::compile() const {
+#ifdef SK_XBYAK
+ if (auto fn = this->jit()) {
+ SkDebugf("Jitted with xbyak!\n");
+ return fn;
+ }
+#endif
return SkOpts::compile_pipeline(fStages.data(), SkToInt(fStages.size()));
}
diff --git a/src/core/SkRasterPipeline.h b/src/core/SkRasterPipeline.h
index e6c99159fa..b73f62631d 100644
--- a/src/core/SkRasterPipeline.h
+++ b/src/core/SkRasterPipeline.h
@@ -126,6 +126,8 @@ public:
void append_from_srgb(SkAlphaType);
private:
+ std::function<void(size_t, size_t, size_t)> jit() const;
+
std::vector<Stage> fStages;
};
diff --git a/src/opts/SkXbyak.cpp b/src/opts/SkXbyak.cpp
new file mode 100644
index 0000000000..12f5200939
--- /dev/null
+++ b/src/opts/SkXbyak.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkCpu.h"
+#include "SkRasterPipeline.h"
+#include <memory>
+
+#if defined(__clang__)
+ #pragma clang diagnostic ignored "-Wduplicate-enum"
+#endif
+#define XBYAK_NO_OP_NAMES // xor(), not(), etc. -> xor_(), not_(), etc.
+#include "xbyak/xbyak.h"
+
+namespace {
+
+ struct Pipeline : public Xbyak::CodeGenerator {
+
+ static std::shared_ptr<Pipeline> Create(const SkRasterPipeline::Stage* stages, int n) {
+ if (!SkCpu::Supports(SkCpu::HSW)) {
+ // TODO: other targets?
+ return nullptr;
+ }
+
+ bool supported = true;
+ auto pipeline = std::make_shared<Pipeline>(stages, n, &supported);
+ if (supported) {
+ return pipeline;
+ }
+ return nullptr;
+ }
+
+ Pipeline(const SkRasterPipeline::Stage* stages, int n, bool* supported) {
+ // Set up some register name aliases.
+ //auto x = rdi, y = rsi, tail = rdx;
+ auto r = ymm0, g = ymm1, b = ymm2, a = ymm3,
+ dr = ymm4, dg = ymm5, db = ymm6, da = ymm7;
+
+ Xbyak::Label floatOneStorage;
+ vbroadcastss(ymm8, ptr[rip + floatOneStorage]);
+
+ // TODO: set up (x+0.5,y+0.5) in (r,g)
+ vxorps(r,r);
+ vxorps(g,g);
+ vxorps(b,b);
+ vxorps(a,a);
+ vxorps(dr,dr);
+ vxorps(dg,dg);
+ vxorps(db,db);
+ vxorps(da,da);
+
+ for (int i = 0; i < n; i++) {
+ switch(stages[i].stage) {
+
+ default:
+ *supported = false;
+ return;
+ }
+ }
+
+ ret();
+ L(floatOneStorage); df(1.0f);
+ }
+
+ void df(float f) {
+ union { float f; uint32_t x; } pun = {f};
+ dd(pun.x);
+ }
+ };
+
+} // namespace
+
+std::function<void(size_t, size_t, size_t)> SkRasterPipeline::jit() const {
+ try {
+ if (auto pipeline = Pipeline::Create(fStages.data(), SkToInt(fStages.size()))) {
+ return [pipeline] (size_t x, size_t y, size_t n) {
+ auto call = pipeline->getCode<void(*)(size_t, size_t, size_t)>();
+ while (n >= 8) {
+ call(x,y,0);
+ x += 8;
+ n -= 8;
+ }
+ if (n) {
+ call(x,y,n);
+ }
+ };
+ }
+ SkDebugf("Cannot yet JIT with xbyak:\n");
+ this->dump();
+ return nullptr;
+ } catch(...) {
+ return nullptr;
+ }
+}