bb
157c6af18e
Avoid cases of filenames Update years in terms and other legal(ish) documents Don't update years in license headers, since change is not meaningful Will add linter rule in seperate commit Happy recompiling everyone! Original Patch By: Nescio Comment By: Gallaecio Differential Revision: D2620 This was SVN commit r27786.
147 lines
3.6 KiB
C++
147 lines
3.6 KiB
C++
/* 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;
|
|
}
|