[ngatoy] Make an explicit ID class and simplify Cmd class

Bug: skia:11837
Change-Id: I44b8f02555c1ed7e2f1bf0872bf41f78d1eb5d25
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/417003
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 2aefdaf..48c92e6 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -2181,6 +2181,7 @@
         "experimental/ngatoy/Fake.h",
         "experimental/ngatoy/SortKey.h",
         "experimental/ngatoy/ngatoy.cpp",
+        "experimental/ngatoy/ngatypes.h",
       ]
       deps = [
         ":flags",
diff --git a/experimental/ngatoy/Cmds.cpp b/experimental/ngatoy/Cmds.cpp
index 6818e83..34eabad 100644
--- a/experimental/ngatoy/Cmds.cpp
+++ b/experimental/ngatoy/Cmds.cpp
@@ -12,15 +12,16 @@
 #include "include/effects/SkGradientShader.h"
 
 //------------------------------------------------------------------------------------------------
-RectCmd::RectCmd(int id,
+RectCmd::RectCmd(ID id,
                  uint32_t paintersOrder,
                  SkIRect r,
                  const FakePaint& p,
                  sk_sp<FakeMCBlob> state)
-    : Cmd(id, p.toID(), std::move(state))
+    : Cmd(id)
     , fPaintersOrder(paintersOrder)
     , fRect(r)
-    , fPaint(p) {
+    , fPaint(p)
+    , fMCState(std::move(state)) {
 }
 
 SortKey RectCmd::getKey() {
@@ -96,7 +97,9 @@
     return 0xFF == SkColorGetA(c);
 }
 
-void RectCmd::rasterize(uint32_t zBuffer[256][256], SkBitmap* dstBM, unsigned int z) const {
+void RectCmd::rasterize(uint32_t zBuffer[256][256], SkBitmap* dstBM) const {
+
+    unsigned int z = fPaintersOrder;
 
     for (int y = fRect.fTop; y < fRect.fBottom; ++y) {
         for (int x = fRect.fLeft; x < fRect.fRight; ++x) {
diff --git a/experimental/ngatoy/Cmds.h b/experimental/ngatoy/Cmds.h
index a9b685c..d14f15a 100644
--- a/experimental/ngatoy/Cmds.h
+++ b/experimental/ngatoy/Cmds.h
@@ -14,51 +14,48 @@
 #include "include/core/SkRect.h"
 
 #include "experimental/ngatoy/Fake.h"
+#include "experimental/ngatoy/ngatypes.h"
 
 class Cmd {
 public:
-    Cmd(int id, int materialID, sk_sp<FakeMCBlob> state)
-        : fID(id)
-        , fMaterialID(materialID)
-        , fMCState(std::move(state)) {
-    }
+    Cmd() : fID(ID::Invalid()) {}
+    Cmd(ID id) : fID(id) {}
     virtual ~Cmd() {}
 
-    int id() const { return fID; }
+    ID id() const { return fID; }
 
     virtual SortKey getKey() = 0;
 
-    const FakeMCBlob* state() const { return fMCState.get(); }
+    virtual const FakeMCBlob* state() const { return nullptr; }
 
     // To generate the actual image
     virtual void execute(FakeCanvas*) const = 0;
-    virtual void rasterize(uint32_t zBuffer[256][256], SkBitmap* dstBM, unsigned int z) const = 0;
+    virtual void rasterize(uint32_t zBuffer[256][256], SkBitmap* dstBM) const = 0;
 
     // To generate the expected image
     virtual void execute(SkCanvas*, const FakeMCBlob* priorState) const = 0;
     virtual void dump() const = 0;
 
 protected:
-    const int         fID;
-    int               fMaterialID;
-    sk_sp<FakeMCBlob> fMCState;
+    const ID fID;
 
 private:
 };
 
 class RectCmd : public Cmd {
 public:
-    RectCmd(int id, uint32_t paintersOrder, SkIRect, const FakePaint&, sk_sp<FakeMCBlob> state);
+    RectCmd(ID id, uint32_t paintersOrder, SkIRect, const FakePaint&, sk_sp<FakeMCBlob> state);
 
     SortKey getKey() override;
+    const FakeMCBlob* state() const override { return fMCState.get(); }
 
     void execute(FakeCanvas*) const override;
     void execute(SkCanvas* c, const FakeMCBlob* priorState) const override;
-    void rasterize(uint32_t zBuffer[256][256], SkBitmap* dstBM, unsigned int z) const override;
+    void rasterize(uint32_t zBuffer[256][256], SkBitmap* dstBM) const override;
 
     void dump() const override {
         SkDebugf("%d: drawRect %d %d %d %d -- %d",
-                 fID,
+                 fID.toInt(),
                  fRect.fLeft, fRect.fTop, fRect.fRight, fRect.fBottom,
                  fPaintersOrder);
     }
@@ -66,9 +63,10 @@
 protected:
 
 private:
-    uint32_t  fPaintersOrder;
-    SkIRect   fRect;
-    FakePaint fPaint;
+    uint32_t          fPaintersOrder;
+    SkIRect           fRect;
+    FakePaint         fPaint;
+    sk_sp<FakeMCBlob> fMCState;
 };
 
 #endif // Cmds_DEFINED
diff --git a/experimental/ngatoy/Fake.cpp b/experimental/ngatoy/Fake.cpp
index 1791509..cc597e7 100644
--- a/experimental/ngatoy/Fake.cpp
+++ b/experimental/ngatoy/Fake.cpp
@@ -75,7 +75,7 @@
     fTracker.push();
 }
 
-void FakeDevice::drawRect(int id, uint32_t paintersOrder, SkIRect r, FakePaint p) {
+void FakeDevice::drawRect(ID id, uint32_t paintersOrder, SkIRect r, FakePaint p) {
 
     sk_sp<FakeMCBlob> state = fTracker.snapState();
 
@@ -98,11 +98,11 @@
 
     this->sort();
     for (auto c : fSortedCmds) {
-        c->rasterize(fZBuffer, &fBM, c->getKey().depth());
+        c->rasterize(fZBuffer, &fBM);
     }
 }
 
-void FakeDevice::getOrder(std::vector<int>* ops) const {
+void FakeDevice::getOrder(std::vector<ID>* ops) const {
     SkASSERT(fFinalized);
 
 //    ops->reserve(fSortedCmds.size());
@@ -126,7 +126,7 @@
 }
 
 //-------------------------------------------------------------------------------------------------
-void FakeCanvas::drawRect(int id, SkIRect r, FakePaint p) {
+void FakeCanvas::drawRect(ID id, SkIRect r, FakePaint p) {
     SkASSERT(!fFinalized);
 
     fDeviceStack.back()->drawRect(id, this->nextZ(), r, p);
@@ -147,10 +147,10 @@
     }
 }
 
-std::vector<int> FakeCanvas::getOrder() const {
+std::vector<ID> FakeCanvas::getOrder() const {
     SkASSERT(fFinalized);
 
-    std::vector<int> ops;
+    std::vector<ID> ops;
 
     for (auto& d : fDeviceStack) {
         d->getOrder(&ops);
diff --git a/experimental/ngatoy/Fake.h b/experimental/ngatoy/Fake.h
index a3b75e1..296e10a 100644
--- a/experimental/ngatoy/Fake.h
+++ b/experimental/ngatoy/Fake.h
@@ -5,6 +5,7 @@
 #define Fake_DEFINED
 
 #include "experimental/ngatoy/SortKey.h"
+#include "experimental/ngatoy/ngatypes.h"
 #include "include/core/SkBitmap.h"
 #include "include/core/SkColor.h"
 #include "include/core/SkMatrix.h"
@@ -254,7 +255,7 @@
     ~FakeDevice() {}
 
     void save();
-    void drawRect(int id, uint32_t z, SkIRect, FakePaint);
+    void drawRect(ID id, uint32_t z, SkIRect, FakePaint);
     void clipRect(SkIRect r);
     void translate(SkIPoint trans) {
         fTracker.translate(trans);
@@ -264,7 +265,7 @@
 
     void finalize();
 
-    void getOrder(std::vector<int>*) const;
+    void getOrder(std::vector<ID>*) const;
     sk_sp<FakeMCBlob> snapState() { return fTracker.snapState(); }
 
 protected:
@@ -297,7 +298,7 @@
         fDeviceStack.back()->save();
     }
 
-    void drawRect(int id, SkIRect, FakePaint);
+    void drawRect(ID id, SkIRect, FakePaint);
 
     void clipRect(SkIRect);
 
@@ -314,7 +315,7 @@
 
     void finalize();
 
-    std::vector<int> getOrder() const;
+    std::vector<ID> getOrder() const;
     sk_sp<FakeMCBlob> snapState() {
         return fDeviceStack.back()->snapState();
     }
diff --git a/experimental/ngatoy/ngatoy.cpp b/experimental/ngatoy/ngatoy.cpp
index 53ad24a..3a8e6cb 100644
--- a/experimental/ngatoy/ngatoy.cpp
+++ b/experimental/ngatoy/ngatoy.cpp
@@ -215,8 +215,8 @@
     SkASSERT(state0 == state4);
 }
 
-static void check_order(const std::vector<int>& actualOrder,
-                        const std::vector<int>& expectedOrder) {
+static void check_order(const std::vector<ID>& actualOrder,
+                        const std::vector<ID>& expectedOrder) {
     if (expectedOrder.size() != actualOrder.size()) {
         exitf("Op count mismatch. Expected %d - got %d\n",
               expectedOrder.size(),
@@ -227,23 +227,23 @@
         SkDebugf("order mismatch:\n");
         SkDebugf("E %d: ", expectedOrder.size());
         for (auto t : expectedOrder) {
-            SkDebugf("%d", t);
+            SkDebugf("%d", t.toInt());
         }
         SkDebugf("\n");
 
         SkDebugf("A %d: ", actualOrder.size());
         for (auto t : actualOrder) {
-            SkDebugf("%d", t);
+            SkDebugf("%d", t.toInt());
         }
         SkDebugf("\n");
     }
 }
 
-typedef int (*PFTest)(std::vector<const Cmd*>* test, std::vector<int>* expectedOrder);
+typedef int (*PFTest)(std::vector<const Cmd*>* test, std::vector<ID>* expectedOrder);
 
 static void sort_test(PFTest testcase) {
     std::vector<const Cmd*> test;
-    std::vector<int> expectedOrder;
+    std::vector<ID> expectedOrder;
     int testID = testcase(&test, &expectedOrder);
 
 
@@ -266,81 +266,81 @@
 
     fake.finalize();
 
-    std::vector<int> actualOrder = fake.getOrder();
+    std::vector<ID> actualOrder = fake.getOrder();
     check_order(actualOrder, expectedOrder);
 
     save_files(testID, expectedBM, actualBM);
 }
 
 // Simple test - green rect should appear atop the red rect
-static int test1(std::vector<const Cmd*>* test, std::vector<int>* expectedOrder) {
+static int test1(std::vector<const Cmd*>* test, std::vector<ID>* expectedOrder) {
     // front-to-back order bc all opaque
-    expectedOrder->push_back(1);
-    expectedOrder->push_back(0);
+    expectedOrder->push_back(ID(1));
+    expectedOrder->push_back(ID(0));
 
     //---------------------------------------------------------------------------------------------
     FakeStateTracker s;
     sk_sp<FakeMCBlob> state = s.snapState();
 
     SkIRect r{0, 0, 100, 100};
-    test->push_back(new RectCmd(0, kInvalidZ, r.makeOffset(8, 8),   FakePaint(SK_ColorRED),   state));
-    test->push_back(new RectCmd(1, kInvalidZ, r.makeOffset(48, 48), FakePaint(SK_ColorGREEN), state));
+    test->push_back(new RectCmd(ID(0), kInvalidZ, r.makeOffset(8, 8),   FakePaint(SK_ColorRED),   state));
+    test->push_back(new RectCmd(ID(1), kInvalidZ, r.makeOffset(48, 48), FakePaint(SK_ColorGREEN), state));
 
     return 1;
 }
 
 // Simple test - blue rect atop green rect atop red rect
-static int test2(std::vector<const Cmd*>* test, std::vector<int>* expectedOrder) {
+static int test2(std::vector<const Cmd*>* test, std::vector<ID>* expectedOrder) {
     // front-to-back order bc all opaque
-    expectedOrder->push_back(2);
-    expectedOrder->push_back(1);
-    expectedOrder->push_back(0);
+    expectedOrder->push_back(ID(2));
+    expectedOrder->push_back(ID(1));
+    expectedOrder->push_back(ID(0));
 
     //---------------------------------------------------------------------------------------------
     FakeStateTracker s;
     sk_sp<FakeMCBlob> state = s.snapState();
 
     SkIRect r{0, 0, 100, 100};
-    test->push_back(new RectCmd(0, kInvalidZ, r.makeOffset(8, 8),   FakePaint(SK_ColorRED),   state));
-    test->push_back(new RectCmd(1, kInvalidZ, r.makeOffset(48, 48), FakePaint(SK_ColorGREEN), state));
-    test->push_back(new RectCmd(2, kInvalidZ, r.makeOffset(98, 98), FakePaint(SK_ColorBLUE),  state));
+    test->push_back(new RectCmd(ID(0), kInvalidZ, r.makeOffset(8, 8),   FakePaint(SK_ColorRED),   state));
+    test->push_back(new RectCmd(ID(1), kInvalidZ, r.makeOffset(48, 48), FakePaint(SK_ColorGREEN), state));
+    test->push_back(new RectCmd(ID(2), kInvalidZ, r.makeOffset(98, 98), FakePaint(SK_ColorBLUE),  state));
     return 2;
 }
 
 // Transparency test - opaque blue rect atop transparent green rect atop opaque red rect
-static int test3(std::vector<const Cmd*>* test, std::vector<int>* expectedOrder) {
+static int test3(std::vector<const Cmd*>* test, std::vector<ID>* expectedOrder) {
     // opaque draws are first and are front-to-back. Transparent draw is last.
-    expectedOrder->push_back(2);
-    expectedOrder->push_back(0);
-    expectedOrder->push_back(1);
+    expectedOrder->push_back(ID(2));
+    expectedOrder->push_back(ID(0));
+    expectedOrder->push_back(ID(1));
 
     //---------------------------------------------------------------------------------------------
     FakeStateTracker s;
     sk_sp<FakeMCBlob> state = s.snapState();
 
     SkIRect r{0, 0, 100, 100};
-    test->push_back(new RectCmd(0, kInvalidZ, r.makeOffset(8, 8),   FakePaint(SK_ColorRED),  state));
-    test->push_back(new RectCmd(1, kInvalidZ, r.makeOffset(48, 48), FakePaint(0x8000FF00),   state));
-    test->push_back(new RectCmd(2, kInvalidZ, r.makeOffset(98, 98), FakePaint(SK_ColorBLUE), state));
+    test->push_back(new RectCmd(ID(0), kInvalidZ, r.makeOffset(8, 8),   FakePaint(SK_ColorRED),  state));
+    test->push_back(new RectCmd(ID(1), kInvalidZ, r.makeOffset(48, 48), FakePaint(0x8000FF00),   state));
+    test->push_back(new RectCmd(ID(2), kInvalidZ, r.makeOffset(98, 98), FakePaint(SK_ColorBLUE), state));
     return 3;
 }
 
 // Multi-transparency test - transparent blue rect atop transparent green rect atop
 // transparent red rect
-static int test4(std::vector<const Cmd*>* test, std::vector<int>* expectedOrder) {
+static int test4(std::vector<const Cmd*>* test, std::vector<ID>* expectedOrder) {
     // All in back-to-front order bc they're all transparent
-    expectedOrder->push_back(0);
-    expectedOrder->push_back(1);
-    expectedOrder->push_back(2);
+    expectedOrder->push_back(ID(0));
+    expectedOrder->push_back(ID(1));
+    expectedOrder->push_back(ID(2));
 
     //---------------------------------------------------------------------------------------------
     FakeStateTracker s;
     sk_sp<FakeMCBlob> state = s.snapState();
 
     SkIRect r{0, 0, 100, 100};
-    test->push_back(new RectCmd(0, kInvalidZ, r.makeOffset(8, 8),   FakePaint(0x80FF0000), state));
-    test->push_back(new RectCmd(1, kInvalidZ, r.makeOffset(48, 48), FakePaint(0x8000FF00), state));
-    test->push_back(new RectCmd(2, kInvalidZ, r.makeOffset(98, 98), FakePaint(0x800000FF), state));
+    test->push_back(new RectCmd(ID(0), kInvalidZ, r.makeOffset(8, 8),   FakePaint(0x80FF0000), state));
+    test->push_back(new RectCmd(ID(1), kInvalidZ, r.makeOffset(48, 48), FakePaint(0x8000FF00), state));
+    test->push_back(new RectCmd(ID(2), kInvalidZ, r.makeOffset(98, 98), FakePaint(0x800000FF), state));
     return 4;
 }
 
@@ -350,15 +350,15 @@
 // Which gets sorted to:
 //   normal2, normal1, linear2, linear1, radial2, radial1
 // So, front to back w/in each material type.
-static int test5(std::vector<const Cmd*>* test, std::vector<int>* expectedOrder) {
+static int test5(std::vector<const Cmd*>* test, std::vector<ID>* expectedOrder) {
     // Note: This pushes sorting by material above sorting by Z. Thus we'll get less front to
     // back benefit.
-    expectedOrder->push_back(3);
-    expectedOrder->push_back(0);
-    expectedOrder->push_back(4);
-    expectedOrder->push_back(1);
-    expectedOrder->push_back(5);
-    expectedOrder->push_back(2);
+    expectedOrder->push_back(ID(3));
+    expectedOrder->push_back(ID(0));
+    expectedOrder->push_back(ID(4));
+    expectedOrder->push_back(ID(1));
+    expectedOrder->push_back(ID(5));
+    expectedOrder->push_back(ID(2));
 
     //---------------------------------------------------------------------------------------------
     FakeStateTracker s;
@@ -367,24 +367,24 @@
     FakePaint p;
 
     SkIRect r{0, 0, 100, 100};
-    test->push_back(new RectCmd(0, kInvalidZ, r.makeOffset(8, 8),     FakePaint(SK_ColorRED),  state));
+    test->push_back(new RectCmd(ID(0), kInvalidZ, r.makeOffset(8, 8),     FakePaint(SK_ColorRED),  state));
     p.setLinear(SK_ColorGREEN,   SK_ColorWHITE);
-    test->push_back(new RectCmd(1, kInvalidZ, r.makeOffset(48, 48),   p,                       state));
+    test->push_back(new RectCmd(ID(1), kInvalidZ, r.makeOffset(48, 48),   p,                       state));
     p.setRadial(SK_ColorBLUE,    SK_ColorBLACK);
-    test->push_back(new RectCmd(2, kInvalidZ, r.makeOffset(98, 98),   p,                       state));
-    test->push_back(new RectCmd(3, kInvalidZ, r.makeOffset(148, 148), FakePaint(SK_ColorCYAN), state));
+    test->push_back(new RectCmd(ID(2), kInvalidZ, r.makeOffset(98, 98),   p,                       state));
+    test->push_back(new RectCmd(ID(3), kInvalidZ, r.makeOffset(148, 148), FakePaint(SK_ColorCYAN), state));
     p.setLinear(SK_ColorMAGENTA, SK_ColorWHITE);
-    test->push_back(new RectCmd(4, kInvalidZ, r.makeOffset(148, 8),   p,                       state));
+    test->push_back(new RectCmd(ID(4), kInvalidZ, r.makeOffset(148, 8),   p,                       state));
     p.setRadial(SK_ColorYELLOW,  SK_ColorBLACK);
-    test->push_back(new RectCmd(5, kInvalidZ, r.makeOffset(8, 148),   p,                       state));
+    test->push_back(new RectCmd(ID(5), kInvalidZ, r.makeOffset(8, 148),   p,                       state));
     return 5;
 }
 
 // simple clipping test - 1 clip w/ two opaque rects
-static int test6(std::vector<const Cmd*>* test, std::vector<int>* expectedOrder) {
+static int test6(std::vector<const Cmd*>* test, std::vector<ID>* expectedOrder) {
     // The expected is front to back after the clip
-    expectedOrder->push_back(1);
-    expectedOrder->push_back(0);
+    expectedOrder->push_back(ID(1));
+    expectedOrder->push_back(ID(0));
 
     //---------------------------------------------------------------------------------------------
     FakeStateTracker s;
@@ -393,22 +393,22 @@
     sk_sp<FakeMCBlob> state = s.snapState();
 
     SkIRect r{0, 0, 100, 100};
-    test->push_back(new RectCmd(0, kInvalidZ, r.makeOffset(8, 8),   FakePaint(SK_ColorRED),   state));
-    test->push_back(new RectCmd(1, kInvalidZ, r.makeOffset(48, 48), FakePaint(SK_ColorGREEN), state));
+    test->push_back(new RectCmd(ID(0), kInvalidZ, r.makeOffset(8, 8),   FakePaint(SK_ColorRED),   state));
+    test->push_back(new RectCmd(ID(1), kInvalidZ, r.makeOffset(48, 48), FakePaint(SK_ColorGREEN), state));
 
     return 6;
 }
 
 // more complicated clipping w/ opaque draws -> should reorder
-static int test7(std::vector<const Cmd*>* test, std::vector<int>* expectedOrder) {
+static int test7(std::vector<const Cmd*>* test, std::vector<ID>* expectedOrder) {
     // The expected is front to back modulated by the two clip states
-    expectedOrder->push_back(5);
-    expectedOrder->push_back(4);
-    expectedOrder->push_back(1);
-    expectedOrder->push_back(0);
+    expectedOrder->push_back(ID(5));
+    expectedOrder->push_back(ID(4));
+    expectedOrder->push_back(ID(1));
+    expectedOrder->push_back(ID(0));
 
-    expectedOrder->push_back(3);
-    expectedOrder->push_back(2);
+    expectedOrder->push_back(ID(3));
+    expectedOrder->push_back(ID(2));
 
     //---------------------------------------------------------------------------------------------
     FakeStateTracker s;
@@ -417,21 +417,21 @@
     sk_sp<FakeMCBlob> state = s.snapState();
 
     SkIRect r{0, 0, 100, 100};
-    test->push_back(new RectCmd(0, kInvalidZ, r.makeOffset(8, 8),     FakePaint(SK_ColorRED),     state));
-    test->push_back(new RectCmd(1, kInvalidZ, r.makeOffset(48, 48),   FakePaint(SK_ColorGREEN),   state));
+    test->push_back(new RectCmd(ID(0), kInvalidZ, r.makeOffset(8, 8),     FakePaint(SK_ColorRED),     state));
+    test->push_back(new RectCmd(ID(1), kInvalidZ, r.makeOffset(48, 48),   FakePaint(SK_ColorGREEN),   state));
 
     s.push();
     s.clipRect(SkIRect::MakeXYWH(0, 85, 256, 86));  // intersect w/ the middle third in y
     state = s.snapState();
 
-    test->push_back(new RectCmd(2, kInvalidZ, r.makeOffset(98, 98),   FakePaint(SK_ColorBLUE),    state));
-    test->push_back(new RectCmd(3, kInvalidZ, r.makeOffset(148, 148), FakePaint(SK_ColorCYAN),    state));
+    test->push_back(new RectCmd(ID(2), kInvalidZ, r.makeOffset(98, 98),   FakePaint(SK_ColorBLUE),    state));
+    test->push_back(new RectCmd(ID(3), kInvalidZ, r.makeOffset(148, 148), FakePaint(SK_ColorCYAN),    state));
 
     s.pop();
     state = s.snapState();
 
-    test->push_back(new RectCmd(4, kInvalidZ, r.makeOffset(148, 8),   FakePaint(SK_ColorMAGENTA), state));
-    test->push_back(new RectCmd(5, kInvalidZ, r.makeOffset(8, 148),   FakePaint(SK_ColorYELLOW),  state));
+    test->push_back(new RectCmd(ID(4), kInvalidZ, r.makeOffset(148, 8),   FakePaint(SK_ColorMAGENTA), state));
+    test->push_back(new RectCmd(ID(5), kInvalidZ, r.makeOffset(8, 148),   FakePaint(SK_ColorYELLOW),  state));
 
     return 7;
 }
diff --git a/experimental/ngatoy/ngatypes.h b/experimental/ngatoy/ngatypes.h
new file mode 100644
index 0000000..bc1c22c
--- /dev/null
+++ b/experimental/ngatoy/ngatypes.h
@@ -0,0 +1,35 @@
+// 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 NGATypes_DEFINED
+#define NGATypes_DEFINED
+
+#include "include/gpu/GrTypes.h"
+
+// This is strictly used to check if we get the order of draw operations we expected. It is
+// pretty much the same as painters order though.
+class ID {
+public:
+    explicit ID(int id) : fID(id) {
+        SkASSERT(id != -1);
+    }
+
+    static ID Invalid() {
+        return ID();
+    }
+
+    bool isValid() const { return fID != -1; }
+
+    bool operator==(ID other) const { return fID == other.fID; }
+
+    int toInt() const { return fID; }
+
+private:
+    ID() : fID(-1) {}
+
+    int fID;
+};
+
+#endif
+
+