"Initial commit to Gerrit"
[profile/ivi/cogl.git] / cogl / cogl-pipeline-snippet.c
1 /*
2  * Cogl
3  *
4  * An object oriented GL/GLES Abstraction/Utility Layer
5  *
6  * Copyright (C) 2011 Intel Corporation.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library. If not, see
20  * <http://www.gnu.org/licenses/>.
21  *
22  *
23  *
24  * Authors:
25  *   Neil Roberts <neil@linux.intel.com>
26  */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include <string.h>
33
34 #include "cogl-pipeline-snippet-private.h"
35 #include "cogl-snippet-private.h"
36 #include "cogl-util.h"
37
38 /* Helper functions that are used by both GLSL pipeline backends */
39
40 void
41 _cogl_pipeline_snippet_generate_code (const CoglPipelineSnippetData *data)
42 {
43   CoglPipelineSnippet *first_snippet, *snippet;
44   int snippet_num = 0;
45   int n_snippets = 0;
46
47   first_snippet = COGL_LIST_FIRST (data->snippets);
48
49   /* First count the number of snippets so we can easily tell when
50      we're at the last one */
51   COGL_LIST_FOREACH (snippet, data->snippets, list_node)
52     if (snippet->snippet->hook == data->hook)
53       {
54         /* Don't bother processing any previous snippets if we reach
55            one that has a replacement */
56         if (snippet->snippet->replace)
57           {
58             n_snippets = 1;
59             first_snippet = snippet;
60           }
61         else
62           n_snippets++;
63       }
64
65   /* If there weren't any snippets then generate a stub function with
66      the final name */
67   if (n_snippets == 0)
68     {
69       if (data->return_type)
70         g_string_append_printf (data->source_buf,
71                                 "\n"
72                                 "%s\n"
73                                 "%s (%s)\n"
74                                 "{\n"
75                                 "  return %s (%s);\n"
76                                 "}\n",
77                                 data->return_type,
78                                 data->final_name,
79                                 data->argument_declarations ?
80                                 data->argument_declarations : "",
81                                 data->chain_function,
82                                 data->arguments ? data->arguments : "");
83       else
84         g_string_append_printf (data->source_buf,
85                                 "\n"
86                                 "void\n"
87                                 "%s (%s)\n"
88                                 "{\n"
89                                 "  %s (%s);\n"
90                                 "}\n",
91                                 data->final_name,
92                                 data->argument_declarations ?
93                                 data->argument_declarations : "",
94                                 data->chain_function,
95                                 data->arguments ? data->arguments : "");
96
97       return;
98     }
99
100   for (snippet = first_snippet, snippet_num = 0;
101        snippet_num < n_snippets;
102        snippet = COGL_LIST_NEXT (snippet, list_node), snippet_num++)
103     if (snippet->snippet->hook == data->hook)
104       {
105         const char *source;
106
107         if ((source = cogl_snippet_get_declarations (snippet->snippet)))
108           g_string_append (data->source_buf, source);
109
110         g_string_append_printf (data->source_buf,
111                                 "\n"
112                                 "%s\n",
113                                 data->return_type ?
114                                 data->return_type :
115                                 "void");
116
117         if (snippet_num + 1 < n_snippets)
118           g_string_append_printf (data->source_buf,
119                                   "%s_%i",
120                                   data->function_prefix,
121                                   snippet_num);
122         else
123           g_string_append (data->source_buf, data->final_name);
124
125         g_string_append (data->source_buf, " (");
126
127         if (data->argument_declarations)
128           g_string_append (data->source_buf, data->argument_declarations);
129
130         g_string_append (data->source_buf,
131                          ")\n"
132                          "{\n");
133
134         if (data->return_type && !data->return_variable_is_argument)
135           g_string_append_printf (data->source_buf,
136                                   "  %s %s;\n"
137                                   "\n",
138                                   data->return_type,
139                                   data->return_variable);
140
141         if ((source = cogl_snippet_get_pre (snippet->snippet)))
142           g_string_append (data->source_buf, source);
143
144         /* Chain on to the next function, or bypass it if there is
145            a replace string */
146         if ((source = cogl_snippet_get_replace (snippet->snippet)))
147           g_string_append (data->source_buf, source);
148         else
149           {
150             g_string_append (data->source_buf, "  ");
151
152             if (data->return_type)
153               g_string_append_printf (data->source_buf,
154                                       "%s = ",
155                                       data->return_variable);
156
157             if (snippet_num > 0)
158               g_string_append_printf (data->source_buf,
159                                       "%s_%i",
160                                       data->function_prefix,
161                                       snippet_num - 1);
162             else
163               g_string_append (data->source_buf, data->chain_function);
164
165             g_string_append (data->source_buf, " (");
166
167             if (data->arguments)
168               g_string_append (data->source_buf, data->arguments);
169
170             g_string_append (data->source_buf, ");\n");
171           }
172
173         if ((source = cogl_snippet_get_post (snippet->snippet)))
174           g_string_append (data->source_buf, source);
175
176         if (data->return_type)
177           g_string_append_printf (data->source_buf,
178                                   "  return %s;\n",
179                                   data->return_variable);
180
181         g_string_append (data->source_buf, "}\n");
182       }
183 }
184
185 static void
186 _cogl_pipeline_snippet_free (CoglPipelineSnippet *pipeline_snippet)
187 {
188   cogl_object_unref (pipeline_snippet->snippet);
189   g_slice_free (CoglPipelineSnippet, pipeline_snippet);
190 }
191
192 void
193 _cogl_pipeline_snippet_list_free (CoglPipelineSnippetList *list)
194 {
195   CoglPipelineSnippet *pipeline_snippet, *tmp;
196
197   COGL_LIST_FOREACH_SAFE (pipeline_snippet, list, list_node, tmp)
198     _cogl_pipeline_snippet_free (pipeline_snippet);
199 }
200
201 void
202 _cogl_pipeline_snippet_list_add (CoglPipelineSnippetList *list,
203                                  CoglSnippet *snippet)
204 {
205   CoglPipelineSnippet *pipeline_snippet = g_slice_new (CoglPipelineSnippet);
206
207   pipeline_snippet->snippet = cogl_object_ref (snippet);
208
209   _cogl_snippet_make_immutable (pipeline_snippet->snippet);
210
211   if (COGL_LIST_EMPTY (list))
212     COGL_LIST_INSERT_HEAD (list, pipeline_snippet, list_node);
213   else
214     {
215       CoglPipelineSnippet *tail;
216
217       for (tail = COGL_LIST_FIRST (list);
218            COGL_LIST_NEXT (tail, list_node);
219            tail = COGL_LIST_NEXT (tail, list_node));
220
221       COGL_LIST_INSERT_AFTER (tail, pipeline_snippet, list_node);
222     }
223 }
224
225 void
226 _cogl_pipeline_snippet_list_copy (CoglPipelineSnippetList *dst,
227                                   const CoglPipelineSnippetList *src)
228 {
229   CoglPipelineSnippet *tail = NULL;
230   const CoglPipelineSnippet *l;
231
232   COGL_LIST_INIT (dst);
233
234   COGL_LIST_FOREACH (l, src, list_node)
235     {
236       CoglPipelineSnippet *copy = g_slice_dup (CoglPipelineSnippet, l);
237
238       cogl_object_ref (copy->snippet);
239
240       if (tail)
241         COGL_LIST_INSERT_AFTER (tail, copy, list_node);
242       else
243         COGL_LIST_INSERT_HEAD (dst, copy, list_node);
244
245       tail = copy;
246     }
247 }
248
249 void
250 _cogl_pipeline_snippet_list_hash (CoglPipelineSnippetList *list,
251                                   unsigned int *hash)
252 {
253   CoglPipelineSnippet *l;
254
255   COGL_LIST_FOREACH (l, list, list_node)
256     {
257       *hash = _cogl_util_one_at_a_time_hash (*hash,
258                                              &l->snippet,
259                                              sizeof (CoglSnippet *));
260     }
261 }
262
263 gboolean
264 _cogl_pipeline_snippet_list_equal (CoglPipelineSnippetList *list0,
265                                    CoglPipelineSnippetList *list1)
266 {
267   CoglPipelineSnippet *l0, *l1;
268
269   for (l0 = COGL_LIST_FIRST (list0), l1 = COGL_LIST_FIRST (list1);
270        l0 && l1;
271        l0 = COGL_LIST_NEXT (l0, list_node), l1 = COGL_LIST_NEXT (l1, list_node))
272     if (l0->snippet != l1->snippet)
273       return FALSE;
274
275   return l0 == NULL && l1 == NULL;
276 }