return *seed;
}
+// I'm having better luck getting these to constant-propagate away as template parameters.
+template <bool kClamp, bool kWide>
struct PMFloatBench : public Benchmark {
- explicit PMFloatBench(bool clamp) : fClamp(clamp) {}
+ PMFloatBench() {}
- const char* onGetName() SK_OVERRIDE { return fClamp ? "SkPMFloat_clamp" : "SkPMFloat_get"; }
+ const char* onGetName() SK_OVERRIDE {
+ switch (kClamp << 1 | kWide) {
+ case 0: return "SkPMFloat_get_1x";
+ case 1: return "SkPMFloat_get_4x";
+ case 2: return "SkPMFloat_clamp_1x";
+ case 3: return "SkPMFloat_clamp_4x";
+ }
+ SkFAIL("unreachable");
+ return "oh bother";
+ }
bool isSuitableFor(Backend backend) SK_OVERRIDE { return backend == kNonRendering_Backend; }
void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
uint32_t junk = 0;
uint32_t seed = 0;
for (int i = 0; i < loops; i++) {
+ SkPMColor colors[4];
#ifdef SK_DEBUG
- // Our SkASSERTs will remind us that it's technically required that we premultiply.
- SkPMColor c = SkPreMultiplyColor(lcg_rand(&seed));
+ for (int i = 0; i < 4; i++) {
+ // Our SkASSERTs will remind us that it's technically required that we premultiply.
+ colors[i] = SkPreMultiplyColor(lcg_rand(&seed));
+ }
#else
// But it's a lot faster not to, and this code won't really mind the non-PM colors.
- SkPMColor c = lcg_rand(&seed);
+ (void)lcg_rand(&seed);
+ colors[0] = seed + 0;
+ colors[1] = seed + 1;
+ colors[2] = seed + 2;
+ colors[3] = seed + 3;
#endif
- SkPMFloat pmf = SkPMFloat::FromPMColor(c);
- SkPMColor back = fClamp ? pmf.clamped() : pmf.get();
- junk ^= back;
+
+ SkPMFloat floats[4];
+ if (kWide) {
+ SkPMFloat::From4PMColors(floats, colors);
+ } else {
+ for (int i = 0; i < 4; i++) {
+ floats[i] = SkPMFloat::FromPMColor(colors[i]);
+ }
+ }
+
+ SkPMColor back[4];
+ switch (kClamp << 1 | kWide) {
+ case 0: for (int i = 0; i < 4; i++) { back[i] = floats[i].get(); } break;
+ case 1: SkPMFloat::To4PMColors(back, floats); break;
+ case 2: for (int i = 0; i < 4; i++) { back[i] = floats[i].clamped(); } break;
+ case 3: SkPMFloat::ClampTo4PMColors(back, floats); break;
+ }
+ for (int i = 0; i < 4; i++) {
+ junk ^= back[i];
+ }
}
blackhole ^= junk;
}
-
- bool fClamp;
};
-DEF_BENCH(return new PMFloatBench( true);)
-DEF_BENCH(return new PMFloatBench(false);)
+
+// Extra () help DEF_BENCH not get confused by the comma inside the <>.
+DEF_BENCH(return (new PMFloatBench< true, true>);)
+DEF_BENCH(return (new PMFloatBench<false, true>);)
+DEF_BENCH(return (new PMFloatBench< true, false>);)
+DEF_BENCH(return (new PMFloatBench<false, false>);)
static SkPMFloat FromPMColor(SkPMColor c) { return SkPMFloat(c); }
static SkPMFloat FromARGB(float a, float r, float g, float b) { return SkPMFloat(a,r,g,b); }
+ // May be more efficient than one at a time. No special alignment assumed for SkPMColors.
+ static void From4PMColors(SkPMFloat floats[4], const SkPMColor colors[4]) {
+ // TODO: specialize
+ for (int i = 0; i < 4; i++) { floats[i] = FromPMColor(colors[i]); }
+ }
+
explicit SkPMFloat(SkPMColor);
SkPMFloat(float a, float r, float g, float b) {
// TODO: faster when specialized?
SkPMColor get() const; // May SkASSERT(this->isValid()). Some implementations may clamp.
SkPMColor clamped() const; // Will clamp all values to [0, 255]. Then may assert isValid().
+ // 4-at-a-time versions of get() and clamped(). Like From4PMColors(), no alignment assumed.
+ static void To4PMColors(SkPMColor colors[4], const SkPMFloat floats[4]) {
+ // TODO: specialize
+ for (int i = 0; i < 4; i++) { colors[i] = floats[i].get(); }
+ }
+ static void ClampTo4PMColors(SkPMColor colors[4], const SkPMFloat floats[4]) {
+ // TODO: specialize
+ for (int i = 0; i < 4; i++) { colors[i] = floats[i].clamped(); }
+ }
+
bool isValid() const {
return this->a() >= 0 && this->a() <= 255
&& this->r() >= 0 && this->r() <= this->a()
REPORTER_ASSERT(r, SkScalarNearlyEqual(38.25f, scaled.r()));
REPORTER_ASSERT(r, SkScalarNearlyEqual( 0.25f, scaled.g()));
REPORTER_ASSERT(r, SkScalarNearlyEqual( 0.00f, scaled.b()));
+
+ // Test 4-at-a-time conversions.
+ SkPMColor colors[4] = { 0xFF000000, 0xFFFF0000, 0xFF00FF00, 0xFF0000FF };
+ SkPMFloat floats[4];
+ SkPMFloat::From4PMColors(floats, colors);
+
+ SkPMColor back[4];
+ SkPMFloat::To4PMColors(back, floats);
+ for (int i = 0; i < 4; i++) {
+ REPORTER_ASSERT(r, back[i] == colors[i]);
+ }
+
+ SkPMFloat::ClampTo4PMColors(back, floats);
+ for (int i = 0; i < 4; i++) {
+ REPORTER_ASSERT(r, back[i] == colors[i]);
+ }
}