1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef sw_Color_hpp
16#define sw_Color_hpp
17
18#include "Common/Types.hpp"
19#include "Common/Math.hpp"
20
21namespace sw
22{
23	template<class T>
24	struct Color
25	{
26		Color();
27
28		Color(const Color<byte> &c);
29		Color(const Color<short> &c);
30		Color(const Color<float> &c);
31
32		Color(int c);
33		Color(unsigned short c);
34		Color(unsigned long c);
35		Color(unsigned int c);
36
37		Color(T r, T g, T b, T a = 1);
38
39		operator unsigned int() const;
40
41		T &operator[](int i);
42		const T &operator[](int i) const;
43
44		Color<T> operator+() const;
45		Color<T> operator-() const;
46
47		Color<T>& operator=(const Color<T>& c);
48
49		Color<T> &operator+=(const Color<T> &c);
50		Color<T> &operator*=(float l);
51
52		static Color<T> gradient(const Color<T> &c1, const Color<T>  &c2, float d);
53		static Color<T> shade(const Color<T> &c1, const Color<T>  &c2, float d);
54
55		template<class S>
56		friend Color<S> operator+(const Color<S> &c1, const Color<S> &c2);
57		template<class S>
58		friend Color<S> operator-(const Color<S> &c1, const Color<S> &c2);
59
60		template<class S>
61		friend Color<S> operator*(float l, const Color<S> &c);
62		template<class S>
63		friend Color<S> operator*(const Color<S> &c1, const Color<S> &c2);
64		template<class S>
65		friend Color<S> operator/(const Color<S> &c, float l);
66
67		T r;
68		T g;
69		T b;
70		T a;
71	};
72}
73
74#include "Common/Math.hpp"
75
76namespace sw
77{
78	template<class T>
79	inline Color<T>::Color()
80	{
81	}
82
83	template<>
84	inline Color<byte>::Color(const Color<byte> &c)
85	{
86		r = c.r;
87		g = c.g;
88		b = c.b;
89		a = c.a;
90	}
91
92	template<>
93	inline Color<byte>::Color(const Color<short> &c)
94	{
95		r = clamp(c.r >> 4, 0, 255);
96		g = clamp(c.g >> 4, 0, 255);
97		b = clamp(c.b >> 4, 0, 255);
98		a = clamp(c.a >> 4, 0, 255);
99	}
100
101	template<>
102	inline Color<byte>::Color(const Color<float> &c)
103	{
104		r = ifloor(clamp(c.r * 256.0f, 0.0f, 255.0f));
105		g = ifloor(clamp(c.g * 256.0f, 0.0f, 255.0f));
106		b = ifloor(clamp(c.b * 256.0f, 0.0f, 255.0f));
107		a = ifloor(clamp(c.a * 256.0f, 0.0f, 255.0f));
108	}
109
110	template<>
111	inline Color<short>::Color(const Color<short> &c)
112	{
113		r = c.r;
114		g = c.g;
115		b = c.b;
116		a = c.a;
117	}
118
119	template<>
120	inline Color<short>::Color(const Color<byte> &c)
121	{
122		r = c.r << 4;
123		g = c.g << 4;
124		b = c.b << 4;
125		a = c.a << 4;
126	}
127
128	template<>
129	inline Color<float>::Color(const Color<float> &c)
130	{
131		r = c.r;
132		g = c.g;
133		b = c.b;
134		a = c.a;
135	}
136
137	template<>
138	inline Color<short>::Color(const Color<float> &c)
139	{
140		r = iround(clamp(c.r * 4095.0f, -4096.0f, 4095.0f));
141		g = iround(clamp(c.g * 4095.0f, -4096.0f, 4095.0f));
142		b = iround(clamp(c.b * 4095.0f, -4096.0f, 4095.0f));
143		a = iround(clamp(c.a * 4095.0f, -4096.0f, 4095.0f));
144	}
145
146	template<>
147	inline Color<float>::Color(const Color<byte> &c)
148	{
149		r = c.r / 255.0f;
150		g = c.g / 255.0f;
151		b = c.b / 255.0f;
152		a = c.a / 255.0f;
153	}
154
155	template<>
156	inline Color<float>::Color(const Color<short> &c)
157	{
158		r = c.r / 4095.0f;
159		g = c.g / 4095.0f;
160		b = c.b / 4095.0f;
161		a = c.a / 4095.0f;
162	}
163
164	template<>
165	inline Color<float>::Color(unsigned short c)
166	{
167		r = (float)(c & 0xF800) / (float)0xF800;
168		g = (float)(c & 0x07E0) / (float)0x07E0;
169		b = (float)(c & 0x001F) / (float)0x001F;
170		a = 1;
171	}
172
173	template<>
174	inline Color<short>::Color(unsigned short c)
175	{
176		// 4.12 fixed-point format
177		r = ((c & 0xF800) >> 4) + ((c & 0xF800) >> 9) + ((c & 0xF800) >> 14);
178		g = ((c & 0x07E0) << 1) + ((c & 0x07E0) >> 5);
179		b = ((c & 0x001F) << 7) + ((c & 0x001F) << 2) + ((c & 0x001F) >> 3);
180		a = 0x1000;
181	}
182
183	template<>
184	inline Color<byte>::Color(unsigned short c)
185	{
186		r = (byte)(((c & 0xF800) >> 8) + ((c & 0xE000) >> 13));
187		g = (byte)(((c & 0x07E0) >> 3) + ((c & 0x0600) >> 9));
188		b = (byte)(((c & 0x001F) << 3) + ((c & 0x001C) >> 2));
189		a = 0xFF;
190	}
191
192	template<>
193	inline Color<float>::Color(int c)
194	{
195		const float d = 1.0f / 255.0f;
196
197		r = (float)((c & 0x00FF0000) >> 16) * d;
198		g = (float)((c & 0x0000FF00) >> 8) * d;
199		b = (float)((c & 0x000000FF) >> 0) * d;
200		a = (float)((c & 0xFF000000) >> 24) * d;
201	}
202
203	template<>
204	inline Color<short>::Color(int c)
205	{
206		// 4.12 fixed-point format
207		r = (short)((c & 0x00FF0000) >> 12);
208		g = (short)((c & 0x0000FF00) >> 4);
209		b = (short)((c & 0x000000FF) << 4);
210		a = (short)((c & 0xFF000000) >> 20);
211	}
212
213	template<>
214	inline Color<byte>::Color(int c)
215	{
216		r = (byte)((c & 0x00FF0000) >> 16);
217		g = (byte)((c & 0x0000FF00) >> 8);
218		b = (byte)((c & 0x000000FF) >> 0);
219		a = (byte)((c & 0xFF000000) >> 24);
220	}
221
222	template<>
223	inline Color<float>::Color(unsigned int c)
224	{
225		const float d = 1.0f / 255.0f;
226
227		r = (float)((c & 0x00FF0000) >> 16) * d;
228		g = (float)((c & 0x0000FF00) >> 8) * d;
229		b = (float)((c & 0x000000FF) >> 0) * d;
230		a = (float)((c & 0xFF000000) >> 24) * d;
231	}
232
233	template<>
234	inline Color<short>::Color(unsigned int c)
235	{
236		// 4.12 fixed-point format
237		r = (short)((c & 0x00FF0000) >> 12);
238		g = (short)((c & 0x0000FF00) >> 4);
239		b = (short)((c & 0x000000FF) << 4);
240		a = (short)((c & 0xFF000000) >> 20);
241	}
242
243	template<>
244	inline Color<byte>::Color(unsigned int c)
245	{
246		r = (byte)((c & 0x00FF0000) >> 16);
247		g = (byte)((c & 0x0000FF00) >> 8);
248		b = (byte)((c & 0x000000FF) >> 0);
249		a = (byte)((c & 0xFF000000) >> 24);
250	}
251
252	template<>
253	inline Color<float>::Color(unsigned long c)
254	{
255		const float d = 1.0f / 255.0f;
256
257		r = (float)((c & 0x00FF0000) >> 16) * d;
258		g = (float)((c & 0x0000FF00) >> 8) * d;
259		b = (float)((c & 0x000000FF) >> 0) * d;
260		a = (float)((c & 0xFF000000) >> 24) * d;
261	}
262
263	template<>
264	inline Color<short>::Color(unsigned long c)
265	{
266		// 4.12 fixed-point format
267		r = (short)((c & 0x00FF0000) >> 12);
268		g = (short)((c & 0x0000FF00) >> 4);
269		b = (short)((c & 0x000000FF) << 4);
270		a = (short)((c & 0xFF000000) >> 20);
271	}
272
273	template<>
274	inline Color<byte>::Color(unsigned long c)
275	{
276		r = (byte)((c & 0x00FF0000) >> 16);
277		g = (byte)((c & 0x0000FF00) >> 8);
278		b = (byte)((c & 0x000000FF) >> 0);
279		a = (byte)((c & 0xFF000000) >> 24);
280	}
281
282	template<class T>
283	inline Color<T>::Color(T r_, T g_, T b_, T a_)
284	{
285		r = r_;
286		g = g_;
287		b = b_;
288		a = a_;
289	}
290
291	template<>
292	inline Color<float>::operator unsigned int() const
293	{
294		return ((unsigned int)min(b * 255.0f, 255.0f) << 0) |
295		       ((unsigned int)min(g * 255.0f, 255.0f) << 8) |
296		       ((unsigned int)min(r * 255.0f, 255.0f) << 16) |
297		       ((unsigned int)min(a * 255.0f, 255.0f) << 24);
298	}
299
300	template<>
301	inline Color<short>::operator unsigned int() const
302	{
303		return ((unsigned int)min(b >> 4, 255) << 0) |
304		       ((unsigned int)min(g >> 4, 255) << 8) |
305		       ((unsigned int)min(r >> 4, 255) << 16) |
306		       ((unsigned int)min(a >> 4, 255) << 24);
307	}
308
309	template<>
310	inline Color<byte>::operator unsigned int() const
311	{
312		return (b << 0) +
313		       (g << 8) +
314		       (r << 16) +
315			   (a << 24);
316	}
317
318	template<class T>
319	inline T &Color<T>::operator[](int i)
320	{
321		return (&r)[i];
322	}
323
324	template<class T>
325	inline const T &Color<T>::operator[](int i) const
326	{
327		return (&r)[i];
328	}
329
330	template<class T>
331	inline Color<T> Color<T>::operator+() const
332	{
333		return *this;
334	}
335
336	template<class T>
337	inline Color<T> Color<T>::operator-() const
338	{
339		return Color(-r, -g, -b, -a);
340	}
341
342	template<class T>
343	inline Color<T> &Color<T>::operator=(const Color& c)
344	{
345		r = c.r;
346		g = c.g;
347		b = c.b;
348		a = c.a;
349
350		return *this;
351	}
352
353	template<class T>
354	inline Color<T> &Color<T>::operator+=(const Color &c)
355	{
356		r += c.r;
357		g += c.g;
358		b += c.b;
359		a += c.a;
360
361		return *this;
362	}
363
364	template<class T>
365	inline Color<T> &Color<T>::operator*=(float l)
366	{
367		*this = l * *this;
368
369		return *this;
370	}
371
372	template<class T>
373	inline Color<T> operator+(const Color<T> &c1, const Color<T> &c2)
374	{
375		return Color<T>(c1.r + c2.r,
376		                c1.g + c2.g,
377		                c1.b + c2.b,
378		                c1.a + c2.a);
379	}
380
381	template<class T>
382	inline Color<T> operator-(const Color<T> &c1, const Color<T> &c2)
383	{
384		return Color<T>(c1.r - c2.r,
385		                c1.g - c2.g,
386		                c1.b - c2.b,
387		                c1.a - c2.a);
388	}
389
390	template<class T>
391	inline Color<T> operator*(float l, const Color<T> &c)
392	{
393		T r = (T)(l * c.r);
394		T g = (T)(l * c.g);
395		T b = (T)(l * c.b);
396		T a = (T)(l * c.a);
397
398		return Color<T>(r, g, b, a);
399	}
400
401	template<class T>
402	inline Color<T> operator*(const Color<T> &c1, const Color<T> &c2)
403	{
404		T r = c1.r * c2.r;
405		T g = c1.g * c2.g;
406		T b = c1.b * c2.b;
407		T a = c1.a * c2.a;
408
409		return Color<T>(r, g, b, a);
410	}
411
412	template<>
413	inline Color<short> operator*(const Color<short> &c1, const Color<short> &c2)
414	{
415		short r = c1.r * c2.r >> 12;
416		short g = c1.g * c2.g >> 12;
417		short b = c1.b * c2.b >> 12;
418		short a = c1.a * c2.a >> 12;
419
420		return Color<short>(r, g, b, a);
421	}
422
423	template<>
424	inline Color<byte> operator*(const Color<byte> &c1, const Color<byte> &c2)
425	{
426		byte r = c1.r * c2.r >> 8;
427		byte g = c1.g * c2.g >> 8;
428		byte b = c1.b * c2.b >> 8;
429		byte a = c1.a * c2.a >> 8;
430
431		return Color<byte>(r, g, b, a);
432	}
433
434	template<class T>
435	inline Color<T> operator/(const Color<T> &c, float l)
436	{
437		l = 1.0f / l;
438
439		T r = (T)(l * c.r);
440		T g = (T)(l * c.g);
441		T b = (T)(l * c.b);
442		T a = (T)(l * c.a);
443
444		return Color<T>(r, g, b, a);
445	}
446
447	template<class T>
448	inline Color<T> Color<T>::gradient(const Color<T> &c1, const Color<T> &c2, float d)
449	{
450		d = 1.0f / d;
451
452		T r = (c2.r - c1.r) * d;
453		T g = (c2.g - c1.g) * d;
454		T b = (c2.b - c1.b) * d;
455		T a = (c2.a - c1.a) * d;
456
457		return Color<T>(r, g, b, a);
458	}
459
460	template<class T>
461	inline Color<T> Color<T>::shade(const Color<T> &c1, const Color<T>  &c2, float d)
462	{
463		T r = c1.r + (T)(d * (c2.r - c1.r));
464		T g = c1.g + (T)(d * (c2.g - c1.g));
465		T b = c1.b + (T)(d * (c2.b - c1.b));
466		T a = c1.a + (T)(d * (c2.a - c1.a));
467
468		return Color<T>(r, g, b, a);
469	}
470}
471
472#endif   // sw_Color_hpp
473