Created
November 13, 2017 18:26
-
-
Save masterzorag/c63f52442088ee3afe75dd72718963e1 to your computer and use it in GitHub Desktop.
An example of using Clang vector extension
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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