blob: ecb17bdcce129f77e64dfaa6f6f5b24e15eb3bdc [file] [log] [blame]
bsalomoncdee0092016-01-08 13:20:12 -08001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/private/SkColorData.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040012#include "src/gpu/GrColor.h"
bsalomoncdee0092016-01-08 13:20:12 -080013
Brian Salomon217522c2019-06-11 15:55:30 -040014class SkRasterPipeline;
15
16/** Represents a rgba swizzle. It can be converted either into a string or a eight bit int. */
bsalomoncdee0092016-01-08 13:20:12 -080017class GrSwizzle {
18public:
Brian Salomon21511652018-10-17 08:30:51 -040019 constexpr GrSwizzle() : GrSwizzle("rgba") {}
Brian Salomon217522c2019-06-11 15:55:30 -040020 explicit constexpr GrSwizzle(const char c[4]);
bsalomoncdee0092016-01-08 13:20:12 -080021
Brian Salomon217522c2019-06-11 15:55:30 -040022 constexpr GrSwizzle(const GrSwizzle&);
23 constexpr GrSwizzle& operator=(const GrSwizzle& that);
bsalomoncdee0092016-01-08 13:20:12 -080024
Brian Salomonf30b1c12019-06-20 12:25:02 -040025 static constexpr GrSwizzle Concat(const GrSwizzle& a, const GrSwizzle& b);
26
bsalomon7f9b2e42016-01-12 13:29:26 -080027 /** Recreates a GrSwizzle from the output of asKey() */
Brian Salomon217522c2019-06-11 15:55:30 -040028 constexpr void setFromKey(uint16_t key);
Brian Salomonf30b1c12019-06-20 12:25:02 -040029
Brian Salomon21511652018-10-17 08:30:51 -040030 constexpr bool operator==(const GrSwizzle& that) const { return fKey == that.fKey; }
31 constexpr bool operator!=(const GrSwizzle& that) const { return !(*this == that); }
bsalomoncdee0092016-01-08 13:20:12 -080032
33 /** Compact representation of the swizzle suitable for a key. */
Greg Danielf259b8b2019-02-14 09:03:43 -050034 constexpr uint16_t asKey() const { return fKey; }
bsalomoncdee0092016-01-08 13:20:12 -080035
Brian Salomonf30b1c12019-06-20 12:25:02 -040036 /** 4 char null terminated string consisting only of chars 'r', 'g', 'b', 'a', '0', and '1'. */
Brian Salomon217522c2019-06-11 15:55:30 -040037 constexpr const char* c_str() const { return fSwiz; }
bsalomoncdee0092016-01-08 13:20:12 -080038
Brian Salomon217522c2019-06-11 15:55:30 -040039 constexpr char operator[](int i) const {
Brian Salomondc829942018-10-23 16:07:24 -040040 SkASSERT(i >= 0 && i < 4);
41 return fSwiz[i];
42 }
43
bsalomon7f9b2e42016-01-12 13:29:26 -080044 /** Applies this swizzle to the input color and returns the swizzled color. */
Brian Salomon217522c2019-06-11 15:55:30 -040045 constexpr SkPMColor4f applyTo(const SkPMColor4f& color) const;
46
47 void apply(SkRasterPipeline*) const;
Brian Osmance425512017-03-22 14:37:50 -040048
Brian Salomon21511652018-10-17 08:30:51 -040049 static constexpr GrSwizzle RGBA() { return GrSwizzle("rgba"); }
50 static constexpr GrSwizzle AAAA() { return GrSwizzle("aaaa"); }
51 static constexpr GrSwizzle RRRR() { return GrSwizzle("rrrr"); }
52 static constexpr GrSwizzle RRRA() { return GrSwizzle("rrra"); }
53 static constexpr GrSwizzle BGRA() { return GrSwizzle("bgra"); }
Greg Danielf259b8b2019-02-14 09:03:43 -050054 static constexpr GrSwizzle RGB1() { return GrSwizzle("rgb1"); }
bsalomoncdee0092016-01-08 13:20:12 -080055
Brian Salomon21511652018-10-17 08:30:51 -040056private:
Brian Salomon217522c2019-06-11 15:55:30 -040057 static constexpr float ComponentIndexToFloat(const SkPMColor4f& color, int idx);
58 static constexpr int CToI(char c);
59 static constexpr char IToC(int idx);
60
Brian Salomon21511652018-10-17 08:30:51 -040061 char fSwiz[5];
Greg Danielf259b8b2019-02-14 09:03:43 -050062 uint16_t fKey;
bsalomoncdee0092016-01-08 13:20:12 -080063};
64
Brian Salomon217522c2019-06-11 15:55:30 -040065constexpr GrSwizzle::GrSwizzle(const char c[4])
66 : fSwiz{c[0], c[1], c[2], c[3], '\0'}
67 , fKey((CToI(c[0]) << 0) | (CToI(c[1]) << 4) | (CToI(c[2]) << 8) | (CToI(c[3]) << 12)) {}
68
69constexpr GrSwizzle::GrSwizzle(const GrSwizzle& that)
70 : fSwiz{that.fSwiz[0], that.fSwiz[1], that.fSwiz[2], that.fSwiz[3], '\0'}
71 , fKey(that.fKey) {}
72
73constexpr GrSwizzle& GrSwizzle::operator=(const GrSwizzle& that) {
74 fSwiz[0] = that.fSwiz[0];
75 fSwiz[1] = that.fSwiz[1];
76 fSwiz[2] = that.fSwiz[2];
77 fSwiz[3] = that.fSwiz[3];
78 SkASSERT(fSwiz[4] == '\0');
79 fKey = that.fKey;
80 return *this;
81}
82
83constexpr SkPMColor4f GrSwizzle::applyTo(const SkPMColor4f& color) const {
84 uint32_t key = fKey;
85 // Index of the input color that should be mapped to output r.
86 int idx = (key & 15);
87 float outR = ComponentIndexToFloat(color, idx);
88 key >>= 4;
89 idx = (key & 15);
90 float outG = ComponentIndexToFloat(color, idx);
91 key >>= 4;
92 idx = (key & 15);
93 float outB = ComponentIndexToFloat(color, idx);
94 key >>= 4;
95 idx = (key & 15);
96 float outA = ComponentIndexToFloat(color, idx);
97 return { outR, outG, outB, outA };
98}
99
100/** Recreates a GrSwizzle from the output of asKey() */
101constexpr void GrSwizzle::setFromKey(uint16_t key) {
102 fKey = key;
103 for (int i = 0; i < 4; ++i) {
104 fSwiz[i] = IToC(key & 15);
105 key >>= 4;
106 }
Brian Salomon24fc4eb2019-06-26 14:15:36 -0400107 SkASSERT(fSwiz[4] == '\0');
Brian Salomon217522c2019-06-11 15:55:30 -0400108}
109
110constexpr float GrSwizzle::ComponentIndexToFloat(const SkPMColor4f& color, int idx) {
111 if (idx <= 3) {
112 return color[idx];
113 }
Brian Salomonf30b1c12019-06-20 12:25:02 -0400114 if (idx == CToI('1')) {
Brian Salomon217522c2019-06-11 15:55:30 -0400115 return 1.0f;
116 }
Brian Salomonf30b1c12019-06-20 12:25:02 -0400117 if (idx == CToI('0')) {
118 return 1.0f;
119 }
Brian Salomon24fc4eb2019-06-26 14:15:36 -0400120 SkUNREACHABLE;
Brian Salomon217522c2019-06-11 15:55:30 -0400121}
122
123constexpr int GrSwizzle::CToI(char c) {
124 switch (c) {
Brian Salomonf30b1c12019-06-20 12:25:02 -0400125 // r...a must map to 0...3 because other methods use them as indices into fSwiz.
126 case 'r': return 0;
127 case 'g': return 1;
128 case 'b': return 2;
129 case 'a': return 3;
130 case '0': return 4;
131 case '1': return 5;
Brian Salomon24fc4eb2019-06-26 14:15:36 -0400132 default: SkUNREACHABLE;
Brian Salomon217522c2019-06-11 15:55:30 -0400133 }
134}
135
136constexpr char GrSwizzle::IToC(int idx) {
Brian Salomonf30b1c12019-06-20 12:25:02 -0400137 switch (idx) {
138 case CToI('r'): return 'r';
139 case CToI('g'): return 'g';
140 case CToI('b'): return 'b';
141 case CToI('a'): return 'a';
142 case CToI('0'): return '0';
143 case CToI('1'): return '1';
Brian Salomon24fc4eb2019-06-26 14:15:36 -0400144 default: SkUNREACHABLE;
Brian Salomon217522c2019-06-11 15:55:30 -0400145 }
146}
147
Brian Salomonf30b1c12019-06-20 12:25:02 -0400148constexpr GrSwizzle GrSwizzle::Concat(const GrSwizzle& a, const GrSwizzle& b) {
149 char swiz[4]{};
150 for (int i = 0; i < 4; ++i) {
151 int idx = (b.fKey >> (4U * i)) & 0xfU;
152 switch (idx) {
153 case CToI('0'): swiz[i] = '0'; break;
154 case CToI('1'): swiz[i] = '1'; break;
155 default: swiz[i] = a.fSwiz[idx]; break;
156 }
157 }
158 return GrSwizzle(swiz);
159}
bsalomoncdee0092016-01-08 13:20:12 -0800160#endif