Add GrTFlagsMask<> wrapper for C++11 bitfield enums

Previously, operator& for enum class bitfields was reserved only to
return a bool. e.g:

  if (flags & Flags::kFlag)

This change adds a new template class GrTFlagsMask<> that gets
instantiated by operator~ and allows us to write expressions like:

  flags &= ~Flags::kFlag
  (flags & ~Flags::kFlag1) | Flags::kFlag2

BUG=skia:

Change-Id: I21e5eb9304135e82cdda459e8a833a3489f6beaf
Reviewed-on: https://skia-review.googlesource.com/8563
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/include/gpu/GrTypes.h b/include/gpu/GrTypes.h
index 330aefd..654febd 100644
--- a/include/gpu/GrTypes.h
+++ b/include/gpu/GrTypes.h
@@ -54,24 +54,74 @@
     friend X operator &(X a, T b); \
 
 /**
+ * Wraps a C++11 enum that we use as a bitfield, and enables a limited amount of
+ * masking with type safety. Instantiated with the ~ operator.
+ */
+template<typename TFlags> class GrTFlagsMask {
+public:
+    constexpr explicit GrTFlagsMask(TFlags value) : GrTFlagsMask(static_cast<int>(value)) {}
+    constexpr explicit GrTFlagsMask(int value) : fValue(value) {}
+    constexpr int value() const { return fValue; }
+private:
+    const int fValue;
+};
+
+// Or-ing a mask always returns another mask.
+template<typename TFlags> constexpr GrTFlagsMask<TFlags> operator|(GrTFlagsMask<TFlags> a,
+                                                                   GrTFlagsMask<TFlags> b) {
+    return GrTFlagsMask<TFlags>(a.value() | b.value());
+}
+template<typename TFlags> constexpr GrTFlagsMask<TFlags> operator|(GrTFlagsMask<TFlags> a,
+                                                                   TFlags b) {
+    return GrTFlagsMask<TFlags>(a.value() | static_cast<int>(b));
+}
+template<typename TFlags> constexpr GrTFlagsMask<TFlags> operator|(TFlags a,
+                                                                   GrTFlagsMask<TFlags> b) {
+    return GrTFlagsMask<TFlags>(static_cast<int>(a) | b.value());
+}
+template<typename TFlags> inline GrTFlagsMask<TFlags>& operator|=(GrTFlagsMask<TFlags>& a,
+                                                                  GrTFlagsMask<TFlags> b) {
+    return (a = a | b);
+}
+
+// And-ing two masks returns another mask; and-ing one with regular flags returns flags.
+template<typename TFlags> constexpr GrTFlagsMask<TFlags> operator&(GrTFlagsMask<TFlags> a,
+                                                                   GrTFlagsMask<TFlags> b) {
+    return GrTFlagsMask<TFlags>(a.value() & b.value());
+}
+template<typename TFlags> constexpr TFlags operator&(GrTFlagsMask<TFlags> a, TFlags b) {
+    return static_cast<TFlags>(a.value() & static_cast<int>(b));
+}
+template<typename TFlags> constexpr TFlags operator&(TFlags a, GrTFlagsMask<TFlags> b) {
+    return static_cast<TFlags>(static_cast<int>(a) & b.value());
+}
+template<typename TFlags> inline TFlags& operator&=(TFlags& a, GrTFlagsMask<TFlags> b) {
+    return (a = a & b);
+}
+
+/**
  * Defines bitwise operators that make it possible to use an enum class as a
- * very basic bitfield.
+ * basic bitfield.
  */
 #define GR_MAKE_BITFIELD_CLASS_OPS(X) \
-    inline X operator |(X a, X b) { \
-        return (X) ((int)a | (int)b); \
+    constexpr GrTFlagsMask<X> operator~(X a) { \
+        return GrTFlagsMask<X>(~static_cast<int>(a)); \
     } \
-    inline X& operator |=(X& a, X b) { \
+    constexpr X operator|(X a, X b) { \
+        return static_cast<X>(static_cast<int>(a) | static_cast<int>(b)); \
+    } \
+    inline X& operator|=(X& a, X b) { \
         return (a = a | b); \
     } \
-    inline bool operator &(X a, X b) { \
-        return SkToBool((int)a & (int)b); \
-    }
+    constexpr bool operator&(X a, X b) { \
+        return SkToBool(static_cast<int>(a) & static_cast<int>(b)); \
+    } \
 
 #define GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(X) \
-    friend X operator |(X a, X b); \
-    friend X& operator |=(X& a, X b); \
-    friend bool operator &(X a, X b);
+    friend constexpr GrTFlagsMask<X> operator ~(X); \
+    friend constexpr X operator |(X, X); \
+    friend X& operator |=(X&, X); \
+    friend constexpr bool operator &(X, X);
 
 ////////////////////////////////////////////////////////////////////////////////