From 38fec546a7555c3797c667207b7804446f907c6a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 20 Aug 2019 21:02:40 +0200 Subject: [PATCH] - moved the generic palette utilities and the matrix class to 'utility' --- src/CMakeLists.txt | 3 +- src/r_data/models/models.h | 2 +- src/r_data/v_palette.cpp | 193 ----------- src/r_data/v_palette.h | 18 +- .../gl/renderer/gl_postprocessstate.h | 2 +- src/rendering/gl/renderer/gl_renderer.h | 2 +- src/rendering/gl/renderer/gl_renderstate.h | 2 +- src/rendering/gl/shaders/gl_shader.cpp | 2 +- src/rendering/hwrenderer/scene/hw_flats.cpp | 2 +- .../hwrenderer/scene/hw_renderstate.h | 2 +- src/rendering/hwrenderer/scene/hw_skydome.h | 2 +- src/rendering/hwrenderer/scene/hw_sprites.cpp | 2 +- .../hwrenderer/scene/hw_viewpointuniforms.h | 2 +- src/rendering/hwrenderer/utility/hw_vrmodes.h | 2 +- src/rendering/polyrenderer/scene/poly_model.h | 2 +- src/rendering/swrenderer/things/r_model.h | 2 +- src/rendering/vulkan/shaders/vk_shader.h | 2 +- src/utility/colormatcher.h | 2 +- src/{r_data => utility}/matrix.cpp | 0 src/{r_data => utility}/matrix.h | 0 src/utility/palette.cpp | 314 ++++++++++++++++++ src/utility/palette.h | 19 ++ src/utility/x86.cpp | 77 ----- src/utility/x86.h | 1 - 24 files changed, 351 insertions(+), 304 deletions(-) rename src/{r_data => utility}/matrix.cpp (100%) rename src/{r_data => utility}/matrix.h (100%) create mode 100644 src/utility/palette.cpp create mode 100644 src/utility/palette.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f6401eda3..84d65ea23 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -884,7 +884,7 @@ set( FASTMATH_SOURCES rendering/hwrenderer/scene/hw_walls_vertex.cpp rendering/hwrenderer/scene/hw_weapon.cpp r_data/models/models.cpp - r_data/matrix.cpp + utility/matrix.cpp sound/adlmidi/adldata.cpp sound/adlmidi/adlmidi.cpp sound/adlmidi/adlmidi_load.cpp @@ -1292,6 +1292,7 @@ set (PCH_SOURCES rendering/swrenderer/textures/warptexture.cpp rendering/swrenderer/textures/swcanvastexture.cpp events.cpp + utility/palette.cpp utility/files.cpp utility/files_decompress.cpp utility/m_png.cpp diff --git a/src/r_data/models/models.h b/src/r_data/models/models.h index ba0920390..b9a41039c 100644 --- a/src/r_data/models/models.h +++ b/src/r_data/models/models.h @@ -24,7 +24,7 @@ #define __GL_MODELS_H_ #include "tarray.h" -#include "r_data/matrix.h" +#include "matrix.h" #include "actor.h" #include "dobject.h" #include "p_pspr.h" diff --git a/src/r_data/v_palette.cpp b/src/r_data/v_palette.cpp index 0c3427cd3..a1c9c4e56 100644 --- a/src/r_data/v_palette.cpp +++ b/src/r_data/v_palette.cpp @@ -92,72 +92,6 @@ CCMD (bumpgamma) } -/****************************/ -/* Palette management stuff */ -/****************************/ - -int BestColor (const uint32_t *pal_in, int r, int g, int b, int first, int num) -{ - const PalEntry *pal = (const PalEntry *)pal_in; - int bestcolor = first; - int bestdist = 257 * 257 + 257 * 257 + 257 * 257; - - for (int color = first; color < num; color++) - { - int x = r - pal[color].r; - int y = g - pal[color].g; - int z = b - pal[color].b; - int dist = x*x + y*y + z*z; - if (dist < bestdist) - { - if (dist == 0) - return color; - - bestdist = dist; - bestcolor = color; - } - } - return bestcolor; -} - - -// [SP] Re-implemented BestColor for more precision rather than speed. This function is only ever called once until the game palette is changed. - -int PTM_BestColor (const uint32_t *pal_in, int r, int g, int b, bool reverselookup, float powtable_val, int first, int num) -{ - const PalEntry *pal = (const PalEntry *)pal_in; - static double powtable[256]; - static bool firstTime = true; - static float trackpowtable = 0.; - - double fbestdist = DBL_MAX, fdist; - int bestcolor = 0; - - if (firstTime || trackpowtable != powtable_val) - { - auto pt = powtable_val; - trackpowtable = pt; - firstTime = false; - for (int x = 0; x < 256; x++) powtable[x] = pow((double)x/255, (double)pt); - } - - for (int color = first; color < num; color++) - { - double x = powtable[abs(r-pal[color].r)]; - double y = powtable[abs(g-pal[color].g)]; - double z = powtable[abs(b-pal[color].b)]; - fdist = x + y + z; - if (color == first || (reverselookup?(fdist <= fbestdist):(fdist < fbestdist))) - { - if (fdist == 0 && !reverselookup) - return color; - - fbestdist = fdist; - bestcolor = color; - } - } - return bestcolor; -} @@ -391,58 +325,6 @@ void InitPalette () R_InitColormaps (); } -void DoBlending_SSE2 (const PalEntry *from, PalEntry *to, int count, int r, int g, int b, int a); - -void DoBlending (const PalEntry *from, PalEntry *to, int count, int r, int g, int b, int a) -{ - if (a == 0) - { - if (from != to) - { - memcpy (to, from, count * sizeof(uint32_t)); - } - return; - } - else if (a == 256) - { - uint32_t t = MAKERGB(r,g,b); - int i; - - for (i = 0; i < count; i++) - { - to[i] = t; - } - return; - } -#if defined(_M_X64) || defined(_M_IX86) || defined(__i386__) || defined(__amd64__) - else if (count >= 4) - { - int not3count = count & ~3; - DoBlending_SSE2 (from, to, not3count, r, g, b, a); - count &= 3; - if (count <= 0) - { - return; - } - from += not3count; - to += not3count; - } -#endif - int i, ia; - - ia = 256 - a; - r *= a; - g *= a; - b *= a; - - for (i = count; i > 0; i--, to++, from++) - { - to->r = (r + from->r * ia) >> 8; - to->g = (g + from->g * ia) >> 8; - to->b = (b + from->b * ia) >> 8; - } -} - CCMD (testblend) { FString colorstring; @@ -475,78 +357,3 @@ CCMD (testblend) } } -/****** Colorspace Conversion Functions ******/ - -// Code from http://www.cs.rit.edu/~yxv4997/t_convert.html - -// r,g,b values are from 0 to 1 -// h = [0,360], s = [0,1], v = [0,1] -// if s == 0, then h = -1 (undefined) - -// Green Doom guy colors: -// RGB - 0: { .46 1 .429 } 7: { .254 .571 .206 } 15: { .0317 .0794 .0159 } -// HSV - 0: { 116.743 .571 1 } 7: { 112.110 .639 .571 } 15: { 105.071 .800 .0794 } -void RGBtoHSV (float r, float g, float b, float *h, float *s, float *v) -{ - float min, max, delta, foo; - - if (r == g && g == b) - { - *h = 0; - *s = 0; - *v = r; - return; - } - - foo = r < g ? r : g; - min = (foo < b) ? foo : b; - foo = r > g ? r : g; - max = (foo > b) ? foo : b; - - *v = max; // v - - delta = max - min; - - *s = delta / max; // s - - if (r == max) - *h = (g - b) / delta; // between yellow & magenta - else if (g == max) - *h = 2 + (b - r) / delta; // between cyan & yellow - else - *h = 4 + (r - g) / delta; // between magenta & cyan - - *h *= 60; // degrees - if (*h < 0) - *h += 360; -} - -void HSVtoRGB (float *r, float *g, float *b, float h, float s, float v) -{ - int i; - float f, p, q, t; - - if (s == 0) - { // achromatic (grey) - *r = *g = *b = v; - return; - } - - h /= 60; // sector 0 to 5 - i = (int)floor (h); - f = h - i; // factorial part of h - p = v * (1 - s); - q = v * (1 - s * f); - t = v * (1 - s * (1 - f)); - - switch (i) - { - case 0: *r = v; *g = t; *b = p; break; - case 1: *r = q; *g = v; *b = p; break; - case 2: *r = p; *g = v; *b = t; break; - case 3: *r = p; *g = q; *b = v; break; - case 4: *r = t; *g = p; *b = v; break; - default: *r = v; *g = p; *b = q; break; - } -} - diff --git a/src/r_data/v_palette.h b/src/r_data/v_palette.h index 703891656..e12ba9a8f 100644 --- a/src/r_data/v_palette.h +++ b/src/r_data/v_palette.h @@ -36,14 +36,7 @@ #include "doomtype.h" #include "c_cvars.h" - -#define MAKERGB(r,g,b) uint32_t(((r)<<16)|((g)<<8)|(b)) -#define MAKEARGB(a,r,g,b) uint32_t(((a)<<24)|((r)<<16)|((g)<<8)|(b)) - -#define APART(c) (((c)>>24)&0xff) -#define RPART(c) (((c)>>16)&0xff) -#define GPART(c) (((c)>>8)&0xff) -#define BPART(c) ((c)&0xff) +#include "palette.h" struct FPalette { @@ -70,10 +63,6 @@ extern FPalette GPalette; // The color overlay to use for depleted items #define DIM_OVERLAY MAKEARGB(170,0,0,0) -int BestColor (const uint32_t *pal, int r, int g, int b, int first=1, int num=255); -int PTM_BestColor (const uint32_t *pal_in, int r, int g, int b, bool reverselookup, float powtable, int first=1, int num=255); -void DoBlending (const PalEntry *from, PalEntry *to, int count, int r, int g, int b, int a); - void ReadPalette(int lumpnum, uint8_t *buffer); void InitPalette (); @@ -91,9 +80,4 @@ class player_t; void V_AddBlend (float r, float g, float b, float a, float v_blend[4]); void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int maxpainblend); - -// Colorspace conversion RGB <-> HSV -void RGBtoHSV (float r, float g, float b, float *h, float *s, float *v); -void HSVtoRGB (float *r, float *g, float *b, float h, float s, float v); - #endif //__V_PALETTE_H__ diff --git a/src/rendering/gl/renderer/gl_postprocessstate.h b/src/rendering/gl/renderer/gl_postprocessstate.h index 7d41f6571..57bef88fd 100644 --- a/src/rendering/gl/renderer/gl_postprocessstate.h +++ b/src/rendering/gl/renderer/gl_postprocessstate.h @@ -3,7 +3,7 @@ #include #include "gl_load/gl_interface.h" -#include "r_data/matrix.h" +#include "matrix.h" #include "c_cvars.h" #include "r_defs.h" diff --git a/src/rendering/gl/renderer/gl_renderer.h b/src/rendering/gl/renderer/gl_renderer.h index 7dd5ad98c..91ac325d5 100644 --- a/src/rendering/gl/renderer/gl_renderer.h +++ b/src/rendering/gl/renderer/gl_renderer.h @@ -5,7 +5,7 @@ #include "v_video.h" #include "vectors.h" #include "swrenderer/r_renderer.h" -#include "r_data/matrix.h" +#include "matrix.h" #include "gl/renderer/gl_renderbuffers.h" #include "hwrenderer/scene/hw_portal.h" #include "hwrenderer/dynlights/hw_shadowmap.h" diff --git a/src/rendering/gl/renderer/gl_renderstate.h b/src/rendering/gl/renderer/gl_renderstate.h index 5d2e0d383..9cb76db47 100644 --- a/src/rendering/gl/renderer/gl_renderstate.h +++ b/src/rendering/gl/renderer/gl_renderstate.h @@ -25,7 +25,7 @@ #include #include "gl_load/gl_interface.h" -#include "r_data/matrix.h" +#include "matrix.h" #include "hwrenderer/scene//hw_drawstructs.h" #include "hwrenderer/scene//hw_renderstate.h" #include "hwrenderer/textures/hw_material.h" diff --git a/src/rendering/gl/shaders/gl_shader.cpp b/src/rendering/gl/shaders/gl_shader.cpp index 1dc6f2c87..0a06e56c0 100644 --- a/src/rendering/gl/shaders/gl_shader.cpp +++ b/src/rendering/gl/shaders/gl_shader.cpp @@ -41,7 +41,7 @@ #include "gl_load/gl_interface.h" #include "gl/system/gl_debug.h" -#include "r_data/matrix.h" +#include "matrix.h" #include "gl/renderer/gl_renderer.h" #include "gl/shaders/gl_shader.h" #include diff --git a/src/rendering/hwrenderer/scene/hw_flats.cpp b/src/rendering/hwrenderer/scene/hw_flats.cpp index bcaaed770..6af492e8e 100644 --- a/src/rendering/hwrenderer/scene/hw_flats.cpp +++ b/src/rendering/hwrenderer/scene/hw_flats.cpp @@ -34,7 +34,7 @@ #include "g_levellocals.h" #include "actorinlines.h" #include "p_lnspec.h" -#include "r_data/matrix.h" +#include "matrix.h" #include "hwrenderer/dynlights/hw_dynlightdata.h" #include "hwrenderer/utility/hw_cvars.h" #include "hwrenderer/utility/hw_clock.h" diff --git a/src/rendering/hwrenderer/scene/hw_renderstate.h b/src/rendering/hwrenderer/scene/hw_renderstate.h index f8b80005c..b09d6e9e0 100644 --- a/src/rendering/hwrenderer/scene/hw_renderstate.h +++ b/src/rendering/hwrenderer/scene/hw_renderstate.h @@ -5,7 +5,7 @@ #include "g_levellocals.h" #include "hw_drawstructs.h" #include "hw_drawlist.h" -#include "r_data/matrix.h" +#include "matrix.h" #include "hwrenderer/textures/hw_material.h" struct FColormap; diff --git a/src/rendering/hwrenderer/scene/hw_skydome.h b/src/rendering/hwrenderer/scene/hw_skydome.h index fc850aeeb..4084ef96f 100644 --- a/src/rendering/hwrenderer/scene/hw_skydome.h +++ b/src/rendering/hwrenderer/scene/hw_skydome.h @@ -1,7 +1,7 @@ #pragma once #include "v_palette.h" -#include "r_data/matrix.h" +#include "matrix.h" #include "hwrenderer/data/buffers.h" class FMaterial; diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 8aef39517..f215e1ef4 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -38,7 +38,7 @@ #include "events.h" #include "actorinlines.h" #include "r_data/r_vanillatrans.h" -#include "r_data/matrix.h" +#include "matrix.h" #include "r_data/models/models.h" #include "vectors.h" diff --git a/src/rendering/hwrenderer/scene/hw_viewpointuniforms.h b/src/rendering/hwrenderer/scene/hw_viewpointuniforms.h index 8752c76aa..5a1a1749d 100644 --- a/src/rendering/hwrenderer/scene/hw_viewpointuniforms.h +++ b/src/rendering/hwrenderer/scene/hw_viewpointuniforms.h @@ -1,6 +1,6 @@ #pragma once -#include "r_data/matrix.h" +#include "matrix.h" #include "r_utility.h" struct HWDrawInfo; diff --git a/src/rendering/hwrenderer/utility/hw_vrmodes.h b/src/rendering/hwrenderer/utility/hw_vrmodes.h index 43caa83d7..a80ecaf57 100644 --- a/src/rendering/hwrenderer/utility/hw_vrmodes.h +++ b/src/rendering/hwrenderer/utility/hw_vrmodes.h @@ -1,6 +1,6 @@ #pragma once -#include "r_data/matrix.h" +#include "matrix.h" class DFrameBuffer; diff --git a/src/rendering/polyrenderer/scene/poly_model.h b/src/rendering/polyrenderer/scene/poly_model.h index bdf6c9423..711e9b737 100644 --- a/src/rendering/polyrenderer/scene/poly_model.h +++ b/src/rendering/polyrenderer/scene/poly_model.h @@ -23,7 +23,7 @@ #pragma once #include "polyrenderer/drawers/poly_triangle.h" -#include "r_data/matrix.h" +#include "matrix.h" #include "r_data/models/models.h" void PolyRenderModel(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor); diff --git a/src/rendering/swrenderer/things/r_model.h b/src/rendering/swrenderer/things/r_model.h index 76509123f..1d37bba3e 100644 --- a/src/rendering/swrenderer/things/r_model.h +++ b/src/rendering/swrenderer/things/r_model.h @@ -23,7 +23,7 @@ #pragma once #include "polyrenderer/drawers/poly_triangle.h" -#include "r_data/matrix.h" +#include "matrix.h" #include "r_data/models/models.h" #include "swrenderer/r_renderthread.h" #include "swrenderer/things/r_visiblesprite.h" diff --git a/src/rendering/vulkan/shaders/vk_shader.h b/src/rendering/vulkan/shaders/vk_shader.h index 37836d83c..d3649870b 100644 --- a/src/rendering/vulkan/shaders/vk_shader.h +++ b/src/rendering/vulkan/shaders/vk_shader.h @@ -4,7 +4,7 @@ #include #include "utility/vectors.h" -#include "r_data/matrix.h" +#include "matrix.h" #include "name.h" #include "hwrenderer/scene/hw_renderstate.h" diff --git a/src/utility/colormatcher.h b/src/utility/colormatcher.h index 4097479b9..c9623c664 100644 --- a/src/utility/colormatcher.h +++ b/src/utility/colormatcher.h @@ -40,7 +40,7 @@ #ifndef __COLORMATCHER_H__ #define __COLORMATCHER_H__ -#include +#include "palette.h" int BestColor (const uint32_t *pal_in, int r, int g, int b, int first, int num); diff --git a/src/r_data/matrix.cpp b/src/utility/matrix.cpp similarity index 100% rename from src/r_data/matrix.cpp rename to src/utility/matrix.cpp diff --git a/src/r_data/matrix.h b/src/utility/matrix.h similarity index 100% rename from src/r_data/matrix.h rename to src/utility/matrix.h diff --git a/src/utility/palette.cpp b/src/utility/palette.cpp new file mode 100644 index 000000000..e79e68a54 --- /dev/null +++ b/src/utility/palette.cpp @@ -0,0 +1,314 @@ +/* +** palette.cpp +** Palette and color utility functions +** +**--------------------------------------------------------------------------- +** Copyright 1998-2006 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "palette.h" +#include "palentry.h" + +/****************************/ +/* Palette management stuff */ +/****************************/ + +int BestColor (const uint32_t *pal_in, int r, int g, int b, int first, int num) +{ + const PalEntry *pal = (const PalEntry *)pal_in; + int bestcolor = first; + int bestdist = 257 * 257 + 257 * 257 + 257 * 257; + + for (int color = first; color < num; color++) + { + int x = r - pal[color].r; + int y = g - pal[color].g; + int z = b - pal[color].b; + int dist = x*x + y*y + z*z; + if (dist < bestdist) + { + if (dist == 0) + return color; + + bestdist = dist; + bestcolor = color; + } + } + return bestcolor; +} + + +// [SP] Re-implemented BestColor for more precision rather than speed. This function is only ever called once until the game palette is changed. + +int PTM_BestColor (const uint32_t *pal_in, int r, int g, int b, bool reverselookup, float powtable_val, int first, int num) +{ + const PalEntry *pal = (const PalEntry *)pal_in; + static double powtable[256]; + static bool firstTime = true; + static float trackpowtable = 0.; + + double fbestdist = DBL_MAX, fdist; + int bestcolor = 0; + + if (firstTime || trackpowtable != powtable_val) + { + auto pt = powtable_val; + trackpowtable = pt; + firstTime = false; + for (int x = 0; x < 256; x++) powtable[x] = pow((double)x/255, (double)pt); + } + + for (int color = first; color < num; color++) + { + double x = powtable[abs(r-pal[color].r)]; + double y = powtable[abs(g-pal[color].g)]; + double z = powtable[abs(b-pal[color].b)]; + fdist = x + y + z; + if (color == first || (reverselookup?(fdist <= fbestdist):(fdist < fbestdist))) + { + if (fdist == 0 && !reverselookup) + return color; + + fbestdist = fdist; + bestcolor = color; + } + } + return bestcolor; +} + +#if defined(_M_X64) || defined(_M_IX86) || defined(__i386__) || defined(__amd64__) + +#ifdef _MSC_VER +#include +#endif +#include + +static void DoBlending_SSE2(const PalEntry *from, PalEntry *to, int count, int r, int g, int b, int a) +{ + __m128i blendcolor; + __m128i blendalpha; + __m128i zero; + __m128i blending256; + __m128i color1; + __m128i color2; + size_t unaligned; + + unaligned = ((size_t)from | (size_t)to) & 0xF; + +#if defined(__amd64__) || defined(_M_X64) + int64_t color; + + blending256 = _mm_set_epi64x(0x10001000100ll, 0x10001000100ll); + + color = ((int64_t)r << 32) | (g << 16) | b; + blendcolor = _mm_set_epi64x(color, color); + + color = ((int64_t)a << 32) | (a << 16) | a; + blendalpha = _mm_set_epi64x(color, color); +#else + int color; + + blending256 = _mm_set_epi32(0x100, 0x1000100, 0x100, 0x1000100); + + color = (g << 16) | b; + blendcolor = _mm_set_epi32(r, color, r, color); + + color = (a << 16) | a; + blendalpha = _mm_set_epi32(a, color, a, color); +#endif + + blendcolor = _mm_mullo_epi16(blendcolor, blendalpha); // premultiply blend by alpha + blendalpha = _mm_subs_epu16(blending256, blendalpha); // one minus alpha + + zero = _mm_setzero_si128(); + + if (unaligned) + { + for (count >>= 2; count > 0; --count) + { + color1 = _mm_loadu_si128((__m128i *)from); + from += 4; + color2 = _mm_unpackhi_epi8(color1, zero); + color1 = _mm_unpacklo_epi8(color1, zero); + color1 = _mm_mullo_epi16(blendalpha, color1); + color2 = _mm_mullo_epi16(blendalpha, color2); + color1 = _mm_adds_epu16(blendcolor, color1); + color2 = _mm_adds_epu16(blendcolor, color2); + color1 = _mm_srli_epi16(color1, 8); + color2 = _mm_srli_epi16(color2, 8); + _mm_storeu_si128((__m128i *)to, _mm_packus_epi16(color1, color2)); + to += 4; + } + } + else + { + for (count >>= 2; count > 0; --count) + { + color1 = _mm_load_si128((__m128i *)from); + from += 4; + color2 = _mm_unpackhi_epi8(color1, zero); + color1 = _mm_unpacklo_epi8(color1, zero); + color1 = _mm_mullo_epi16(blendalpha, color1); + color2 = _mm_mullo_epi16(blendalpha, color2); + color1 = _mm_adds_epu16(blendcolor, color1); + color2 = _mm_adds_epu16(blendcolor, color2); + color1 = _mm_srli_epi16(color1, 8); + color2 = _mm_srli_epi16(color2, 8); + _mm_store_si128((__m128i *)to, _mm_packus_epi16(color1, color2)); + to += 4; + } + } +} +#endif + +void DoBlending (const PalEntry *from, PalEntry *to, int count, int r, int g, int b, int a) +{ + if (a == 0) + { + if (from != to) + { + memcpy (to, from, count * sizeof(uint32_t)); + } + return; + } + else if (a == 256) + { + uint32_t t = MAKERGB(r,g,b); + int i; + + for (i = 0; i < count; i++) + { + to[i] = t; + } + return; + } +#if defined(_M_X64) || defined(_M_IX86) || defined(__i386__) || defined(__amd64__) + else if (count >= 4) + { + int not3count = count & ~3; + DoBlending_SSE2 (from, to, not3count, r, g, b, a); + count &= 3; + if (count <= 0) + { + return; + } + from += not3count; + to += not3count; + } +#endif + int i, ia; + + ia = 256 - a; + r *= a; + g *= a; + b *= a; + + for (i = count; i > 0; i--, to++, from++) + { + to->r = (r + from->r * ia) >> 8; + to->g = (g + from->g * ia) >> 8; + to->b = (b + from->b * ia) >> 8; + } +} + +/****** Colorspace Conversion Functions ******/ + +// Code from http://www.cs.rit.edu/~yxv4997/t_convert.html + +// r,g,b values are from 0 to 1 +// h = [0,360], s = [0,1], v = [0,1] +// if s == 0, then h = -1 (undefined) + +// Green Doom guy colors: +// RGB - 0: { .46 1 .429 } 7: { .254 .571 .206 } 15: { .0317 .0794 .0159 } +// HSV - 0: { 116.743 .571 1 } 7: { 112.110 .639 .571 } 15: { 105.071 .800 .0794 } +void RGBtoHSV (float r, float g, float b, float *h, float *s, float *v) +{ + float min, max, delta, foo; + + if (r == g && g == b) + { + *h = 0; + *s = 0; + *v = r; + return; + } + + foo = r < g ? r : g; + min = (foo < b) ? foo : b; + foo = r > g ? r : g; + max = (foo > b) ? foo : b; + + *v = max; // v + + delta = max - min; + + *s = delta / max; // s + + if (r == max) + *h = (g - b) / delta; // between yellow & magenta + else if (g == max) + *h = 2 + (b - r) / delta; // between cyan & yellow + else + *h = 4 + (r - g) / delta; // between magenta & cyan + + *h *= 60; // degrees + if (*h < 0) + *h += 360; +} + +void HSVtoRGB (float *r, float *g, float *b, float h, float s, float v) +{ + int i; + float f, p, q, t; + + if (s == 0) + { // achromatic (grey) + *r = *g = *b = v; + return; + } + + h /= 60; // sector 0 to 5 + i = (int)floor (h); + f = h - i; // factorial part of h + p = v * (1 - s); + q = v * (1 - s * f); + t = v * (1 - s * (1 - f)); + + switch (i) + { + case 0: *r = v; *g = t; *b = p; break; + case 1: *r = q; *g = v; *b = p; break; + case 2: *r = p; *g = v; *b = t; break; + case 3: *r = p; *g = q; *b = v; break; + case 4: *r = t; *g = p; *b = v; break; + default: *r = v; *g = p; *b = q; break; + } +} + diff --git a/src/utility/palette.h b/src/utility/palette.h new file mode 100644 index 000000000..3e7c2f5eb --- /dev/null +++ b/src/utility/palette.h @@ -0,0 +1,19 @@ +#pragma once + +#include +struct PalEntry; + +#define MAKERGB(r,g,b) uint32_t(((r)<<16)|((g)<<8)|(b)) +#define MAKEARGB(a,r,g,b) uint32_t(((a)<<24)|((r)<<16)|((g)<<8)|(b)) + +#define APART(c) (((c)>>24)&0xff) +#define RPART(c) (((c)>>16)&0xff) +#define GPART(c) (((c)>>8)&0xff) +#define BPART(c) ((c)&0xff) + +int BestColor(const uint32_t* pal, int r, int g, int b, int first = 1, int num = 255); +int PTM_BestColor(const uint32_t* pal_in, int r, int g, int b, bool reverselookup, float powtable, int first = 1, int num = 255); +void DoBlending(const PalEntry* from, PalEntry* to, int count, int r, int g, int b, int a); +// Colorspace conversion RGB <-> HSV +void RGBtoHSV (float r, float g, float b, float *h, float *s, float *v); +void HSVtoRGB (float *r, float *g, float *b, float h, float s, float v); diff --git a/src/utility/x86.cpp b/src/utility/x86.cpp index a27c6a984..c03c87efb 100644 --- a/src/utility/x86.cpp +++ b/src/utility/x86.cpp @@ -257,81 +257,4 @@ void DumpCPUInfo(const CPUInfo *cpu) } } - -void DoBlending_SSE2(const PalEntry *from, PalEntry *to, int count, int r, int g, int b, int a) -{ - __m128i blendcolor; - __m128i blendalpha; - __m128i zero; - __m128i blending256; - __m128i color1; - __m128i color2; - size_t unaligned; - - unaligned = ((size_t)from | (size_t)to) & 0xF; - -#if defined(__amd64__) || defined(_M_X64) - int64_t color; - - blending256 = _mm_set_epi64x(0x10001000100ll, 0x10001000100ll); - - color = ((int64_t)r << 32) | (g << 16) | b; - blendcolor = _mm_set_epi64x(color, color); - - color = ((int64_t)a << 32) | (a << 16) | a; - blendalpha = _mm_set_epi64x(color, color); -#else - int color; - - blending256 = _mm_set_epi32(0x100, 0x1000100, 0x100, 0x1000100); - - color = (g << 16) | b; - blendcolor = _mm_set_epi32(r, color, r, color); - - color = (a << 16) | a; - blendalpha = _mm_set_epi32(a, color, a, color); -#endif - - blendcolor = _mm_mullo_epi16(blendcolor, blendalpha); // premultiply blend by alpha - blendalpha = _mm_subs_epu16(blending256, blendalpha); // one minus alpha - - zero = _mm_setzero_si128(); - - if (unaligned) - { - for (count >>= 2; count > 0; --count) - { - color1 = _mm_loadu_si128((__m128i *)from); - from += 4; - color2 = _mm_unpackhi_epi8(color1, zero); - color1 = _mm_unpacklo_epi8(color1, zero); - color1 = _mm_mullo_epi16(blendalpha, color1); - color2 = _mm_mullo_epi16(blendalpha, color2); - color1 = _mm_adds_epu16(blendcolor, color1); - color2 = _mm_adds_epu16(blendcolor, color2); - color1 = _mm_srli_epi16(color1, 8); - color2 = _mm_srli_epi16(color2, 8); - _mm_storeu_si128((__m128i *)to, _mm_packus_epi16(color1, color2)); - to += 4; - } - } - else - { - for (count >>= 2; count > 0; --count) - { - color1 = _mm_load_si128((__m128i *)from); - from += 4; - color2 = _mm_unpackhi_epi8(color1, zero); - color1 = _mm_unpacklo_epi8(color1, zero); - color1 = _mm_mullo_epi16(blendalpha, color1); - color2 = _mm_mullo_epi16(blendalpha, color2); - color1 = _mm_adds_epu16(blendcolor, color1); - color2 = _mm_adds_epu16(blendcolor, color2); - color1 = _mm_srli_epi16(color1, 8); - color2 = _mm_srli_epi16(color2, 8); - _mm_store_si128((__m128i *)to, _mm_packus_epi16(color1, color2)); - to += 4; - } - } -} #endif diff --git a/src/utility/x86.h b/src/utility/x86.h index 9c0f0f170..13152e0d7 100644 --- a/src/utility/x86.h +++ b/src/utility/x86.h @@ -106,7 +106,6 @@ struct PalEntry; void CheckCPUID (CPUInfo *cpu); void DumpCPUInfo (const CPUInfo *cpu); -void DoBlending_SSE2(const PalEntry *from, PalEntry *to, int count, int r, int g, int b, int a); #endif