ufo-filter-padding-2d.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. #include <gmodule.h>
  2. #ifdef __APPLE__
  3. #include <OpenCL/cl.h>
  4. #else
  5. #include <CL/cl.h>
  6. #endif
  7. #include <ufo/ufo-resource-manager.h>
  8. #include <ufo/ufo-filter.h>
  9. #include <ufo/ufo-buffer.h>
  10. #include "ufo-filter-padding-2d.h"
  11. /**
  12. * SECTION:ufo-filter-padding-2d
  13. * @Short_description:
  14. * @Title: padding2d
  15. *
  16. * Detailed description.
  17. */
  18. typedef enum {
  19. PADDING_ZERO = 0,
  20. PADDING_CONST,
  21. PADDING_GAVG,
  22. PADDING_BREP
  23. } PaddingMode;
  24. struct _UfoFilterPadding2DPrivate
  25. {
  26. guint in_width;
  27. guint in_height;
  28. guint out_width;
  29. guint out_height;
  30. // extent adds
  31. guint xl;
  32. guint xr;
  33. guint yt;
  34. guint yb;
  35. size_t global_work_size_small[2];
  36. size_t global_work_size_large[2];
  37. PaddingMode mode;
  38. // padding constant
  39. float pconst;
  40. cl_kernel kernel_iconst;
  41. cl_kernel kernel_cpyimg;
  42. cl_kernel kernel_brep;
  43. };
  44. G_DEFINE_TYPE(UfoFilterPadding2D, ufo_filter_padding_2d, UFO_TYPE_FILTER)
  45. #define UFO_FILTER_PADDING_2D_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_FILTER_PADDING_2D, UfoFilterPadding2DPrivate))
  46. enum {
  47. PROP_0 = 0,
  48. PROP_XL,
  49. PROP_XR,
  50. PROP_YT,
  51. PROP_YB,
  52. PROP_MODE,
  53. PROP_PCONST,
  54. N_PROPERTIES
  55. };
  56. static GParamSpec *padding_2d_properties[N_PROPERTIES] = { NULL, };
  57. static void
  58. ufo_filter_padding_2d_initialize (UfoFilter *filter, UfoBuffer *params[], guint **dim_sizes, GError **error)
  59. {
  60. UfoFilterPadding2DPrivate *priv = UFO_FILTER_PADDING_2D_GET_PRIVATE(filter);
  61. UfoResourceManager *manager = ufo_filter_get_resource_manager(filter);
  62. GError *tmp_error = NULL;
  63. priv->kernel_iconst = ufo_resource_manager_get_kernel(manager, "padding_2d.cl", "padding_2d_init_const", &tmp_error);
  64. priv->kernel_cpyimg = ufo_resource_manager_get_kernel(manager, "padding_2d.cl", "padding_2d_copy_in", &tmp_error);
  65. priv->kernel_brep = ufo_resource_manager_get_kernel(manager, "padding_2d.cl", "padding_2d_brep", &tmp_error);
  66. if (tmp_error != NULL) {
  67. g_propagate_error (error, tmp_error);
  68. return;
  69. }
  70. ufo_buffer_get_2d_dimensions (params[0], &priv->in_width, &priv->in_height);
  71. dim_sizes[0][0] = priv->out_width = priv->xl + priv->in_width + priv->xr;
  72. dim_sizes[0][1] = priv->out_height = priv->yt + priv->in_height + priv->yb;
  73. priv->global_work_size_small[0] = (size_t) priv->in_width;
  74. priv->global_work_size_small[1] = (size_t) priv->in_height;
  75. priv->global_work_size_large[0] = (size_t) dim_sizes[0][0];
  76. priv->global_work_size_large[1] = (size_t) dim_sizes[0][1];
  77. }
  78. /*
  79. * This is the main method in which the filter processes one buffer after
  80. * another.
  81. */
  82. static void
  83. ufo_filter_padding_2d_process_gpu(UfoFilter *filter, UfoBuffer *input[], UfoBuffer *output[], GError **error)
  84. {
  85. g_return_if_fail (UFO_IS_FILTER (filter));
  86. cl_command_queue command_queue = ufo_filter_get_command_queue (filter);
  87. UfoFilterPadding2DPrivate *priv = UFO_FILTER_PADDING_2D_GET_PRIVATE(filter);
  88. const PaddingMode mode = priv->mode;
  89. const guint pxl = priv->xl;
  90. const guint pyt = priv->yt;
  91. float pval = priv->pconst;
  92. const guint ixs = priv->in_width;
  93. const guint iys = priv->in_height;
  94. const guint oxs = priv->out_width;
  95. // init padding value for different modes
  96. if (mode == PADDING_ZERO)
  97. pval = 0.0;
  98. cl_event event;
  99. cl_mem input_mem = (cl_mem) ufo_buffer_get_device_array (input[0], command_queue);
  100. cl_mem output_mem = (cl_mem) ufo_buffer_get_device_array (output[0], command_queue);
  101. if (mode == PADDING_GAVG) {
  102. float *indata = ufo_buffer_get_host_array(input[0], command_queue);
  103. float sum = 0;
  104. guint psz = ixs * iys;
  105. for (guint i =0; i < psz; i++)
  106. sum += indata[i];
  107. pval = sum / (float)psz;
  108. }
  109. // processing itself
  110. if ((mode == PADDING_ZERO) || (mode == PADDING_CONST) || (mode == PADDING_GAVG)) {
  111. cl_kernel k_iconst = priv->kernel_iconst;
  112. cl_kernel k_cpyimg = priv->kernel_cpyimg;
  113. /// fill with constant
  114. CHECK_OPENCL_ERROR(clSetKernelArg( k_iconst, 0, sizeof(cl_mem), (void *) &output_mem));
  115. CHECK_OPENCL_ERROR(clSetKernelArg( k_iconst, 1, sizeof(int), &oxs));
  116. CHECK_OPENCL_ERROR(clSetKernelArg( k_iconst, 2, sizeof(float), &pval));
  117. CHECK_OPENCL_ERROR(clEnqueueNDRangeKernel(command_queue, k_iconst,
  118. 2, NULL, priv->global_work_size_large, NULL,
  119. 0, NULL, &event));
  120. //ufo_buffer_attach_event(output, event);
  121. /// copy old image
  122. CHECK_OPENCL_ERROR(clSetKernelArg( k_cpyimg, 0, sizeof(cl_mem), (void *) &input_mem));
  123. CHECK_OPENCL_ERROR(clSetKernelArg( k_cpyimg, 1, sizeof(cl_mem), (void *) &output_mem));
  124. CHECK_OPENCL_ERROR(clSetKernelArg( k_cpyimg, 2, sizeof(int), &ixs));
  125. CHECK_OPENCL_ERROR(clSetKernelArg( k_cpyimg, 3, sizeof(int), &oxs));
  126. CHECK_OPENCL_ERROR(clSetKernelArg( k_cpyimg, 4, sizeof(int), &pxl));
  127. CHECK_OPENCL_ERROR(clSetKernelArg( k_cpyimg, 5, sizeof(int), &pyt));
  128. //cl_event event2;
  129. CHECK_OPENCL_ERROR(clEnqueueNDRangeKernel(command_queue, k_cpyimg,
  130. 2, NULL, priv->global_work_size_small, NULL,
  131. 0, NULL, &event));
  132. //ufo_buffer_attach_event(output, event2);
  133. }
  134. if (mode == PADDING_BREP) {
  135. cl_kernel k_brep = priv->kernel_brep;
  136. CHECK_OPENCL_ERROR(clSetKernelArg( k_brep, 0, sizeof(cl_mem), (void *) &input_mem));
  137. CHECK_OPENCL_ERROR(clSetKernelArg( k_brep, 1, sizeof(cl_mem), (void *) &output_mem));
  138. CHECK_OPENCL_ERROR(clSetKernelArg( k_brep, 2, sizeof(int), &ixs));
  139. CHECK_OPENCL_ERROR(clSetKernelArg( k_brep, 3, sizeof(int), &iys));
  140. CHECK_OPENCL_ERROR(clSetKernelArg( k_brep, 4, sizeof(int), &oxs));
  141. CHECK_OPENCL_ERROR(clSetKernelArg( k_brep, 5, sizeof(int), &pxl));
  142. CHECK_OPENCL_ERROR(clSetKernelArg( k_brep, 6, sizeof(int), &pyt));
  143. CHECK_OPENCL_ERROR(clEnqueueNDRangeKernel(command_queue, k_brep,
  144. 2, NULL, priv->global_work_size_large, NULL,
  145. 0, NULL, &event));
  146. // ufo_buffer_attach_event(output, event);
  147. }
  148. clFinish(command_queue); // synchro?
  149. }
  150. static void
  151. ufo_filter_padding_2d_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
  152. {
  153. UfoFilterPadding2D *self = UFO_FILTER_PADDING_2D(object);
  154. switch (property_id) {
  155. case PROP_XL:
  156. self->priv->xl = g_value_get_uint(value);
  157. break;
  158. case PROP_XR:
  159. self->priv->xr = g_value_get_uint(value);
  160. break;
  161. case PROP_YT:
  162. self->priv->yt = g_value_get_uint(value);
  163. break;
  164. case PROP_YB:
  165. self->priv->yb = g_value_get_uint(value);
  166. break;
  167. case PROP_MODE:
  168. if (!g_strcmp0(g_value_get_string(value), "zero"))
  169. self->priv->mode = PADDING_ZERO;
  170. else if (!g_strcmp0(g_value_get_string(value), "const"))
  171. self->priv->mode = PADDING_CONST;
  172. else if (!g_strcmp0(g_value_get_string(value), "gavg"))
  173. self->priv->mode = PADDING_GAVG;
  174. else if (!g_strcmp0(g_value_get_string(value), "brep"))
  175. self->priv->mode = PADDING_BREP;
  176. else
  177. G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
  178. break;
  179. case PROP_PCONST:
  180. self->priv->pconst = (float) g_value_get_double(value);
  181. break;
  182. default:
  183. G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
  184. break;
  185. }
  186. }
  187. static void
  188. ufo_filter_padding_2d_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
  189. {
  190. UfoFilterPadding2D *self = UFO_FILTER_PADDING_2D(object);
  191. switch (property_id) {
  192. case PROP_XL:
  193. g_value_set_uint(value, self->priv->xl);
  194. break;
  195. case PROP_XR:
  196. g_value_set_uint(value, self->priv->xr);
  197. break;
  198. case PROP_YT:
  199. g_value_set_uint(value, self->priv->yt);
  200. break;
  201. case PROP_YB:
  202. g_value_set_uint(value, self->priv->yb);
  203. break;
  204. case PROP_MODE:
  205. switch (self->priv->mode) {
  206. case PADDING_ZERO:
  207. g_value_set_string(value, "zero");
  208. break;
  209. case PADDING_CONST:
  210. g_value_set_string(value, "const");
  211. break;
  212. case PADDING_GAVG:
  213. g_value_set_string(value, "gavg");
  214. break;
  215. case PADDING_BREP:
  216. g_value_set_string(value, "brep");
  217. break;
  218. default:
  219. G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
  220. break;
  221. }
  222. break;
  223. case PROP_PCONST:
  224. g_value_set_double(value, self->priv->pconst);
  225. break;
  226. default:
  227. G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
  228. break;
  229. }
  230. }
  231. static void ufo_filter_padding_2d_class_init(UfoFilterPadding2DClass *klass)
  232. {
  233. GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
  234. UfoFilterClass *filter_class = UFO_FILTER_CLASS(klass);
  235. gobject_class->set_property = ufo_filter_padding_2d_set_property;
  236. gobject_class->get_property = ufo_filter_padding_2d_get_property;
  237. filter_class->initialize = ufo_filter_padding_2d_initialize;
  238. filter_class->process_gpu = ufo_filter_padding_2d_process_gpu;
  239. padding_2d_properties[PROP_XL] =
  240. g_param_spec_uint("xl",
  241. "Number of additional pixel on the left hand image side",
  242. "Number of additional pixel on the left hand image side",
  243. 0, 16384, 1,
  244. G_PARAM_READWRITE);
  245. padding_2d_properties[PROP_XR] =
  246. g_param_spec_uint("xr",
  247. "Number of additional pixel on the right hand image side",
  248. "Number of additional pixel on the right hand image side",
  249. 0, 16384, 1,
  250. G_PARAM_READWRITE);
  251. padding_2d_properties[PROP_YT] =
  252. g_param_spec_uint("yt",
  253. "Number of additional pixel on the top image side",
  254. "Number of additional pixel on the top image side",
  255. 0, 16384, 1,
  256. G_PARAM_READWRITE);
  257. padding_2d_properties[PROP_YB] =
  258. g_param_spec_uint("yb",
  259. "Number of additional pixel on the bottom image side",
  260. "Number of additional pixel on the bottom image side",
  261. 0, 16384, 1,
  262. G_PARAM_READWRITE);
  263. padding_2d_properties[PROP_MODE] =
  264. g_param_spec_string("mode",
  265. "Padding mode can be 'zero', 'const', 'gavg' or 'brep' ",
  266. "Padding mode can be 'zero', 'const', 'gavg' or 'brep' ",
  267. "zero",
  268. G_PARAM_READWRITE);
  269. padding_2d_properties[PROP_PCONST] =
  270. g_param_spec_double("pconst",
  271. "Padding constant",
  272. "Padding constant",
  273. -320000.0,
  274. 320000.0,
  275. 0.0,
  276. G_PARAM_READWRITE);
  277. g_object_class_install_property(gobject_class, PROP_XL, padding_2d_properties[PROP_XL]);
  278. g_object_class_install_property(gobject_class, PROP_XR, padding_2d_properties[PROP_XR]);
  279. g_object_class_install_property(gobject_class, PROP_YT, padding_2d_properties[PROP_YT]);
  280. g_object_class_install_property(gobject_class, PROP_YB, padding_2d_properties[PROP_YB]);
  281. g_object_class_install_property(gobject_class, PROP_MODE, padding_2d_properties[PROP_MODE]);
  282. g_object_class_install_property(gobject_class, PROP_PCONST, padding_2d_properties[PROP_PCONST]);
  283. g_type_class_add_private(gobject_class, sizeof(UfoFilterPadding2DPrivate));
  284. }
  285. static void
  286. ufo_filter_padding_2d_init(UfoFilterPadding2D *self)
  287. {
  288. UfoFilterPadding2DPrivate *priv = self->priv = UFO_FILTER_PADDING_2D_GET_PRIVATE(self);
  289. UfoInputParameter input_params[] = {{2, UFO_FILTER_INFINITE_INPUT}};
  290. UfoOutputParameter output_params[] = {{2}};
  291. // set default values
  292. priv->xl = 1;
  293. priv->xr = 1;
  294. priv->yt = 1;
  295. priv->yb = 1;
  296. priv->mode = PADDING_ZERO;
  297. priv->pconst = 0.0;
  298. priv->kernel_iconst = NULL;
  299. priv->kernel_cpyimg = NULL;
  300. priv->kernel_brep = NULL;
  301. // register filter input and output
  302. ufo_filter_register_inputs (UFO_FILTER (self), 1, input_params);
  303. ufo_filter_register_outputs (UFO_FILTER (self), 1, output_params);
  304. }
  305. G_MODULE_EXPORT
  306. UfoFilter *ufo_filter_plugin_new(void)
  307. {
  308. return g_object_new(UFO_TYPE_FILTER_PADDING_2D, NULL);
  309. }