// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
|
//
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
// you may not use this file except in compliance with the License.
|
// You may obtain a copy of the License at
|
//
|
// http://www.apache.org/licenses/LICENSE-2.0
|
//
|
// Unless required by applicable law or agreed to in writing, software
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// See the License for the specific language governing permissions and
|
// limitations under the License.
|
|
#ifndef sw_Color_hpp
|
#define sw_Color_hpp
|
|
#include "Common/Types.hpp"
|
#include "Common/Math.hpp"
|
|
namespace sw
|
{
|
template<class T>
|
struct Color
|
{
|
Color();
|
|
Color(const Color<byte> &c);
|
Color(const Color<short> &c);
|
Color(const Color<float> &c);
|
|
Color(int c);
|
Color(unsigned short c);
|
Color(unsigned long c);
|
Color(unsigned int c);
|
|
Color(T r, T g, T b, T a = 1);
|
|
operator unsigned int() const;
|
|
T &operator[](int i);
|
const T &operator[](int i) const;
|
|
Color<T> operator+() const;
|
Color<T> operator-() const;
|
|
Color<T>& operator=(const Color<T>& c);
|
|
Color<T> &operator+=(const Color<T> &c);
|
Color<T> &operator*=(float l);
|
|
static Color<T> gradient(const Color<T> &c1, const Color<T> &c2, float d);
|
static Color<T> shade(const Color<T> &c1, const Color<T> &c2, float d);
|
|
template<class S>
|
friend Color<S> operator+(const Color<S> &c1, const Color<S> &c2);
|
template<class S>
|
friend Color<S> operator-(const Color<S> &c1, const Color<S> &c2);
|
|
template<class S>
|
friend Color<S> operator*(float l, const Color<S> &c);
|
template<class S>
|
friend Color<S> operator*(const Color<S> &c1, const Color<S> &c2);
|
template<class S>
|
friend Color<S> operator/(const Color<S> &c, float l);
|
|
T r;
|
T g;
|
T b;
|
T a;
|
};
|
}
|
|
#include "Common/Math.hpp"
|
|
namespace sw
|
{
|
template<class T>
|
inline Color<T>::Color()
|
{
|
}
|
|
template<>
|
inline Color<byte>::Color(const Color<byte> &c)
|
{
|
r = c.r;
|
g = c.g;
|
b = c.b;
|
a = c.a;
|
}
|
|
template<>
|
inline Color<byte>::Color(const Color<short> &c)
|
{
|
r = clamp(c.r >> 4, 0, 255);
|
g = clamp(c.g >> 4, 0, 255);
|
b = clamp(c.b >> 4, 0, 255);
|
a = clamp(c.a >> 4, 0, 255);
|
}
|
|
template<>
|
inline Color<byte>::Color(const Color<float> &c)
|
{
|
r = ifloor(clamp(c.r * 256.0f, 0.0f, 255.0f));
|
g = ifloor(clamp(c.g * 256.0f, 0.0f, 255.0f));
|
b = ifloor(clamp(c.b * 256.0f, 0.0f, 255.0f));
|
a = ifloor(clamp(c.a * 256.0f, 0.0f, 255.0f));
|
}
|
|
template<>
|
inline Color<short>::Color(const Color<short> &c)
|
{
|
r = c.r;
|
g = c.g;
|
b = c.b;
|
a = c.a;
|
}
|
|
template<>
|
inline Color<short>::Color(const Color<byte> &c)
|
{
|
r = c.r << 4;
|
g = c.g << 4;
|
b = c.b << 4;
|
a = c.a << 4;
|
}
|
|
template<>
|
inline Color<float>::Color(const Color<float> &c)
|
{
|
r = c.r;
|
g = c.g;
|
b = c.b;
|
a = c.a;
|
}
|
|
template<>
|
inline Color<short>::Color(const Color<float> &c)
|
{
|
r = iround(clamp(c.r * 4095.0f, -4096.0f, 4095.0f));
|
g = iround(clamp(c.g * 4095.0f, -4096.0f, 4095.0f));
|
b = iround(clamp(c.b * 4095.0f, -4096.0f, 4095.0f));
|
a = iround(clamp(c.a * 4095.0f, -4096.0f, 4095.0f));
|
}
|
|
template<>
|
inline Color<float>::Color(const Color<byte> &c)
|
{
|
r = c.r / 255.0f;
|
g = c.g / 255.0f;
|
b = c.b / 255.0f;
|
a = c.a / 255.0f;
|
}
|
|
template<>
|
inline Color<float>::Color(const Color<short> &c)
|
{
|
r = c.r / 4095.0f;
|
g = c.g / 4095.0f;
|
b = c.b / 4095.0f;
|
a = c.a / 4095.0f;
|
}
|
|
template<>
|
inline Color<float>::Color(unsigned short c)
|
{
|
r = (float)(c & 0xF800) / (float)0xF800;
|
g = (float)(c & 0x07E0) / (float)0x07E0;
|
b = (float)(c & 0x001F) / (float)0x001F;
|
a = 1;
|
}
|
|
template<>
|
inline Color<short>::Color(unsigned short c)
|
{
|
// 4.12 fixed-point format
|
r = ((c & 0xF800) >> 4) + ((c & 0xF800) >> 9) + ((c & 0xF800) >> 14);
|
g = ((c & 0x07E0) << 1) + ((c & 0x07E0) >> 5);
|
b = ((c & 0x001F) << 7) + ((c & 0x001F) << 2) + ((c & 0x001F) >> 3);
|
a = 0x1000;
|
}
|
|
template<>
|
inline Color<byte>::Color(unsigned short c)
|
{
|
r = (byte)(((c & 0xF800) >> 8) + ((c & 0xE000) >> 13));
|
g = (byte)(((c & 0x07E0) >> 3) + ((c & 0x0600) >> 9));
|
b = (byte)(((c & 0x001F) << 3) + ((c & 0x001C) >> 2));
|
a = 0xFF;
|
}
|
|
template<>
|
inline Color<float>::Color(int c)
|
{
|
const float d = 1.0f / 255.0f;
|
|
r = (float)((c & 0x00FF0000) >> 16) * d;
|
g = (float)((c & 0x0000FF00) >> 8) * d;
|
b = (float)((c & 0x000000FF) >> 0) * d;
|
a = (float)((c & 0xFF000000) >> 24) * d;
|
}
|
|
template<>
|
inline Color<short>::Color(int c)
|
{
|
// 4.12 fixed-point format
|
r = (short)((c & 0x00FF0000) >> 12);
|
g = (short)((c & 0x0000FF00) >> 4);
|
b = (short)((c & 0x000000FF) << 4);
|
a = (short)((c & 0xFF000000) >> 20);
|
}
|
|
template<>
|
inline Color<byte>::Color(int c)
|
{
|
r = (byte)((c & 0x00FF0000) >> 16);
|
g = (byte)((c & 0x0000FF00) >> 8);
|
b = (byte)((c & 0x000000FF) >> 0);
|
a = (byte)((c & 0xFF000000) >> 24);
|
}
|
|
template<>
|
inline Color<float>::Color(unsigned int c)
|
{
|
const float d = 1.0f / 255.0f;
|
|
r = (float)((c & 0x00FF0000) >> 16) * d;
|
g = (float)((c & 0x0000FF00) >> 8) * d;
|
b = (float)((c & 0x000000FF) >> 0) * d;
|
a = (float)((c & 0xFF000000) >> 24) * d;
|
}
|
|
template<>
|
inline Color<short>::Color(unsigned int c)
|
{
|
// 4.12 fixed-point format
|
r = (short)((c & 0x00FF0000) >> 12);
|
g = (short)((c & 0x0000FF00) >> 4);
|
b = (short)((c & 0x000000FF) << 4);
|
a = (short)((c & 0xFF000000) >> 20);
|
}
|
|
template<>
|
inline Color<byte>::Color(unsigned int c)
|
{
|
r = (byte)((c & 0x00FF0000) >> 16);
|
g = (byte)((c & 0x0000FF00) >> 8);
|
b = (byte)((c & 0x000000FF) >> 0);
|
a = (byte)((c & 0xFF000000) >> 24);
|
}
|
|
template<>
|
inline Color<float>::Color(unsigned long c)
|
{
|
const float d = 1.0f / 255.0f;
|
|
r = (float)((c & 0x00FF0000) >> 16) * d;
|
g = (float)((c & 0x0000FF00) >> 8) * d;
|
b = (float)((c & 0x000000FF) >> 0) * d;
|
a = (float)((c & 0xFF000000) >> 24) * d;
|
}
|
|
template<>
|
inline Color<short>::Color(unsigned long c)
|
{
|
// 4.12 fixed-point format
|
r = (short)((c & 0x00FF0000) >> 12);
|
g = (short)((c & 0x0000FF00) >> 4);
|
b = (short)((c & 0x000000FF) << 4);
|
a = (short)((c & 0xFF000000) >> 20);
|
}
|
|
template<>
|
inline Color<byte>::Color(unsigned long c)
|
{
|
r = (byte)((c & 0x00FF0000) >> 16);
|
g = (byte)((c & 0x0000FF00) >> 8);
|
b = (byte)((c & 0x000000FF) >> 0);
|
a = (byte)((c & 0xFF000000) >> 24);
|
}
|
|
template<class T>
|
inline Color<T>::Color(T r_, T g_, T b_, T a_)
|
{
|
r = r_;
|
g = g_;
|
b = b_;
|
a = a_;
|
}
|
|
template<>
|
inline Color<float>::operator unsigned int() const
|
{
|
return ((unsigned int)min(b * 255.0f, 255.0f) << 0) |
|
((unsigned int)min(g * 255.0f, 255.0f) << 8) |
|
((unsigned int)min(r * 255.0f, 255.0f) << 16) |
|
((unsigned int)min(a * 255.0f, 255.0f) << 24);
|
}
|
|
template<>
|
inline Color<short>::operator unsigned int() const
|
{
|
return ((unsigned int)min(b >> 4, 255) << 0) |
|
((unsigned int)min(g >> 4, 255) << 8) |
|
((unsigned int)min(r >> 4, 255) << 16) |
|
((unsigned int)min(a >> 4, 255) << 24);
|
}
|
|
template<>
|
inline Color<byte>::operator unsigned int() const
|
{
|
return (b << 0) +
|
(g << 8) +
|
(r << 16) +
|
(a << 24);
|
}
|
|
template<class T>
|
inline T &Color<T>::operator[](int i)
|
{
|
return (&r)[i];
|
}
|
|
template<class T>
|
inline const T &Color<T>::operator[](int i) const
|
{
|
return (&r)[i];
|
}
|
|
template<class T>
|
inline Color<T> Color<T>::operator+() const
|
{
|
return *this;
|
}
|
|
template<class T>
|
inline Color<T> Color<T>::operator-() const
|
{
|
return Color(-r, -g, -b, -a);
|
}
|
|
template<class T>
|
inline Color<T> &Color<T>::operator=(const Color& c)
|
{
|
r = c.r;
|
g = c.g;
|
b = c.b;
|
a = c.a;
|
|
return *this;
|
}
|
|
template<class T>
|
inline Color<T> &Color<T>::operator+=(const Color &c)
|
{
|
r += c.r;
|
g += c.g;
|
b += c.b;
|
a += c.a;
|
|
return *this;
|
}
|
|
template<class T>
|
inline Color<T> &Color<T>::operator*=(float l)
|
{
|
*this = l * *this;
|
|
return *this;
|
}
|
|
template<class T>
|
inline Color<T> operator+(const Color<T> &c1, const Color<T> &c2)
|
{
|
return Color<T>(c1.r + c2.r,
|
c1.g + c2.g,
|
c1.b + c2.b,
|
c1.a + c2.a);
|
}
|
|
template<class T>
|
inline Color<T> operator-(const Color<T> &c1, const Color<T> &c2)
|
{
|
return Color<T>(c1.r - c2.r,
|
c1.g - c2.g,
|
c1.b - c2.b,
|
c1.a - c2.a);
|
}
|
|
template<class T>
|
inline Color<T> operator*(float l, const Color<T> &c)
|
{
|
T r = (T)(l * c.r);
|
T g = (T)(l * c.g);
|
T b = (T)(l * c.b);
|
T a = (T)(l * c.a);
|
|
return Color<T>(r, g, b, a);
|
}
|
|
template<class T>
|
inline Color<T> operator*(const Color<T> &c1, const Color<T> &c2)
|
{
|
T r = c1.r * c2.r;
|
T g = c1.g * c2.g;
|
T b = c1.b * c2.b;
|
T a = c1.a * c2.a;
|
|
return Color<T>(r, g, b, a);
|
}
|
|
template<>
|
inline Color<short> operator*(const Color<short> &c1, const Color<short> &c2)
|
{
|
short r = c1.r * c2.r >> 12;
|
short g = c1.g * c2.g >> 12;
|
short b = c1.b * c2.b >> 12;
|
short a = c1.a * c2.a >> 12;
|
|
return Color<short>(r, g, b, a);
|
}
|
|
template<>
|
inline Color<byte> operator*(const Color<byte> &c1, const Color<byte> &c2)
|
{
|
byte r = c1.r * c2.r >> 8;
|
byte g = c1.g * c2.g >> 8;
|
byte b = c1.b * c2.b >> 8;
|
byte a = c1.a * c2.a >> 8;
|
|
return Color<byte>(r, g, b, a);
|
}
|
|
template<class T>
|
inline Color<T> operator/(const Color<T> &c, float l)
|
{
|
l = 1.0f / l;
|
|
T r = (T)(l * c.r);
|
T g = (T)(l * c.g);
|
T b = (T)(l * c.b);
|
T a = (T)(l * c.a);
|
|
return Color<T>(r, g, b, a);
|
}
|
|
template<class T>
|
inline Color<T> Color<T>::gradient(const Color<T> &c1, const Color<T> &c2, float d)
|
{
|
d = 1.0f / d;
|
|
T r = (c2.r - c1.r) * d;
|
T g = (c2.g - c1.g) * d;
|
T b = (c2.b - c1.b) * d;
|
T a = (c2.a - c1.a) * d;
|
|
return Color<T>(r, g, b, a);
|
}
|
|
template<class T>
|
inline Color<T> Color<T>::shade(const Color<T> &c1, const Color<T> &c2, float d)
|
{
|
T r = c1.r + (T)(d * (c2.r - c1.r));
|
T g = c1.g + (T)(d * (c2.g - c1.g));
|
T b = c1.b + (T)(d * (c2.b - c1.b));
|
T a = c1.a + (T)(d * (c2.a - c1.a));
|
|
return Color<T>(r, g, b, a);
|
}
|
}
|
|
#endif // sw_Color_hpp
|