1 /* This file is an image processing operation for GEGL 2 * 3 * GEGL is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU Lesser General Public 5 * License as published by the Free Software Foundation; either 6 * version 3 of the License, or (at your option) any later version. 7 * 8 * GEGL is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public 14 * License along with GEGL; if not, see <https://www.gnu.org/licenses/>. 15 * 16 * Copyright 2006 Øyvind Kolås <pippin@gimp.org> 17 */ 18 19 #include "config.h" 20 #include <glib/gi18n-lib.h> 21 22 23 #ifdef GEGL_PROPERTIES 24 25 property_object (buffer, _("Buffer location"), GEGL_TYPE_BUFFER) 26 description(_("A pre-existing GeglBuffer to write incoming buffer data to.")) 27 28 #else 29 30 #define GEGL_OP_SINK 31 #define GEGL_OP_C_SOURCE write-buffer.c 32 #define GEGL_OP_NAME write_buffer 33 34 #include "gegl-op.h" 35 36 #include "gegl/gegl-debug.h" 37 #include "opencl/gegl-cl.h" 38 #include "gegl-buffer-cl-iterator.h" 39 40 typedef struct 41 { 42 GeglBuffer *input; 43 GeglBuffer *output; 44 } ThreadData; 45 46 static void 47 thread_process (const GeglRectangle *area, 48 ThreadData *data) 49 { 50 gegl_buffer_copy (data->input, area, GEGL_ABYSS_NONE, 51 data->output, area); 52 } 53 54 static gboolean 55 process (GeglOperation *operation, 56 GeglBuffer *input, 57 const GeglRectangle *result, 58 gint level) 59 { 60 GeglProperties *o = GEGL_PROPERTIES (operation); 61 62 if (o->buffer) 63 { 64 GeglBuffer *output = GEGL_BUFFER (o->buffer); 65 const Babl *in_format = gegl_buffer_get_format (input); 66 const Babl *out_format = gegl_buffer_get_format (output); 67 68 if (gegl_operation_use_opencl (operation) 69 && gegl_cl_color_supported (in_format, out_format) == GEGL_CL_COLOR_CONVERT) 70 { 71 size_t size; 72 gboolean err; 73 cl_int cl_err = 0; 74 75 GeglBufferClIterator *i = gegl_buffer_cl_iterator_new (output, 76 result, 77 out_format, 78 GEGL_CL_BUFFER_WRITE); 79 80 gint read = gegl_buffer_cl_iterator_add (i, 81 input, 82 result, 83 out_format, 84 GEGL_CL_BUFFER_READ, 85 GEGL_ABYSS_NONE); 86 87 gegl_cl_color_babl (out_format, &size); 88 89 GEGL_NOTE (GEGL_DEBUG_OPENCL, 90 "write-buffer: " 91 "%p %p %s %s {%d %d %d %d}", 92 input, 93 output, 94 babl_get_name (in_format), 95 babl_get_name (out_format), 96 result->x, 97 result->y, 98 result->width, 99 result->height); 100 101 while (gegl_buffer_cl_iterator_next (i, &err)) 102 { 103 if (err) break; 104 105 cl_err = gegl_clEnqueueCopyBuffer (gegl_cl_get_command_queue (), 106 i->tex[read], 107 i->tex[0], 108 0, 109 0, 110 i->size[0] * size, 111 0, 112 NULL, 113 NULL); 114 115 if (cl_err != CL_SUCCESS) 116 { 117 GEGL_NOTE (GEGL_DEBUG_OPENCL, "Error: %s", gegl_cl_errstring (cl_err)); 118 break; 119 } 120 } 121 122 if (! (cl_err || err)) 123 return TRUE; 124 } 125 126 if (in_format == out_format) 127 { 128 gegl_buffer_copy (input, result, GEGL_ABYSS_NONE, 129 output, result); 130 } 131 else 132 { 133 ThreadData data; 134 135 data.input = input; 136 data.output = output; 137 138 gegl_parallel_distribute_area ( 139 result, 140 gegl_operation_get_pixels_per_thread (operation), 141 GEGL_SPLIT_STRATEGY_AUTO, 142 (GeglParallelDistributeAreaFunc) thread_process, 143 &data); 144 } 145 } 146 147 return TRUE; 148 } 149 150 static void 151 dispose (GObject *object) 152 { 153 GeglProperties *o = GEGL_PROPERTIES (object); 154 155 g_clear_object (&o->buffer); 156 157 G_OBJECT_CLASS (gegl_op_parent_class)->dispose (object); 158 } 159 160 static void 161 gegl_op_class_init (GeglOpClass *klass) 162 { 163 GeglOperationClass *operation_class; 164 GeglOperationSinkClass *sink_class; 165 166 operation_class = GEGL_OPERATION_CLASS (klass); 167 sink_class = GEGL_OPERATION_SINK_CLASS (klass); 168 169 sink_class->process = process; 170 sink_class->needs_full = FALSE; 171 172 G_OBJECT_CLASS (klass)->dispose = dispose; 173 174 gegl_operation_class_set_keys (operation_class, 175 "name", "gegl:write-buffer", 176 "title", _("Write Buffer"), 177 "categories" , "programming:output", 178 "description", _("Write input data into an existing GEGL buffer destination surface."), 179 NULL); 180 } 181 182 #endif 183