mirror of
https://github.com/brl/mutter.git
synced 2025-02-16 21:34:09 +00:00
[clutter-color] Use a different hls->rgb algorithm + use floating point
Using test-cogl-vertex-buffer as a test case which is CPU bound due to hls -> rgb conversions this alternative algorithm looked to be ~10% faster when tested on an X61s Lenovo.
This commit is contained in:
parent
567a96c96a
commit
bb93a98762
@ -132,35 +132,33 @@ clutter_color_darken (const ClutterColor *color,
|
|||||||
clutter_color_shade (color, 0.7, result);
|
clutter_color_shade (color, 0.7, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* clutter_color_to_hlsx:
|
* clutter_color_to_hls:
|
||||||
* @color: a #ClutterColor
|
* @color: a #ClutterColor
|
||||||
* @hue: return location for the hue value or %NULL
|
* @hue: return location for the hue value or %NULL
|
||||||
* @luminance: return location for the luminance value or %NULL
|
* @luminance: return location for the luminance value or %NULL
|
||||||
* @saturation: return location for the saturation value or %NULL
|
* @saturation: return location for the saturation value or %NULL
|
||||||
*
|
*
|
||||||
* Converts @color to the HLS format. Returned hue is in degrees (0 .. 360),
|
* Converts @color to the HLS format.
|
||||||
* luminance and saturation from interval <0 .. 1>.
|
|
||||||
*
|
*
|
||||||
* The implementation is in fixed point because we don't particularly
|
* The @hue value is in the 0 .. 360 range. The @luminance and
|
||||||
* care about precision. It can be moved to floating point at any later
|
* @saturation values are in the 0 .. 1 range.
|
||||||
* date.
|
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
clutter_color_to_hlsx (const ClutterColor *color,
|
clutter_color_to_hls (const ClutterColor *color,
|
||||||
CoglFixed *hue,
|
float *hue,
|
||||||
CoglFixed *luminance,
|
float *luminance,
|
||||||
CoglFixed *saturation)
|
float *saturation)
|
||||||
{
|
{
|
||||||
CoglFixed red, green, blue;
|
float red, green, blue;
|
||||||
CoglFixed min, max, delta;
|
float min, max, delta;
|
||||||
CoglFixed h, l, s;
|
float h, l, s;
|
||||||
|
|
||||||
g_return_if_fail (color != NULL);
|
g_return_if_fail (color != NULL);
|
||||||
|
|
||||||
red = COGL_FIXED_FAST_DIV (color->red, COGL_FIXED_255);
|
red = color->red / 255.0;
|
||||||
green = COGL_FIXED_FAST_DIV (color->green, COGL_FIXED_255);
|
green = color->green / 255.0;
|
||||||
blue = COGL_FIXED_FAST_DIV (color->blue, COGL_FIXED_255);
|
blue = color->blue / 255.0;
|
||||||
|
|
||||||
if (red > green)
|
if (red > green)
|
||||||
{
|
{
|
||||||
@ -193,25 +191,24 @@ clutter_color_to_hlsx (const ClutterColor *color,
|
|||||||
|
|
||||||
if (max != min)
|
if (max != min)
|
||||||
{
|
{
|
||||||
if (l <= COGL_FIXED_0_5)
|
if (l <= 0.5)
|
||||||
s = COGL_FIXED_DIV ((max - min), (max + min));
|
s = (max - min) / (max + min);
|
||||||
else
|
else
|
||||||
s = COGL_FIXED_DIV ((max - min),
|
s = (max - min) / (2.0 - max - min);
|
||||||
(COGL_FIXED_FROM_INT (2) - max - min));
|
|
||||||
|
|
||||||
delta = max - min;
|
delta = max - min;
|
||||||
|
|
||||||
if (red == max)
|
if (red == max)
|
||||||
h = COGL_FIXED_DIV ((green - blue), delta);
|
h = (green - blue) / delta;
|
||||||
else if (green == max)
|
else if (green == max)
|
||||||
h = COGL_FIXED_FROM_INT (2) + COGL_FIXED_DIV ((blue - red), delta);
|
h = 2.0 + (blue - red) / delta;
|
||||||
else if (blue == max)
|
else if (blue == max)
|
||||||
h = COGL_FIXED_FROM_INT (4) + COGL_FIXED_DIV ((red - green), delta);
|
h = 4.0 + (red - green) / delta;
|
||||||
|
|
||||||
h *= 60;
|
h *= 60;
|
||||||
|
|
||||||
if (h < 0)
|
if (h < 0)
|
||||||
h += COGL_FIXED_360;
|
h += 360.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hue)
|
if (hue)
|
||||||
@ -224,164 +221,6 @@ clutter_color_to_hlsx (const ClutterColor *color,
|
|||||||
*saturation = s;
|
*saturation = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* clutter_color_from_hlsx:
|
|
||||||
* @dest: (out): return location for a #ClutterColor
|
|
||||||
* @hue: hue value (0 .. 360)
|
|
||||||
* @luminance: luminance value (0 .. 1)
|
|
||||||
* @saturation: saturation value (0 .. 1)
|
|
||||||
*
|
|
||||||
* Converts a color expressed in HLS (hue, luminance and saturation)
|
|
||||||
* values into a #ClutterColor.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
clutter_color_from_hlsx (ClutterColor *color,
|
|
||||||
CoglFixed hue,
|
|
||||||
CoglFixed luminance,
|
|
||||||
CoglFixed saturation)
|
|
||||||
{
|
|
||||||
CoglFixed h, l, s;
|
|
||||||
CoglFixed m1, m2;
|
|
||||||
|
|
||||||
g_return_if_fail (color != NULL);
|
|
||||||
|
|
||||||
l = luminance;
|
|
||||||
s = saturation;
|
|
||||||
|
|
||||||
if (l <= COGL_FIXED_0_5)
|
|
||||||
m2 = COGL_FIXED_MUL (l, (COGL_FIXED_1 + s));
|
|
||||||
else
|
|
||||||
m2 = l + s - COGL_FIXED_MUL (l, s);
|
|
||||||
|
|
||||||
m1 = 2 * l - m2;
|
|
||||||
|
|
||||||
if (s == 0)
|
|
||||||
{
|
|
||||||
color->red = (guint8) (COGL_FIXED_TO_FLOAT (l) * 255);
|
|
||||||
color->green = (guint8) (COGL_FIXED_TO_FLOAT (l) * 255);
|
|
||||||
color->blue = (guint8) (COGL_FIXED_TO_FLOAT (l) * 255);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
h = hue + COGL_FIXED_120;
|
|
||||||
|
|
||||||
while (h > COGL_FIXED_360)
|
|
||||||
h -= COGL_FIXED_360;
|
|
||||||
|
|
||||||
while (h < 0)
|
|
||||||
h += COGL_FIXED_360;
|
|
||||||
|
|
||||||
if (h < COGL_FIXED_60)
|
|
||||||
{
|
|
||||||
CoglFixed tmp;
|
|
||||||
|
|
||||||
tmp = (m1 + COGL_FIXED_MUL_DIV ((m2 - m1), h, COGL_FIXED_60));
|
|
||||||
color->red = (guint8) (COGL_FIXED_TO_FLOAT (tmp) * 255);
|
|
||||||
}
|
|
||||||
else if (h < COGL_FIXED_180)
|
|
||||||
color->red = (guint8) (COGL_FIXED_TO_FLOAT (m2) * 255);
|
|
||||||
else if (h < COGL_FIXED_240)
|
|
||||||
{
|
|
||||||
CoglFixed tmp;
|
|
||||||
|
|
||||||
tmp = (m1 + COGL_FIXED_MUL_DIV ((m2 - m1),
|
|
||||||
(COGL_FIXED_240 - h),
|
|
||||||
COGL_FIXED_60));
|
|
||||||
color->red = (guint8) (COGL_FIXED_TO_FLOAT (tmp) * 255);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
color->red = (guint8) (COGL_FIXED_TO_FLOAT (m1) * 255);
|
|
||||||
|
|
||||||
h = hue;
|
|
||||||
while (h > COGL_FIXED_360)
|
|
||||||
h -= COGL_FIXED_360;
|
|
||||||
while (h < 0)
|
|
||||||
h += COGL_FIXED_360;
|
|
||||||
|
|
||||||
if (h < COGL_FIXED_60)
|
|
||||||
{
|
|
||||||
CoglFixed tmp;
|
|
||||||
|
|
||||||
tmp = (m1 + COGL_FIXED_MUL_DIV ((m2 - m1), h, COGL_FIXED_60));
|
|
||||||
color->green = (guint8) (COGL_FIXED_TO_FLOAT (tmp) * 255);
|
|
||||||
}
|
|
||||||
else if (h < COGL_FIXED_180)
|
|
||||||
color->green = (guint8) (COGL_FIXED_TO_FLOAT (m2) * 255);
|
|
||||||
else if (h < COGL_FIXED_240)
|
|
||||||
{
|
|
||||||
CoglFixed tmp;
|
|
||||||
|
|
||||||
tmp = (m1 + COGL_FIXED_MUL_DIV ((m2 - m1),
|
|
||||||
(COGL_FIXED_240 - h),
|
|
||||||
COGL_FIXED_60));
|
|
||||||
color->green = (guint8) (COGL_FIXED_TO_FLOAT (tmp) * 255);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
color->green = (guint8) (COGL_FIXED_TO_FLOAT (m1) * 255);
|
|
||||||
|
|
||||||
h = hue - COGL_FIXED_120;
|
|
||||||
|
|
||||||
while (h > COGL_FIXED_360)
|
|
||||||
h -= COGL_FIXED_360;
|
|
||||||
|
|
||||||
while (h < 0)
|
|
||||||
h += COGL_FIXED_360;
|
|
||||||
|
|
||||||
if (h < COGL_FIXED_60)
|
|
||||||
{
|
|
||||||
CoglFixed tmp;
|
|
||||||
|
|
||||||
tmp = (m1 + COGL_FIXED_MUL_DIV ((m2 - m1), h, COGL_FIXED_60));
|
|
||||||
color->blue = (guint8) (COGL_FIXED_TO_FLOAT (tmp) * 255);
|
|
||||||
}
|
|
||||||
else if (h < COGL_FIXED_180)
|
|
||||||
color->blue = (guint8) (COGL_FIXED_TO_FLOAT (m2) * 255);
|
|
||||||
else if (h < COGL_FIXED_240)
|
|
||||||
{
|
|
||||||
CoglFixed tmp;
|
|
||||||
|
|
||||||
tmp = (m1 + COGL_FIXED_MUL_DIV ((m2 - m1),
|
|
||||||
(COGL_FIXED_240 - h),
|
|
||||||
COGL_FIXED_60));
|
|
||||||
color->blue = (guint8) (COGL_FIXED_TO_FLOAT (tmp) * 255);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
color->blue = (guint8) (COGL_FIXED_TO_FLOAT (m1) * 255);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_color_to_hls:
|
|
||||||
* @color: a #ClutterColor
|
|
||||||
* @hue: return location for the hue value or %NULL
|
|
||||||
* @luminance: return location for the luminance value or %NULL
|
|
||||||
* @saturation: return location for the saturation value or %NULL
|
|
||||||
*
|
|
||||||
* Converts @color to the HLS format.
|
|
||||||
*
|
|
||||||
* The @hue value is in the 0 .. 360 range. The @luminance and
|
|
||||||
* @saturation values are in the 0 .. 1 range.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
clutter_color_to_hls (const ClutterColor *color,
|
|
||||||
gfloat *hue,
|
|
||||||
gfloat *luminance,
|
|
||||||
gfloat *saturation)
|
|
||||||
{
|
|
||||||
CoglFixed h, l, s;
|
|
||||||
|
|
||||||
clutter_color_to_hlsx (color, &h, &l, &s);
|
|
||||||
|
|
||||||
if (hue)
|
|
||||||
*hue = COGL_FIXED_TO_FLOAT (h);
|
|
||||||
|
|
||||||
if (luminance)
|
|
||||||
*luminance = COGL_FIXED_TO_FLOAT (l);
|
|
||||||
|
|
||||||
if (saturation)
|
|
||||||
*saturation = COGL_FIXED_TO_FLOAT (s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_color_from_hls:
|
* clutter_color_from_hls:
|
||||||
* @color: (out): return location for a #ClutterColor
|
* @color: (out): return location for a #ClutterColor
|
||||||
@ -394,54 +233,60 @@ clutter_color_to_hls (const ClutterColor *color,
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
clutter_color_from_hls (ClutterColor *color,
|
clutter_color_from_hls (ClutterColor *color,
|
||||||
gfloat hue,
|
float hue,
|
||||||
gfloat luminance,
|
float luminance,
|
||||||
gfloat saturation)
|
float saturation)
|
||||||
{
|
{
|
||||||
CoglFixed h, l, s;
|
float tmp1, tmp2;
|
||||||
|
float tmp3[3];
|
||||||
|
float clr[3];
|
||||||
|
int i;
|
||||||
|
|
||||||
h = COGL_FIXED_FROM_FLOAT (hue);
|
hue /= 360.0;
|
||||||
l = COGL_FIXED_FROM_FLOAT (luminance);
|
|
||||||
s = COGL_FIXED_FROM_FLOAT (saturation);
|
|
||||||
|
|
||||||
clutter_color_from_hlsx (color, h, l, s);
|
if (luminance == 0)
|
||||||
}
|
{
|
||||||
|
color->red = color->green = color->blue = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
if (saturation == 0)
|
||||||
* clutter_color_shadex:
|
{
|
||||||
* @color: a #ClutterColor
|
color->red = color->green = color->blue = luminance;
|
||||||
* @factor: the shade factor to apply, as a fixed point value
|
return;
|
||||||
* @result: (out): return location for the shaded color
|
}
|
||||||
*
|
|
||||||
* Shades @color by @factor and saves the modified color into @result.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
clutter_color_shadex (const ClutterColor *color,
|
|
||||||
CoglFixed factor,
|
|
||||||
ClutterColor *result)
|
|
||||||
{
|
|
||||||
CoglFixed h, l, s;
|
|
||||||
|
|
||||||
g_return_if_fail (color != NULL);
|
if (luminance <= 0.5)
|
||||||
g_return_if_fail (result != NULL);
|
tmp2 = luminance * (1.0 + saturation);
|
||||||
|
else
|
||||||
clutter_color_to_hlsx (color, &h, &l, &s);
|
tmp2 = luminance + saturation - (luminance * saturation);
|
||||||
|
|
||||||
l = COGL_FIXED_MUL (l, factor);
|
tmp1 = 2.0 * luminance - tmp2;
|
||||||
if (l > COGL_FIXED_1)
|
|
||||||
l = COGL_FIXED_1;
|
|
||||||
else if (l < 0)
|
|
||||||
l = 0;
|
|
||||||
|
|
||||||
s = COGL_FIXED_MUL (s, factor);
|
tmp3[0] = hue + 1.0 / 3.0;
|
||||||
if (s > COGL_FIXED_1)
|
tmp3[1] = hue;
|
||||||
s = COGL_FIXED_1;
|
tmp3[2] = hue - 1.0 / 3.0;
|
||||||
else if (s < 0)
|
|
||||||
s = 0;
|
|
||||||
|
|
||||||
clutter_color_from_hlsx (result, h, l, s);
|
|
||||||
|
|
||||||
result->alpha = color->alpha;
|
for (i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (tmp3[i] < 0)
|
||||||
|
tmp3[i] += 1.0;
|
||||||
|
if (tmp3[i] > 1)
|
||||||
|
tmp3[i] -= 1.0;
|
||||||
|
|
||||||
|
if (6.0 * tmp3[i] < 1.0)
|
||||||
|
clr[i] = tmp1 + (tmp2 - tmp1) * tmp3[i] * 6.0;
|
||||||
|
else if (2.0 * tmp3[i] < 1.0)
|
||||||
|
clr[i] = tmp2;
|
||||||
|
else if (3.0 * tmp3[i] < 2.0)
|
||||||
|
clr[i] = (tmp1 + (tmp2 - tmp1) * ((2.0 / 3.0) - tmp3[i]) * 6.0);
|
||||||
|
else
|
||||||
|
clr[i] = tmp1;
|
||||||
|
}
|
||||||
|
|
||||||
|
color->red = clr[0] * 255.0;
|
||||||
|
color->green = clr[1] * 255.0;
|
||||||
|
color->blue = clr[2] * 255.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -455,11 +300,30 @@ clutter_color_shadex (const ClutterColor *color,
|
|||||||
void
|
void
|
||||||
clutter_color_shade (const ClutterColor *color,
|
clutter_color_shade (const ClutterColor *color,
|
||||||
gdouble factor,
|
gdouble factor,
|
||||||
ClutterColor *result)
|
ClutterColor *result)
|
||||||
{
|
{
|
||||||
clutter_color_shadex (color,
|
float h, l, s;
|
||||||
COGL_FIXED_FROM_FLOAT (factor),
|
|
||||||
result);
|
g_return_if_fail (color != NULL);
|
||||||
|
g_return_if_fail (result != NULL);
|
||||||
|
|
||||||
|
clutter_color_to_hls (color, &h, &l, &s);
|
||||||
|
|
||||||
|
l *= factor;
|
||||||
|
if (l > 1.0)
|
||||||
|
l = 1.0;
|
||||||
|
else if (l < 0)
|
||||||
|
l = 0;
|
||||||
|
|
||||||
|
s *= factor;
|
||||||
|
if (s > 1.0)
|
||||||
|
s = 1.0;
|
||||||
|
else if (s < 0)
|
||||||
|
s = 0;
|
||||||
|
|
||||||
|
clutter_color_from_hls (result, h, l, s);
|
||||||
|
|
||||||
|
result->alpha = color->alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,6 +41,8 @@
|
|||||||
#define HSL_OFFSET 0.5 /* the hue that we map an amplitude of 0 too */
|
#define HSL_OFFSET 0.5 /* the hue that we map an amplitude of 0 too */
|
||||||
#define HSL_SCALE 0.25
|
#define HSL_SCALE 0.25
|
||||||
|
|
||||||
|
#define USE_CLUTTER_COLOR 1
|
||||||
|
|
||||||
typedef struct _TestState
|
typedef struct _TestState
|
||||||
{
|
{
|
||||||
ClutterActor *dummy;
|
ClutterActor *dummy;
|
||||||
@ -52,6 +54,7 @@ typedef struct _TestState
|
|||||||
ClutterTimeline *timeline;
|
ClutterTimeline *timeline;
|
||||||
} TestState;
|
} TestState;
|
||||||
|
|
||||||
|
#ifndef USE_CLUTTER_COLOR
|
||||||
/* This algorithm is adapted from the book:
|
/* This algorithm is adapted from the book:
|
||||||
* Fundamentals of Interactive Computer Graphics by Foley and van Dam
|
* Fundamentals of Interactive Computer Graphics by Foley and van Dam
|
||||||
*/
|
*/
|
||||||
@ -105,6 +108,7 @@ hsl_to_rgb (float h, float s, float l,
|
|||||||
*g = clr[1] * 255.0;
|
*g = clr[1] * 255.0;
|
||||||
*b = clr[2] * 255.0;
|
*b = clr[2] * 255.0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
frame_cb (ClutterTimeline *timeline,
|
frame_cb (ClutterTimeline *timeline,
|
||||||
@ -152,7 +156,11 @@ frame_cb (ClutterTimeline *timeline,
|
|||||||
s = 0.5;
|
s = 0.5;
|
||||||
l = 0.25 + (period_progress_sin + 1.0) / 4.0;
|
l = 0.25 + (period_progress_sin + 1.0) / 4.0;
|
||||||
color = &state->quad_mesh_colors[4 * vert_index];
|
color = &state->quad_mesh_colors[4 * vert_index];
|
||||||
|
#ifdef USE_CLUTTER_COLOR
|
||||||
|
clutter_color_from_hls ((ClutterColor *)color, h * 360.0, l, s);
|
||||||
|
#else
|
||||||
hsl_to_rgb (h, s, l, &color[0], &color[1], &color[2]);
|
hsl_to_rgb (h, s, l, &color[0], &color[1], &color[2]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
cogl_vertex_buffer_add (state->buffer,
|
cogl_vertex_buffer_add (state->buffer,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user