LCOV - code coverage report
Current view: top level - source/graphics - Color.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 55 62 88.7 %
Date: 2023-01-19 00:18:29 Functions: 6 7 85.7 %

          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 : }

Generated by: LCOV version 1.13