libc3: Added c3program
[simavr] / examples / shared / libc3 / src / c3program.c
1 /*
2         c3program.c
3
4         Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
8         simavr is free software: you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 3 of the License, or
11         (at your option) any later version.
12
13         simavr 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
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25 #include <stdio.h>
26 #include <errno.h>
27 #include <fcntl.h>
28
29 #include "c3program.h"
30
31 c3program_p
32 c3program_new(
33                 const char * name)
34 {
35         c3program_p p = malloc(sizeof(*p));
36         memset(p, 0, sizeof(*p));
37         p->name = str_new(name);
38         return p;
39 }
40
41 void
42 c3program_dispose(
43                 const char * name)
44 {
45         // TODO: implement c3program_dispose
46 }
47
48 void
49 c3program_purge(
50                 c3program_p p)
51 {
52         // TODO: implement c3program_purge
53 }
54
55 int
56 c3program_load_shader(
57                 c3program_p p,
58                 uint32_t        type,
59                 const char * header,
60                 const char * filename,
61                 uint16_t flags)
62 {
63         struct stat st;
64         str_p pgm = NULL;
65
66         if (stat(filename, &st))
67                 goto error;
68         int fd = open(filename, O_RDONLY);
69         if (fd == -1)
70                 goto error;
71
72         int hlen = header ? strlen(header) : 0;
73         pgm = str_alloc(st.st_size + hlen);
74         if (header)
75                 strcpy(pgm->str, header);
76
77         if (read(fd, pgm->str + hlen, st.st_size) != st.st_size)
78                 goto error;
79         close(fd);
80         pgm->str[pgm->len] = 0; // zero terminate it
81
82         c3shader_t s = {
83                 .type = type,
84                 .name = str_new(filename),
85                 .shader = pgm,
86         };
87         c3shader_array_add(&p->shaders, s);
88
89         if (flags & C3_PROGRAM_LOAD_UNIFORM) {
90                 char * cur = pgm->str;
91                 char * l;
92
93                 while ((l = strsep(&cur, "\r\n")) != NULL) {
94                         while (*l && *l <= ' ')
95                                 l++;
96                         str_p line = str_new(l);
97                         if (cur) // fix the endline after strsep
98                                 *(cur-1) = '\n';
99                         if (strncmp(line->str, "uniform", 7))
100                                 continue;
101                         // printf("UNI: %s\n", line->str);
102
103                         char * sep = line->str;
104                         char * uniform = strsep(&sep, " \t");
105                         char * unitype = strsep(&sep, " \t");
106                         char * uniname = strsep(&sep, " \t");
107                         /*
108                          * found a parameter, extract it's type & name
109                          */
110                         if (uniform && unitype && uniname) {
111                                 str_p name = str_new(uniname);
112                                 for (int pi = 0; pi < p->params.count && uniform; pi++)
113                                         if (!str_cmp(name, p->params.e[pi].name))
114                                                 uniform = NULL; // already there
115                                 if (uniform) {
116                                         c3program_param_t pa = {
117                                                         .type = str_new(unitype),
118                                                         .name = name,
119                                         };
120                                         c3program_param_array_add(&p->params, pa);
121                                         printf("%s %s: new parameter '%s' '%s'\n", __func__,
122                                                         p->name->str, unitype, uniname);
123                                 } else
124                                         str_free(name);
125                         }
126                         str_free(line);
127                 }
128         }
129         return p->shaders.count - 1;
130
131 error:
132         if (fd != -1)
133                 close(fd);
134         if (pgm)
135                 str_free(pgm);
136         fprintf(stderr, "%s: %s: %s\n", __func__, filename, strerror(errno));
137         return -1;
138
139 }