Commit: 2474058570b92f13747294e04fbb851ab5b2ab6a
Parent: 42466716c04ecb1502bedf711f2e0e78d8fa7d8e
Author: Randy Palamar
Date: Wed, 24 Jul 2024 20:24:47 -0600
dump colour to stdout on close
Diffstat:
M | colourpicker.c | | | 90 | ------------------------------------------------------------------------------- |
M | main.c | | | 17 | ++++++++++++++++- |
M | util.c | | | 89 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 105 insertions(+), 91 deletions(-)
diff --git a/colourpicker.c b/colourpicker.c
@@ -1,7 +1,4 @@
/* See LICENSE for copyright details */
-#include <emmintrin.h>
-#include <immintrin.h>
-
#include <raylib.h>
#include <stdio.h>
@@ -81,93 +78,6 @@ cut_rect_right(Rect r, f32 fraction)
return r;
}
-static Color
-colour_from_normalized(v4 colour)
-{
- __m128 colour_v = _mm_loadu_ps(colour.E);
- __m128 scale = _mm_set1_ps(255.0f);
- __m128i result = _mm_cvtps_epi32(_mm_mul_ps(colour_v, scale));
- _Alignas(16) u32 outu[4];
- _mm_store_si128((__m128i *)outu, result);
- return (Color){.r = outu[0] & 0xFF, .g = outu[1] & 0xFF, .b = outu[2] & 0xFF, .a = outu[3] & 0xFF };
-}
-
-static v4
-rgb_to_hsv(v4 rgb)
-{
- __m128 rgba = _mm_loadu_ps(rgb.E);
- __m128 gbra = _mm_shuffle_ps(rgba, rgba, _MM_SHUFFLE(3, 0, 2, 1));
- __m128 brga = _mm_shuffle_ps(gbra, gbra, _MM_SHUFFLE(3, 0, 2, 1));
-
- __m128 Max = _mm_max_ps(rgba, _mm_max_ps(gbra, brga));
- __m128 Min = _mm_min_ps(rgba, _mm_min_ps(gbra, brga));
- __m128 C = _mm_sub_ps(Max, Min);
-
- __m128 t = _mm_div_ps(_mm_sub_ps(gbra, brga), C);
-
- _Alignas(16) f32 aval[4] = { 0, 2, 4, 0 };
- t = _mm_add_ps(t, _mm_load_ps(aval));
-
- /* TODO: does (G - B) / C ever exceed 6.0? */
- /* NOTE: 1e9 ensures that the remainder after floor is 0.
- * This limits the fmodf to apply only to element [0] */
- _Alignas(16) f32 div[4] = { 6, 1e9, 1e9, 1e9 };
- __m128 six = _mm_set1_ps(6);
- __m128 rem = _mm_floor_ps(_mm_div_ps(t, _mm_load_ps(div)));
- t = _mm_sub_ps(t, _mm_mul_ps(rem, six));
-
- __m128 zero = _mm_set1_ps(0);
- __m128 maxmask = _mm_cmpeq_ps(rgba, Max);
-
- __m128 H = _mm_div_ps(_mm_blendv_ps(zero, t, maxmask), six);
- __m128 S = _mm_div_ps(C, Max);
-
- /* NOTE: Make sure H & S are 0 instead of NaN when V == 0 */
- __m128 zeromask = _mm_cmpeq_ps(zero, Max);
- H = _mm_blendv_ps(H, zero, zeromask);
- S = _mm_blendv_ps(S, zero, zeromask);
-
- __m128 H0 = _mm_shuffle_ps(H, H, _MM_SHUFFLE(3, 0, 0, 0));
- __m128 H1 = _mm_shuffle_ps(H, H, _MM_SHUFFLE(3, 1, 1, 1));
- __m128 H2 = _mm_shuffle_ps(H, H, _MM_SHUFFLE(3, 2, 2, 2));
- H = _mm_or_ps(H0, _mm_or_ps(H1, H2));
-
- /* NOTE: keep only element [0] from H vector; Max contains V & A */
- __m128 hva = _mm_blend_ps(Max, H, 0x01);
- v4 res;
- _mm_storeu_ps(res.E, _mm_blend_ps(hva, S, 0x02));
- return res;
-}
-
-static v4
-hsv_to_rgb(v4 hsv)
-{
- /* f(k(n)) = V - V*S*max(0, min(k, min(4 - k, 1)))
- * k(n) = fmod((n + H * 6), 6)
- * (R, G, B) = (f(n = 5), f(n = 3), f(n = 1))
- */
- _Alignas(16) f32 nval[4] = {5.0f, 3.0f, 1.0f, 0.0f};
- __m128 n = _mm_load_ps(nval);
- __m128 H = _mm_set1_ps(hsv.x);
- __m128 S = _mm_set1_ps(hsv.y);
- __m128 V = _mm_set1_ps(hsv.z);
- __m128 six = _mm_set1_ps(6);
-
- __m128 t = _mm_add_ps(n, _mm_mul_ps(six, H));
- __m128 rem = _mm_floor_ps(_mm_div_ps(t, six));
- __m128 k = _mm_sub_ps(t, _mm_mul_ps(rem, six));
-
- t = _mm_min_ps(_mm_sub_ps(_mm_set1_ps(4), k), _mm_set1_ps(1));
- t = _mm_max_ps(_mm_set1_ps(0), _mm_min_ps(k, t));
- t = _mm_mul_ps(t, _mm_mul_ps(S, V));
-
- v4 rgba;
- _mm_storeu_ps(rgba.E, _mm_sub_ps(V, t));
- rgba.a = hsv.a;
-
- return rgba;
-}
-
static void
fill_hsv_texture(RenderTexture texture, v4 hsv)
{
diff --git a/main.c b/main.c
@@ -96,7 +96,7 @@ main(void)
};
#ifndef _DEBUG
- SetTraceLogLevel(LOG_ERROR);
+ SetTraceLogLevel(LOG_NONE);
#endif
SetConfigFlags(FLAG_VSYNC_HINT);
@@ -114,4 +114,19 @@ main(void)
do_colour_picker(&ctx);
EndDrawing();
}
+
+ v4 rgba = {0};
+ switch (ctx.mode) {
+ case CPM_RGB: rgba = ctx.colour; break;
+ case CPM_HSV: rgba = hsv_to_rgb(ctx.colour); break;
+ default: ASSERT(0); break;
+ }
+
+ Color rl = colour_from_normalized(rgba);
+ u32 packed_rgba = rl.r << 24 | rl.g << 16 | rl.b << 8 | rl.a << 0;
+
+ printf("0x%08X|{.r = %0.02f, .g = %0.02f, .b = %0.02f, .a = %0.02f}\n",
+ packed_rgba, rgba.r, rgba.g, rgba.b, rgba.a);
+
+ return 0;
}
diff --git a/util.c b/util.c
@@ -1,6 +1,8 @@
/* See LICENSE for copyright details */
#ifndef _UTIL_C_
#define _UTIL_C_
+#include <emmintrin.h>
+#include <immintrin.h>
#include <stddef.h>
#include <stdint.h>
@@ -85,4 +87,91 @@ typedef struct {
#define ABS(x) ((x) < 0 ? (-x) : (x))
#define CLAMP(x, a, b) ((x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x))
+static Color
+colour_from_normalized(v4 colour)
+{
+ __m128 colour_v = _mm_loadu_ps(colour.E);
+ __m128 scale = _mm_set1_ps(255.0f);
+ __m128i result = _mm_cvtps_epi32(_mm_mul_ps(colour_v, scale));
+ _Alignas(16) u32 outu[4];
+ _mm_store_si128((__m128i *)outu, result);
+ return (Color){.r = outu[0] & 0xFF, .g = outu[1] & 0xFF, .b = outu[2] & 0xFF, .a = outu[3] & 0xFF };
+}
+
+static v4
+rgb_to_hsv(v4 rgb)
+{
+ __m128 rgba = _mm_loadu_ps(rgb.E);
+ __m128 gbra = _mm_shuffle_ps(rgba, rgba, _MM_SHUFFLE(3, 0, 2, 1));
+ __m128 brga = _mm_shuffle_ps(gbra, gbra, _MM_SHUFFLE(3, 0, 2, 1));
+
+ __m128 Max = _mm_max_ps(rgba, _mm_max_ps(gbra, brga));
+ __m128 Min = _mm_min_ps(rgba, _mm_min_ps(gbra, brga));
+ __m128 C = _mm_sub_ps(Max, Min);
+
+ __m128 t = _mm_div_ps(_mm_sub_ps(gbra, brga), C);
+
+ _Alignas(16) f32 aval[4] = { 0, 2, 4, 0 };
+ t = _mm_add_ps(t, _mm_load_ps(aval));
+
+ /* TODO: does (G - B) / C ever exceed 6.0? */
+ /* NOTE: 1e9 ensures that the remainder after floor is 0.
+ * This limits the fmodf to apply only to element [0] */
+ _Alignas(16) f32 div[4] = { 6, 1e9, 1e9, 1e9 };
+ __m128 six = _mm_set1_ps(6);
+ __m128 rem = _mm_floor_ps(_mm_div_ps(t, _mm_load_ps(div)));
+ t = _mm_sub_ps(t, _mm_mul_ps(rem, six));
+
+ __m128 zero = _mm_set1_ps(0);
+ __m128 maxmask = _mm_cmpeq_ps(rgba, Max);
+
+ __m128 H = _mm_div_ps(_mm_blendv_ps(zero, t, maxmask), six);
+ __m128 S = _mm_div_ps(C, Max);
+
+ /* NOTE: Make sure H & S are 0 instead of NaN when V == 0 */
+ __m128 zeromask = _mm_cmpeq_ps(zero, Max);
+ H = _mm_blendv_ps(H, zero, zeromask);
+ S = _mm_blendv_ps(S, zero, zeromask);
+
+ __m128 H0 = _mm_shuffle_ps(H, H, _MM_SHUFFLE(3, 0, 0, 0));
+ __m128 H1 = _mm_shuffle_ps(H, H, _MM_SHUFFLE(3, 1, 1, 1));
+ __m128 H2 = _mm_shuffle_ps(H, H, _MM_SHUFFLE(3, 2, 2, 2));
+ H = _mm_or_ps(H0, _mm_or_ps(H1, H2));
+
+ /* NOTE: keep only element [0] from H vector; Max contains V & A */
+ __m128 hva = _mm_blend_ps(Max, H, 0x01);
+ v4 res;
+ _mm_storeu_ps(res.E, _mm_blend_ps(hva, S, 0x02));
+ return res;
+}
+
+static v4
+hsv_to_rgb(v4 hsv)
+{
+ /* f(k(n)) = V - V*S*max(0, min(k, min(4 - k, 1)))
+ * k(n) = fmod((n + H * 6), 6)
+ * (R, G, B) = (f(n = 5), f(n = 3), f(n = 1))
+ */
+ _Alignas(16) f32 nval[4] = {5.0f, 3.0f, 1.0f, 0.0f};
+ __m128 n = _mm_load_ps(nval);
+ __m128 H = _mm_set1_ps(hsv.x);
+ __m128 S = _mm_set1_ps(hsv.y);
+ __m128 V = _mm_set1_ps(hsv.z);
+ __m128 six = _mm_set1_ps(6);
+
+ __m128 t = _mm_add_ps(n, _mm_mul_ps(six, H));
+ __m128 rem = _mm_floor_ps(_mm_div_ps(t, six));
+ __m128 k = _mm_sub_ps(t, _mm_mul_ps(rem, six));
+
+ t = _mm_min_ps(_mm_sub_ps(_mm_set1_ps(4), k), _mm_set1_ps(1));
+ t = _mm_max_ps(_mm_set1_ps(0), _mm_min_ps(k, t));
+ t = _mm_mul_ps(t, _mm_mul_ps(S, V));
+
+ v4 rgba;
+ _mm_storeu_ps(rgba.E, _mm_sub_ps(V, t));
+ rgba.a = hsv.a;
+
+ return rgba;
+}
+
#endif /* _UTIL_C_ */