Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2016 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef GrSwizzle_DEFINED
      9 #define GrSwizzle_DEFINED
     10 
     11 #include "GrColor.h"
     12 #include "SkRandom.h"
     13 
     14 /** Represents a rgba swizzle. It can be converted either into a string or a eight bit int.
     15     Currently there is no way to specify an arbitrary swizzle, just some static swizzles and an
     16     assignment operator. That could be relaxed. */
     17 class GrSwizzle {
     18 public:
     19     GrSwizzle() { *this = RGBA(); }
     20 
     21     GrSwizzle(const GrSwizzle& that) { *this = that; }
     22 
     23     GrSwizzle& operator=(const GrSwizzle& that) {
     24         memcpy(this, &that, sizeof(GrSwizzle));
     25         return *this;
     26     }
     27 
     28     /** Recreates a GrSwizzle from the output of asKey() */
     29     void setFromKey(uint8_t key) {
     30         fKey = key;
     31         for (int i = 0; i < 4; ++i) {
     32             fSwiz[i] = IdxToChar(key & 3);
     33             key >>= 2;
     34         }
     35         SkASSERT(fSwiz[4] == 0);
     36     }
     37 
     38     bool operator==(const GrSwizzle& that) const { return this->asUInt() == that.asUInt(); }
     39 
     40     bool operator!=(const GrSwizzle& that) const { return !(*this == that); }
     41 
     42     /** Compact representation of the swizzle suitable for a key. */
     43     uint8_t asKey() const { return fKey; }
     44 
     45     /** 4 char null terminated string consisting only of chars 'r', 'g', 'b', 'a'. */
     46     const char* c_str() const { return fSwiz; }
     47 
     48     /** Applies this swizzle to the input color and returns the swizzled color. */
     49     GrColor applyTo(GrColor color) const {
     50         int idx;
     51         uint32_t key = fKey;
     52         // Index of the input color that should be mapped to output r.
     53         idx = (key & 3);
     54         uint32_t outR = (color >> idx * 8)  & 0xFF;
     55         key >>= 2;
     56         idx = (key & 3);
     57         uint32_t outG = (color >> idx * 8)  & 0xFF;
     58         key >>= 2;
     59         idx = (key & 3);
     60         uint32_t outB = (color >> idx * 8)  & 0xFF;
     61         key >>= 2;
     62         idx = (key & 3);
     63         uint32_t outA = (color >> idx * 8)  & 0xFF;
     64         return GrColorPackRGBA(outR, outG, outB, outA);
     65     }
     66 
     67     static const GrSwizzle& RGBA() {
     68         static GrSwizzle gRGBA("rgba");
     69         return gRGBA;
     70     }
     71 
     72     static const GrSwizzle& AAAA() {
     73         static GrSwizzle gAAAA("aaaa");
     74         return gAAAA;
     75     }
     76 
     77     static const GrSwizzle& RRRR() {
     78         static GrSwizzle gRRRR("rrrr");
     79         return gRRRR;
     80     }
     81 
     82     static const GrSwizzle& BGRA() {
     83         static GrSwizzle gBGRA("bgra");
     84         return gBGRA;
     85     }
     86 
     87     static const GrSwizzle& CreateRandom(SkRandom* random) {
     88         switch (random->nextU() % 4) {
     89             case 0:
     90                 return RGBA();
     91             case 1:
     92                 return BGRA();
     93             case 2:
     94                 return RRRR();
     95             case 3:
     96                 return AAAA();
     97             default:
     98                 SkFAIL("Mod is broken?!?");
     99                 return RGBA();
    100         }
    101     }
    102 
    103 private:
    104     char fSwiz[5];
    105     uint8_t fKey;
    106 
    107     static int CharToIdx(char c) {
    108         switch (c) {
    109             case 'r':
    110                 return (GrColor_SHIFT_R / 8);
    111             case 'g':
    112                 return (GrColor_SHIFT_G / 8);
    113             case 'b':
    114                 return (GrColor_SHIFT_B / 8);
    115             case 'a':
    116                 return (GrColor_SHIFT_A / 8);
    117             default:
    118                 SkFAIL("Invalid swizzle char");
    119                 return 0;
    120         }
    121     }
    122 
    123     static /* constexpr */ char IToC(int idx) {
    124         return (8*idx) == GrColor_SHIFT_R ? 'r' :
    125                (8*idx) == GrColor_SHIFT_G ? 'g' :
    126                (8*idx) == GrColor_SHIFT_B ? 'b' : 'a';
    127     }
    128 
    129     static char IdxToChar(int c) {
    130         // Hopefully this array gets computed at compile time.
    131         static const char gStr[4] = { IToC(0), IToC(1), IToC(2), IToC(3) };
    132         return gStr[c];
    133     }
    134 
    135     explicit GrSwizzle(const char* str) {
    136         SkASSERT(strlen(str) == 4);
    137         fSwiz[0] = str[0];
    138         fSwiz[1] = str[1];
    139         fSwiz[2] = str[2];
    140         fSwiz[3] = str[3];
    141         fSwiz[4] = 0;
    142         fKey = SkToU8(CharToIdx(fSwiz[0]) | (CharToIdx(fSwiz[1]) << 2) |
    143                       (CharToIdx(fSwiz[2]) << 4) | (CharToIdx(fSwiz[3]) << 6));
    144     }
    145 
    146     uint32_t* asUIntPtr() { return SkTCast<uint32_t*>(fSwiz); }
    147     uint32_t asUInt() const { return *SkTCast<const uint32_t*>(fSwiz); }
    148 
    149     GR_STATIC_ASSERT(sizeof(char[4]) == sizeof(uint32_t));
    150 };
    151 
    152 #endif
    153