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