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"), GEGL_TYPE_BUFFER)
26     description(_("An already existing GeglBuffer to write incoming buffer data to, or NULL."))
27 
28 #else
29 
30 #define GEGL_OP_FILTER
31 #define GEGL_OP_NAME     copy_buffer
32 #define GEGL_OP_C_SOURCE copy-buffer.c
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 static void
41 prepare (GeglOperation *operation)
42 {
43   const Babl *format = gegl_operation_get_source_format (operation, "input");
44 
45   if (! format)
46     format = babl_format ("RGBA float");
47 
48   gegl_operation_set_format (operation, "input",  format);
49   gegl_operation_set_format (operation, "output", format);
50 }
51 
52 static gboolean
53 process (GeglOperation       *operation,
54          GeglBuffer          *input,
55          GeglBuffer          *output,
56          const GeglRectangle *result,
57          gint                 level)
58 {
59   GeglProperties *o = GEGL_PROPERTIES (operation);
60 
61   if (o->buffer)
62     {
63       GeglBuffer *buffer = GEGL_BUFFER (o->buffer);
64       const Babl *in_format = gegl_buffer_get_format (input);
65       const Babl *out_format = gegl_buffer_get_format (buffer);
66 
67       if (gegl_operation_use_opencl (operation)
68           && gegl_cl_color_supported (in_format, out_format) == GEGL_CL_COLOR_CONVERT)
69         {
70           size_t size;
71           gboolean err;
72           cl_int cl_err = 0;
73 
74           GeglBufferClIterator *i = gegl_buffer_cl_iterator_new (buffer,
75                                                                  result,
76                                                                  out_format,
77                                                                  GEGL_CL_BUFFER_WRITE);
78 
79           gint read = gegl_buffer_cl_iterator_add (i,
80                                                    input,
81                                                    result,
82                                                    out_format,
83                                                    GEGL_CL_BUFFER_READ,
84                                                    GEGL_ABYSS_NONE);
85 
86           gegl_cl_color_babl (out_format, &size);
87 
88           GEGL_NOTE (GEGL_DEBUG_OPENCL,
89                      "write-buffer: "
90                      "%p %p %s %s {%d %d %d %d}",
91                      input,
92                      buffer,
93                      babl_get_name (in_format),
94                      babl_get_name (out_format),
95                      result->x,
96                      result->y,
97                      result->width,
98                      result->height);
99 
100           while (gegl_buffer_cl_iterator_next (i, &err))
101             {
102               if (err) break;
103 
104               cl_err = gegl_clEnqueueCopyBuffer (gegl_cl_get_command_queue (),
105                                                  i->tex[read],
106                                                  i->tex[0],
107                                                  0,
108                                                  0,
109                                                  i->size[0] * size,
110                                                  0,
111                                                  NULL,
112                                                  NULL);
113 
114               if (cl_err != CL_SUCCESS)
115                 {
116                   GEGL_NOTE (GEGL_DEBUG_OPENCL, "Error: %s", gegl_cl_errstring (cl_err));
117                   break;
118                 }
119             }
120 
121           if (cl_err || err)
122             gegl_buffer_copy (input, result, GEGL_ABYSS_NONE,
123                               buffer, result);
124         }
125       else
126         gegl_buffer_copy (input, result, GEGL_ABYSS_NONE,
127                           buffer, result);
128     }
129 
130   if (output)
131     gegl_buffer_copy (input, result, GEGL_ABYSS_NONE,
132                       output, result);
133 
134   return TRUE;
135 }
136 
137 static void
138 gegl_op_class_init (GeglOpClass *klass)
139 {
140   GeglOperationClass       *operation_class;
141   GeglOperationFilterClass *filter_class;
142 
143   operation_class = GEGL_OPERATION_CLASS (klass);
144   filter_class    = GEGL_OPERATION_FILTER_CLASS (klass);
145 
146   operation_class->prepare      = prepare;
147   operation_class->cache_policy = GEGL_CACHE_POLICY_NEVER;
148   operation_class->threaded     = FALSE;
149   filter_class->process         = process;
150 
151   gegl_operation_class_set_keys (operation_class,
152     "name",           "gegl:copy-buffer",
153     "title",          _("Copy Buffer"),
154     "categories" ,    "programming",
155     "reference-hash", "ffb9e86edb25bc92e8d4e68f59bbb04b",
156     "description",    _("Writes image data to an already existing buffer"),
157     NULL);
158 }
159 
160 #endif
161