Skip to content

Instantly share code, notes, and snippets.

@masterzorag
Created November 13, 2017 18:26
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save masterzorag/c63f52442088ee3afe75dd72718963e1 to your computer and use it in GitHub Desktop.
Save masterzorag/c63f52442088ee3afe75dd72718963e1 to your computer and use it in GitHub Desktop.
An example of using Clang vector extension
/*
an example of using GCC/Clang vector extension
clang argb_vector.c
./a.out
0 ffffffff ffffffff
1 dde0e2e5 dddfe1e4
2 bbc0c5ca bbbfc4c9
3 99a1a8af 99a0a7ae
4 77818b95 77808a94
5 55626e7a 55616d79
6 3342515f 3341505e
7 11223344 11223344
*/
#include <stdint.h>
#include <stdio.h>
// compose ARGB color by components
#define ARGB(a, r, g, b) ( \
(((a) &0xFF) <<24) | (((r) &0xFF) <<16) | \
(((g) &0xFF) << 8) | (((b) &0xFF) << 0))
// extract single component form ARGB color
#define GET_A(color) ((color >>24) &0xFF)
#define GET_R(color) ((color >>16) &0xFF)
#define GET_G(color) ((color >> 8) &0xFF)
#define GET_B(color) ((color >> 0) &0xFF)
#define SIMPLE_GRADIENT_STEPS ((uint8_t)(16 /2)) // steps we split delta
static uint32_t fading_color[SIMPLE_GRADIENT_STEPS]; // precomputed gradient [0-7]
/***********************************************************************
* simple gradient (ARGB)
*
* uint32_t *a = pointer to start color
* uint32_t *b = pointer to end color
* uint8_t steps = number of steps we split fade
* uint8_t step = which step we compute and return
***********************************************************************/
typedef float float4 __attribute__((ext_vector_type(4)));
/*
https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
https://clang.llvm.org/docs/LanguageExtensions.html#vector-literals
*/
static uint32_t simple_gradient(const uint32_t *a, const uint32_t *b, const uint8_t steps, const uint8_t step)
{
float4 fr4, to4, col; // use .xyzw vector components as ARGB color components
// load vectors
fr4 = (float4){ GET_A(*a), GET_R(*a), GET_G(*a), GET_B(*a) };
to4 = (float4){ GET_A(*b), GET_R(*b), GET_G(*b), GET_B(*b) };
// compute which color we return
col = ((to4 - fr4) / ( (float)(steps -1) )); // num of slice
fr4 += col * ( (float)(step) ); // requested one
return ARGB( (uint8_t)fr4.x, (uint8_t)fr4.y, (uint8_t)fr4.z, (uint8_t)fr4.w );
}
static uint32_t simple_gradient_v1(const uint32_t *a, const uint32_t *b, const uint8_t steps, const uint8_t step)
{
uint8_t fr[4], to[4];
float st[4];
fr[0] = GET_A(*a), fr[1] = GET_R(*a), fr[2] = GET_G(*a), fr[3] = GET_B(*a), // load in fr4
to[0] = GET_A(*b), to[1] = GET_R(*b), to[2] = GET_G(*b), to[3] = GET_B(*b); // load in to4
st[0] = ((to[0] - fr[0]) / (float)(steps -1));
st[1] = ((to[1] - fr[1]) / (float)(steps -1));
st[2] = ((to[2] - fr[2]) / (float)(steps -1));
st[3] = ((to[3] - fr[3]) / (float)(steps -1));
return ARGB((int)fr[0] + (int)(st[0] * step),
(int)fr[1] + (int)(st[1] * step),
(int)fr[2] + (int)(st[2] * step),
(int)fr[3] + (int)(st[3] * step));
}
/***********************************************************************
* update_gradient
*
* precompute palette to use in print_text() and setup colors range
*
* uint32_t *a = pointer to start color
* uint32_t *b = pointer to end color
***********************************************************************/
void update_gradient(const uint32_t *a, const uint32_t *b)
{
for(uint8_t i = 0; i < SIMPLE_GRADIENT_STEPS; i++)
{
fading_color[i] = (*a == *b) ? *a : simple_gradient_v1(a, b, SIMPLE_GRADIENT_STEPS, i);
printf("%d %8x ", i, fading_color[i]);
fading_color[i] = (*a == *b) ? *a : simple_gradient(a, b, SIMPLE_GRADIENT_STEPS, i);
printf("%8x\n", fading_color[i]);
}
}
int main()
{
uint32_t c1, c2;
c1 = 0xffffffff;
c2 = 0x11223344;
// report two coloumn for each version of the function
update_gradient(&c1, &c2);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment