[gegl/soc-2013-opecl-ops: 1/6] Added OpenCL support to color-to-alpha



commit 81f5de46655b71c773b4447c6396fe61ca12a6ef
Author: Carlos Zubieta <czubieta dev gmail com>
Date:   Tue Jul 23 18:08:06 2013 -0500

    Added OpenCL support to color-to-alpha

 opencl/color-to-alpha.cl           |   63 ++++++++++++++++++++++++++++++
 opencl/color-to-alpha.cl.h         |   65 +++++++++++++++++++++++++++++++
 operations/common/color-to-alpha.c |   75 +++++++++++++++++++++++++++++++-----
 3 files changed, 193 insertions(+), 10 deletions(-)
---
diff --git a/opencl/color-to-alpha.cl b/opencl/color-to-alpha.cl
new file mode 100644
index 0000000..9ca0894
--- /dev/null
+++ b/opencl/color-to-alpha.cl
@@ -0,0 +1,63 @@
+__kernel void cl_color_to_alpha(__global const float4 *in,
+                                __global       float4 *out,
+                                float4                color)
+{
+  int gid = get_global_id(0);
+  float4 in_v = in[gid];
+  float4 out_v = in_v;
+  float4 alpha;
+
+  alpha.w = in_v.w;
+
+  /*First component*/
+  if ( color.x < 0.00001f )
+    alpha.x = in_v.x;
+  else if ( in_v.x > color.x + 0.00001f )
+    alpha.x = (in_v.x - color.x) / (1.0f - color.x);
+  else if ( in_v.x < color.x - 0.00001f )
+    alpha.x = (color.x - in_v.x) / color.x;
+  else
+    alpha.x = 0.0f;
+  /*Second component*/
+  if ( color.y < 0.00001f )
+    alpha.y = in_v.y;
+  else if ( in_v.y > color.y + 0.00001f )
+    alpha.y = (in_v.y - color.y) / (1.0f - color.y);
+  else if ( in_v.y < color.y - 0.00001f )
+    alpha.y = (color.y - in_v.y) / color.y;
+  else
+    alpha.y = 0.0f;
+  /*Third component*/
+  if ( color.z < 0.00001f )
+    alpha.z = in_v.z;
+  else if ( in_v.z > color.z + 0.00001f )
+    alpha.z = (in_v.z - color.z) / (1.0f - color.z);
+  else if ( in_v.z < color.z - 0.00001f )
+    alpha.z = (color.z - in_v.z) / color.z;
+  else
+    alpha.z = 0.0f;
+
+  if (alpha.x > alpha.y)
+    {
+      if (alpha.x > alpha.z)
+        out_v.w = alpha.x;
+      else
+        out_v.w = alpha.z;
+    }
+  else if (alpha.y > alpha.z)
+    {
+      out_v.w = alpha.y;
+    }
+  else
+    {
+      out_v.w = alpha.z;
+    }
+
+  if (out_v.w >= 0.00001f)
+    {
+      out_v.xyz = (out_v.xyz - color.xyz) / out_v.www + color.xyz;
+      out_v.w *= alpha.w;
+    }
+
+    out[gid] = out_v;
+}
diff --git a/opencl/color-to-alpha.cl.h b/opencl/color-to-alpha.cl.h
new file mode 100644
index 0000000..0efc5af
--- /dev/null
+++ b/opencl/color-to-alpha.cl.h
@@ -0,0 +1,65 @@
+static const char* color_to_alpha_cl_source =
+"__kernel void cl_color_to_alpha(__global const float4 *in,                    \n"
+"                                __global       float4 *out,                   \n"
+"                                float4                color)                  \n"
+"{                                                                             \n"
+"  int gid = get_global_id(0);                                                 \n"
+"  float4 in_v = in[gid];                                                      \n"
+"  float4 out_v = in_v;                                                        \n"
+"  float4 alpha;                                                               \n"
+"                                                                              \n"
+"  alpha.w = in_v.w;                                                           \n"
+"                                                                              \n"
+"  /*First component*/                                                         \n"
+"  if ( color.x < 0.00001f )                                                   \n"
+"    alpha.x = in_v.x;                                                         \n"
+"  else if ( in_v.x > color.x + 0.00001f )                                     \n"
+"    alpha.x = (in_v.x - color.x) / (1.0f - color.x);                          \n"
+"  else if ( in_v.x < color.x - 0.00001f )                                     \n"
+"    alpha.x = (color.x - in_v.x) / color.x;                                   \n"
+"  else                                                                        \n"
+"    alpha.x = 0.0f;                                                           \n"
+"  /*Second component*/                                                        \n"
+"  if ( color.y < 0.00001f )                                                   \n"
+"    alpha.y = in_v.y;                                                         \n"
+"  else if ( in_v.y > color.y + 0.00001f )                                     \n"
+"    alpha.y = (in_v.y - color.y) / (1.0f - color.y);                          \n"
+"  else if ( in_v.y < color.y - 0.00001f )                                     \n"
+"    alpha.y = (color.y - in_v.y) / color.y;                                   \n"
+"  else                                                                        \n"
+"    alpha.y = 0.0f;                                                           \n"
+"  /*Third component*/                                                         \n"
+"  if ( color.z < 0.00001f )                                                   \n"
+"    alpha.z = in_v.z;                                                         \n"
+"  else if ( in_v.z > color.z + 0.00001f )                                     \n"
+"    alpha.z = (in_v.z - color.z) / (1.0f - color.z);                          \n"
+"  else if ( in_v.z < color.z - 0.00001f )                                     \n"
+"    alpha.z = (color.z - in_v.z) / color.z;                                   \n"
+"  else                                                                        \n"
+"    alpha.z = 0.0f;                                                           \n"
+"                                                                              \n"
+"  if (alpha.x > alpha.y)                                                      \n"
+"    {                                                                         \n"
+"      if (alpha.x > alpha.z)                                                  \n"
+"        out_v.w = alpha.x;                                                    \n"
+"      else                                                                    \n"
+"        out_v.w = alpha.z;                                                    \n"
+"    }                                                                         \n"
+"  else if (alpha.y > alpha.z)                                                 \n"
+"    {                                                                         \n"
+"      out_v.w = alpha.y;                                                      \n"
+"    }                                                                         \n"
+"  else                                                                        \n"
+"    {                                                                         \n"
+"      out_v.w = alpha.z;                                                      \n"
+"    }                                                                         \n"
+"                                                                              \n"
+"  if (out_v.w >= 0.00001f)                                                    \n"
+"    {                                                                         \n"
+"      out_v.xyz = (out_v.xyz - color.xyz) / out_v.www + color.xyz;            \n"
+"      out_v.w *= alpha.w;                                                     \n"
+"    }                                                                         \n"
+"                                                                              \n"
+"    out[gid] = out_v;                                                          \n"
+"}                                                                             \n"
+;
diff --git a/operations/common/color-to-alpha.c b/operations/common/color-to-alpha.c
index aae21c4..df96b70 100644
--- a/operations/common/color-to-alpha.c
+++ b/operations/common/color-to-alpha.c
@@ -42,9 +42,9 @@ static void
 prepare (GeglOperation *operation)
 {
   gegl_operation_set_format (operation, "input",
-                             babl_format ("R'G'B'A double"));
+                             babl_format ("R'G'B'A float"));
   gegl_operation_set_format (operation, "output",
-                             babl_format ("R'G'B'A double"));
+                             babl_format ("R'G'B'A float"));
 }
 
 /*
@@ -81,12 +81,12 @@ prepare (GeglOperation *operation)
 */
 
 static void
