Line data Source code
1 : /* Copyright (C) 2022 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #include "precompiled.h"
19 :
20 : #include "graphics/Color.h"
21 :
22 : #include "graphics/SColor.h"
23 : #include "lib/sysdep/arch/x86_x64/simd.h"
24 : #include "maths/MathUtil.h"
25 : #include "ps/CLogger.h"
26 : #include "ps/CStr.h"
27 :
28 : #if COMPILER_HAS_SSE
29 : #include <xmmintrin.h>
30 : #endif
31 :
32 0 : static SColor4ub ConvertRGBColorTo4ubFallback(const RGBColor& src)
33 : {
34 0 : SColor4ub result;
35 0 : result.R = Clamp(static_cast<int>(src.X * 255), 0, 255);
36 0 : result.G = Clamp(static_cast<int>(src.Y * 255), 0, 255);
37 0 : result.B = Clamp(static_cast<int>(src.Z * 255), 0, 255);
38 0 : result.A = 255;
39 0 : return result;
40 : }
41 :
42 : // on IA32, this is replaced by an SSE assembly version in ia32.cpp
43 : SColor4ub (*ConvertRGBColorTo4ub)(const RGBColor& src) = ConvertRGBColorTo4ubFallback;
44 :
45 :
46 : // Assembler-optimized function for color conversion
47 : #if COMPILER_HAS_SSE
48 5 : static SColor4ub ConvertRGBColorTo4ubSSE(const RGBColor& src)
49 : {
50 5 : const __m128 zero = _mm_setzero_ps();
51 5 : const __m128 _255 = _mm_set_ss(255.0f);
52 10 : __m128 r = _mm_load_ss(&src.X);
53 10 : __m128 g = _mm_load_ss(&src.Y);
54 10 : __m128 b = _mm_load_ss(&src.Z);
55 :
56 : // C = min(255, 255*max(C, 0)) ( == Clamp(255*C, 0, 255) )
57 5 : r = _mm_max_ss(r, zero);
58 5 : g = _mm_max_ss(g, zero);
59 5 : b = _mm_max_ss(b, zero);
60 :
61 5 : r = _mm_mul_ss(r, _255);
62 5 : g = _mm_mul_ss(g, _255);
63 5 : b = _mm_mul_ss(b, _255);
64 :
65 5 : r = _mm_min_ss(r, _255);
66 5 : g = _mm_min_ss(g, _255);
67 5 : b = _mm_min_ss(b, _255);
68 :
69 : // convert to integer and combine channels using bit logic
70 5 : int ri = _mm_cvtss_si32(r);
71 5 : int gi = _mm_cvtss_si32(g);
72 5 : int bi = _mm_cvtss_si32(b);
73 :
74 5 : return SColor4ub(ri, gi, bi, 0xFF);
75 : }
76 : #endif
77 :
78 9 : void ColorActivateFastImpl()
79 : {
80 : #if COMPILER_HAS_SSE
81 9 : if (HostHasSSE())
82 : {
83 9 : ConvertRGBColorTo4ub = ConvertRGBColorTo4ubSSE;
84 9 : return;
85 : }
86 : #elif defined(ARCH_X86_64)
87 : debug_printf("No SSE available. Slow fallback routines will be used.\n");
88 : #endif
89 : }
90 :
91 : /**
92 : * Important: This function does not modify the value if parsing fails.
93 : */
94 20 : bool CColor::ParseString(const CStr8& value, int defaultAlpha)
95 : {
96 20 : const size_t NUM_VALS = 4;
97 20 : int values[NUM_VALS] = { 0, 0, 0, defaultAlpha };
98 40 : std::stringstream stream;
99 20 : stream.str(value);
100 : // Parse each value
101 : size_t i;
102 58 : for (i = 0; i < NUM_VALS; ++i)
103 : {
104 52 : if (stream.eof())
105 4 : break;
106 :
107 48 : stream >> values[i];
108 48 : if ((stream.rdstate() & std::stringstream::failbit) != 0)
109 : {
110 6 : LOGWARNING("Unable to parse CColor parameters. Your input: '%s'", value.c_str());
111 6 : return false;
112 : }
113 42 : if (values[i] < 0 || values[i] > 255)
114 : {
115 4 : LOGWARNING("Invalid value (<0 or >255) when parsing CColor parameters. Your input: '%s'", value.c_str());
116 4 : return false;
117 : }
118 : }
119 :
120 10 : if (i < 3)
121 : {
122 2 : LOGWARNING("Not enough parameters when parsing as CColor. Your input: '%s'", value.c_str());
123 2 : return false;
124 : }
125 8 : if (!stream.eof())
126 : {
127 2 : LOGWARNING("Too many parameters when parsing as CColor. Your input: '%s'", value.c_str());
128 2 : return false;
129 : }
130 :
131 6 : r = values[0] / 255.f;
132 6 : g = values[1] / 255.f;
133 6 : b = values[2] / 255.f;
134 6 : a = values[3] / 255.f;
135 :
136 6 : return true;
137 : }
138 :
139 6 : bool CColor::operator==(const CColor& color) const
140 : {
141 : return
142 12 : r == color.r &&
143 12 : g == color.g &&
144 18 : b == color.b &&
145 12 : a == color.a;
146 3 : }
|