-color_to_alpha (const gdouble *color,
-                const gdouble *src,
-                gdouble       *dst)
+color_to_alpha (const gfloat *color,
+                const gfloat *src,
+                gfloat       *dst)
 {
   gint i;
-  gdouble alpha[4];
+  gfloat alpha[4];
 
   for (i=0; i<4; i++)
     dst[i] = src[i];
@@ -130,6 +130,58 @@ color_to_alpha (const gdouble *color,
   dst[3] *= alpha[3];
 }
 
+#include "opencl/gegl-cl.h"
+#include "opencl/color-to-alpha.cl.h"
+
+static GeglClRunData * cl_data = NULL;
+
+static gboolean
+cl_process (GeglOperation       *operation,
+            cl_mem              in,
+            cl_mem              out,
+            size_t              global_worksize,
+            const GeglRectangle *roi,
+            gint                level)
+{
+  GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
+  gfloat      color[4];
+  gegl_color_get_pixel (o->color, babl_format ("R'G'B'A float"), color);
+
+  if (!cl_data)
+    {
+      const char *kernel_name[] = {"cl_color_to_alpha",NULL};
+      cl_data = gegl_cl_compile_and_build (color_to_alpha_cl_source, kernel_name);
+    }
+  if (!cl_data) return TRUE;
+
+  {
+  cl_int cl_err = 0;
+  cl_float4 f_color;
+  f_color.s[0] = color[0];
+  f_color.s[1] = color[1];
+  f_color.s[2] = color[2];
+  f_color.s[3] = color[3];
+
+  cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 0,  sizeof(cl_mem),   (void*)&in);
+  CL_CHECK;
+  cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 1,  sizeof(cl_mem),   (void*)&out);
+  CL_CHECK;
+  cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 2,  sizeof(cl_float4),(void*)&f_color);
+  CL_CHECK;
+
+  cl_err = gegl_clEnqueueNDRangeKernel(gegl_cl_get_command_queue (),
+                                       cl_data->kernel[0], 1,
+                                       NULL, &global_worksize, NULL,
+                                       0, NULL, NULL);
+  CL_CHECK;
+  }
+
+  return  FALSE;
+
+error:
+  return TRUE;
+
+}
 
 
 static gboolean
@@ -141,12 +193,12 @@ process (GeglOperation       *operation,
          gint                 level)
 {
   GeglChantO *o      = GEGL_CHANT_PROPERTIES (operation);
-  const Babl *format = babl_format ("R'G'B'A double");
-  gdouble      color[4];
+  const Babl *format = babl_format ("R'G'B'A float");
+  gfloat      color[4];
   gint        x;
 
-  gdouble *in_buff = in_buf;
-  gdouble *out_buff = out_buf;
+  gfloat *in_buff = in_buf;
+  gfloat *out_buff = out_buf;
 
   gegl_color_get_pixel (o->color, format, color);
 
@@ -192,7 +244,10 @@ gegl_chant_class_init (GeglChantClass *klass)
   filter_class    = GEGL_OPERATION_POINT_FILTER_CLASS (klass);
 
   filter_class->process    = process;
+  filter_class->cl_process = cl_process;
+
   operation_class->prepare = prepare;
+  operation_class->opencl_support = TRUE;
 
   gegl_operation_class_set_keys (operation_class,
     "name",        "gegl:color-to-alpha",


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]