1 /*
2 * GPAC - Multimedia Framework C SDK
3 *
4 * Authors: Cyril Concolato
5 * Copyright (c) Telecom ParisTech 2004-2012
6 * All rights reserved
7 *
8 * This file is part of GPAC / SVG Scene Graph Generator sub-project
9 *
10 * GPAC is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * GPAC is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; see the file COPYING. If not, write to
22 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25
26 #include <gpac/tools.h>
27 #include <gpac/list.h>
28
start_ctx(char * ctx_name,FILE ** ifce_c,FILE ** fun_c)29 static void start_ctx(char *ctx_name, FILE **ifce_c, FILE **fun_c)
30 {
31 char szFile[GF_MAX_PATH];
32 sprintf(szFile, "../../../src/jsmods/%s.c", ctx_name);
33 FILE *res = gf_fopen(szFile, "wt");
34 *ifce_c = res;
35 *fun_c = gf_file_temp(NULL);
36
37 fprintf(res, "/* !! AUTOGENERATED FILE - DO NOT MODIFY !! \n");
38 fprintf(res, "\n%s implementation for QJS\n*/\n\n", ctx_name);
39 }
40
41
end_ctx(FILE * ifce_c,FILE * func_c,char * ctx_name)42 static void end_ctx(FILE *ifce_c, FILE *func_c, char *ctx_name)
43 {
44
45 fprintf(ifce_c, "static const JSCFunctionListEntry %s_funcs[] =\n\{\n", ctx_name);
46 gf_fseek(func_c, 0, SEEK_SET);
47 while (!feof(func_c)) {
48 char szLine[4001];
49 szLine[0] = 0;
50 gf_fgets(szLine, 4000, func_c);
51 gf_fputs(szLine, ifce_c);
52 }
53 gf_fclose(func_c);
54 fprintf(ifce_c, "};\n");
55 gf_fclose(ifce_c);
56 gf_free(ctx_name);
57
58 }
59
put_const(FILE * fun_defs,char * c_name,char * c_val)60 static void put_const(FILE *fun_defs, char *c_name, char *c_val)
61 {
62 fprintf(fun_defs, "\tJS_PROP_INT32_DEF(\"%s\", %s, JS_PROP_CONFIGURABLE),\n", c_name, c_val);
63 }
put_fun(FILE * fun_defs,char * f_name)64 static void put_fun(FILE *fun_defs, char *f_name)
65 {
66 fprintf(fun_defs, "\tJS_CFUNC_DEF(\"%s\", 0, wgl_%s),\n", f_name, f_name);
67 }
put_prop(FILE * fun_defs,char * ctx_name,char * pname,Bool is_readonly)68 static void put_prop(FILE *fun_defs, char *ctx_name, char *pname, Bool is_readonly)
69 {
70 if (is_readonly) {
71 fprintf(fun_defs, "\tJS_CGETSET_MAGIC_DEF(\"%s\", %s_getProperty, NULL, %s_PROP_%s),\n", pname, ctx_name, ctx_name, pname);
72 } else {
73 fprintf(fun_defs, "\tJS_CGETSET_MAGIC_DEF(\"%s\", %s_getProperty, %s_setProperty, %s_PROP_%s),\n", pname, ctx_name, ctx_name, ctx_name, pname);
74 }
75 }
76
get_arg_type(char * arg_type,Bool * is_array)77 static const char *get_arg_type(char *arg_type, Bool *is_array)
78 {
79 *is_array = GF_FALSE;
80 if (!strcmp(arg_type, "GLenum")) return "u32";
81 if (!strcmp(arg_type, "DOMString")) return "const char *";
82 if (!strcmp(arg_type, "DOMString?")) return "const char *";
83 if (!strcmp(arg_type, "GLuint")) return "u32";
84 if (!strcmp(arg_type, "GLint")) return "s32";
85 if (!strcmp(arg_type, "GLuint")) return "u32";
86 if (!strcmp(arg_type, "GLclampf")) return "Float";
87 if (!strcmp(arg_type, "GLfloat")) return "Float";
88 if (!strcmp(arg_type, "GLboolean")) return "Bool";
89 if (!strcmp(arg_type, "boolean")) return "Bool";
90 if (!strcmp(arg_type, "GLsizei")) return "u32";
91 if (!strcmp(arg_type, "GLbitfield")) return "u32";
92 if (!strcmp(arg_type, "GLshort")) return "s16";
93 if (!strcmp(arg_type, "GLushort")) return "u16";
94 if (!strcmp(arg_type, "GLsizeiptr")) return "u64";
95 if (!strcmp(arg_type, "GLintptr")) return "u64";
96 if (!strcmp(arg_type, "GLbyte")) return "s8";
97 if (!strcmp(arg_type, "GLubyte")) return "u8";
98 if (!strcmp(arg_type, "WebGLProgram?")) return "WebGLProgram";
99 if (!strcmp(arg_type, "WebGLShader?")) return "WebGLShader";
100 if (!strcmp(arg_type, "WebGLBuffer?")) return "WebGLBuffer";
101 if (!strcmp(arg_type, "WebGLFramebuffer?")) return "WebGLFramebuffer";
102 if (!strcmp(arg_type, "WebGLRenderbuffer?")) return "WebGLRenderbuffer";
103 if (!strcmp(arg_type, "WebGLTexture?")) return "WebGLTexture";
104 if (!strcmp(arg_type, "WebGLUniformLocation?")) return "WebGLUniformLocation";
105 if (!strcmp(arg_type, "TexImageSource?")) return "TexImageSource";
106 if (!strcmp(arg_type, "WebGLContextAttributes?")) return "WebGLContextAttributes";
107 if (!strcmp(arg_type, "boolean?")) return "Bool";
108 if (!strcmp(arg_type, "WebGLActiveInfo?")) return "JSValue";
109
110 if (!strcmp(arg_type, "Float32Array")) {
111 *is_array = GF_TRUE;
112 return "Float *";
113 }
114 if (!strcmp(arg_type, "Int32Array")) {
115 *is_array = GF_TRUE;
116 return "s32 *";
117 }
118 if (!strcmp(arg_type, "sequence<DOMString>?")) {
119 return "JSValue";
120 }
121 if (!strcmp(arg_type, "sequence<WebGLShader>?")) {
122 return "JSValue";
123 }
124 if (!strcmp(arg_type, "ArrayBufferView")
125 || !strcmp(arg_type, "ArrayBufferView?")
126 || !strcmp(arg_type, "BufferDataSource?")
127 ) {
128 *is_array = GF_TRUE;
129 return "u8 *";
130 }
131
132 if (!strcmp(arg_type, "object?")
133 || !strcmp(arg_type, "WebGLShaderPrecisionFormat?")
134 || !strcmp(arg_type, "any")
135 ) {
136 return NULL;
137 }
138
139 fprintf(stderr, "arg type %s not supported\n", arg_type);
140 return "JSValue";
141 }
142
put_arg_get(FILE * ifce_c,char * fname,int idx,char * arg_type,char * arg_name)143 static void put_arg_get(FILE *ifce_c, char *fname, int idx, char *arg_type, char *arg_name)
144 {
145 Bool is_array;
146 const char *native_type = get_arg_type(arg_type, &is_array);
147 if (!native_type) return;
148
149 if (!strcmp(native_type, "Bool")) {
150 fprintf(ifce_c, "\tWGL_GET_BOOL(%s, argv[%d]);\n", arg_name, idx);
151 }
152 else if (!strcmp(native_type, "s32")) {
153 fprintf(ifce_c, "\tWGL_GET_S32(%s, argv[%d]);\n", arg_name, idx);
154 }
155 else if (!strcmp(native_type, "u32")) {
156 fprintf(ifce_c, "\tWGL_GET_U32(%s, argv[%d]);\n", arg_name, idx);
157 }
158 else if (!strcmp(native_type, "u64")) {
159 fprintf(ifce_c, "\tWGL_GET_U64(%s, argv[%d]);\n", arg_name, idx);
160 }
161 else if (!strcmp(native_type, "s64")) {
162 fprintf(ifce_c, "\tWGL_GET_S64(%s, argv[%d]);\n", arg_name, idx);
163 }
164 else if (!strcmp(native_type, "s16")) {
165 fprintf(ifce_c, "\tWGL_GET_S16(%s, argv[%d]);\n", arg_name, idx);
166 }
167 else if (!strcmp(native_type, "u16")) {
168 fprintf(ifce_c, "\tWGL_GET_U16(%s, argv[%d]);\n", arg_name, idx);
169 }
170 else if (!strcmp(arg_type, "GLclampf")) {
171 fprintf(ifce_c, "\tWGL_GET_FLOAT_CLAMP(%s, argv[%d]);\n", arg_name, idx);
172 }
173 else if (!strcmp(native_type, "Float")) {
174 fprintf(ifce_c, "\tWGL_GET_FLOAT(%s, argv[%d]);\n", arg_name, idx);
175 }
176 else if (!strcmp(native_type, "const char *")) {
177 fprintf(ifce_c, "\tWGL_GET_STRING(%s, argv[%d]);\n", arg_name, idx);
178 }
179 else if (!strcmp(native_type, "WebGLProgram")
180 || !strcmp(native_type, "WebGLShader")
181 || !strcmp(native_type, "WebGLBuffer")
182 || !strcmp(native_type, "WebGLFramebuffer")
183 || !strcmp(native_type, "WebGLRenderbuffer")
184 || !strcmp(native_type, "WebGLTexture")
185 || !strcmp(native_type, "WebGLUniformLocation")
186 ) {
187 fprintf(ifce_c, "\tWGL_GET_GLID(%s, argv[%d], %s_class_id);\n", arg_name, idx, native_type);
188 }
189
190 else if (!strcmp(arg_type, "BufferDataSource?")) {
191 fprintf(ifce_c, "\tif(!JS_IsObject(argv[%d])) {\n", idx);
192 fprintf(ifce_c, "\t\tWGL_GET_U32(%s_size, argv[%d]);\n", arg_name, idx);
193 fprintf(ifce_c, "\t} else {\n");
194 fprintf(ifce_c, "\t\t%s = wgl_GetArrayBuffer(ctx, &%s_size, argv[%d]);\n", arg_name, arg_name, idx);
195 fprintf(ifce_c, "\t}\n");
196 }
197 else if (is_array && !strcmp(native_type, "u8 *")) {
198 fprintf(ifce_c, "\tif(!JS_IsArray(ctx, argv[%d])) return js_throw_err(ctx, WGL_INVALID_VALUE);\n", idx);
199 fprintf(ifce_c, "\t%s = wgl_GetArrayBuffer(ctx, &%s_size, argv[%d]);\n", arg_name, arg_name, idx);
200 }
201 else if (is_array && (!strcmp(native_type, "Float *") || !strcmp(native_type, "s32 *")) ) {
202 u32 vlen = 1;
203 if (strstr(fname, "2fv")) vlen = 2;
204 else if (strstr(fname, "3fv")) vlen = 3;
205 else if (strstr(fname, "4fv")) vlen = 4;
206
207 if (!strcmp(native_type, "s32 *"))
208 fprintf(ifce_c, "\tif (!WGL_LOAD_INT32_VEC(ctx, argv[%d], (s32 **) &%s, &%s_size, %d)) return js_throw_err(ctx, WGL_INVALID_VALUE);;\n", idx, arg_name, arg_name, vlen);
209 else {
210 Bool is_matrix = GF_FALSE;
211 if (strstr(fname, "Matrix")) is_matrix = GF_TRUE;
212 if (strstr(fname, "vertexAttrib")) {
213 fprintf(ifce_c, "\tif (!WGL_LOAD_FLOAT_VEC(ctx, argv[%d], (Float **) &%s, NULL, %d, %d)) return js_throw_err(ctx, WGL_INVALID_VALUE);\n", idx, arg_name, vlen, is_matrix);
214 } else {
215 fprintf(ifce_c, "\tif (!WGL_LOAD_FLOAT_VEC(ctx, argv[%d], (Float **) &%s, &%s_size, %d, %d)) return js_throw_err(ctx, WGL_INVALID_VALUE);\n", idx, arg_name, arg_name, vlen, is_matrix);
216 }
217 }
218 }
219 else {
220 fprintf(stderr, "arg type %s not supported\n", arg_type);
221 }
222
223 }
224
put_arg_decl(FILE * ifce_c,char * fname,char * arg_type,char * arg_name)225 static void put_arg_decl(FILE *ifce_c, char *fname, char *arg_type, char *arg_name)
226 {
227 Bool is_array = GF_FALSE;
228 const char *native_type = get_arg_type(arg_type, &is_array);
229 if (!native_type)
230 return;
231
232 if (is_array) {
233 if (strstr(fname, "vertexAttrib1fv")) {
234 fprintf(ifce_c, "\tFloat %s[1];\n", arg_name);
235 } else if (strstr(fname, "vertexAttrib2fv")) {
236 fprintf(ifce_c, "\tFloat %s[2];\n", arg_name);
237 } else if (strstr(fname, "vertexAttrib3fv")) {
238 fprintf(ifce_c, "\tFloat %s[3];\n", arg_name);
239 } else if (strstr(fname, "vertexAttrib4fv")) {
240 fprintf(ifce_c, "\tFloat %s[4];\n", arg_name);
241 } else {
242 fprintf(ifce_c, "\t%s %s = NULL;\n", native_type, arg_name);
243 fprintf(ifce_c, "\tu32 %s_size = 0;\n", arg_name);
244 }
245 } else {
246 if (strstr(arg_name, " *"))
247 fprintf(ifce_c, "\t%s %s = NULL;\n", native_type, arg_name);
248 else if (!strcmp(native_type, "JSValue"))
249 fprintf(ifce_c, "\t%s %s = JS_UNDEFINED;\n", native_type, arg_name);
250 else if (!strncmp(native_type, "WebGL", 5))
251 fprintf(ifce_c, "\tGLuint %s = 0;\n", arg_name);
252 else
253 fprintf(ifce_c, "\t%s %s = 0;\n", native_type, arg_name);
254 }
255 }
256 /*all functions that cannot be mapped directly due to to heavy syntax pacthing or our own hacking*/
257 static const char *not_autogen_funcs = "getContextAttributes,isContextLost,getSupportedExtensions,getExtension,getBufferParameter,getParameter,getFramebufferAttachmentParameter,getProgramParameter,getRenderbufferParameter,getShaderParameter,getShaderPrecisionFormat,getProgramInfoLog,getShaderParameter,getShaderInfoLog,getShaderSource,getTexParameter,getUniform,getVertexAttrib,getVertexAttribOffset,readPixels,shaderSource,texImage2D,texSubImage2D,useProgram,activeTexture,bindTexture,getUniformLocation,createTexture,bindFramebuffer";
258
wrap_func(FILE * ifce_c,char * fname,char * fun_def)259 static void wrap_func(FILE *ifce_c, char *fname, char *fun_def)
260 {
261 char *sep, *nsep;
262 u32 len, i, nb_args;
263 u32 first_char;
264 u32 ret_type=0;
265 Bool is_create=GF_FALSE;
266 Bool is_delete_fun=GF_FALSE;
267 char *ret_val=NULL, *exc_value=NULL, *arg_type[50], *arg_name[50];
268
269 if (strstr(not_autogen_funcs, fname)) {
270 fprintf(ifce_c, "\nstatic JSValue wgl_%s(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);\n", fname);
271 return;
272 }
273
274 fprintf(ifce_c, "\nstatic JSValue wgl_%s(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)\n{\n", fname);
275
276 nb_args = 0;
277 memset(arg_type, 0, sizeof(char *)*50);
278 memset(arg_name, 0, sizeof(char *)*50);
279
280 sep = fun_def;
281 while (sep[0]==' ') sep++;
282 /*parse exception*/
283 if (sep[0]=='[') {
284 nsep = strchr(sep, ']');
285 assert(nsep);
286 nsep[0]=0;
287 exc_value = gf_strdup(sep);
288 nsep[0]=']';
289 sep = nsep+1;
290 while (sep[0]==' ') sep++;
291 }
292 /*parse return value*/
293 nsep = strchr(sep, ' ');
294 assert(nsep);
295 nsep[0] = 0;
296 ret_val = strdup(sep);
297 sep = nsep+1;
298 len = strlen(fname);
299 assert(!strncmp(sep, fname, len) );
300 sep += len+1;
301 while (sep) {
302 char *next_arg;
303 nsep = strchr(sep, ',');
304 if (!nsep) {
305 nsep = strchr(sep, ')');
306 if (!nsep) break;
307 }
308 nsep[0]=0;
309 next_arg = nsep+1;
310
311 if (nb_args>=50) {
312 assert(0);
313 }
314 nsep = strchr(sep, ' ');
315 if (!nsep)
316 break;
317 assert(nsep);
318 nsep[0] = 0;
319 arg_type[nb_args] = gf_strdup(sep);
320 arg_name[nb_args] = gf_strdup(nsep+1);
321 nb_args++;
322 sep = next_arg;
323 while (sep[0]==' ') sep++;
324 }
325
326 fprintf(ifce_c, "\tJSValue ret_val_js = JS_UNDEFINED;\n");
327
328 for (i=0; i<nb_args; i++) {
329 put_arg_decl(ifce_c, fname, arg_type[i], arg_name[i]);
330 }
331 fprintf(ifce_c, "\tWGL_CHECK_CONTEXT\n");
332
333 if (nb_args) {
334 fprintf(ifce_c, "\tif (argc<%d) return js_throw_err(ctx, WGL_INVALID_VALUE);\n", nb_args);
335 for (i=0; i<nb_args; i++) {
336 put_arg_get(ifce_c, fname, i, arg_type[i], arg_name[i]);
337 }
338 }
339
340 /*hack a few funcs with different signatures*/
341 if (!strcmp(fname, "getActiveAttrib")) {
342 fprintf(ifce_c, "\tret_val_js = webgl_getActiveAttrib(ctx, program, index);\n\treturn ret_val_js;\n");
343 goto fun_done;
344 }
345 if (!strcmp(fname, "getActiveUniform")) {
346 fprintf(ifce_c, "\tret_val_js = webgl_getActiveUniform(ctx, program, index);\n\treturn ret_val_js;\n");
347 goto fun_done;
348 }
349 if (!strcmp(fname, "getAttachedShaders")) {
350 fprintf(ifce_c, "\tret_val_js = webgl_getAttachedShaders(ctx, JS_GetOpaque(this_val, WebGLRenderingContextBase_class_id), program);\n\treturn ret_val_js;\n");
351 goto fun_done;
352 }
353 if (!strcmp(fname, "getBufferParameter")) {
354 fprintf(ifce_c, "\tret_val_js = webgl_getBufferParameter(ctx, target, pname);\n\treturn ret_val_js;\n");
355 goto fun_done;
356 }
357
358 if (ret_val && strcmp(ret_val, "void")) {
359 if (!strcmp(fname, "createBuffer") || !strcmp(fname, "createFramebuffer") || !strcmp(fname, "createTexture") || !strcmp(fname, "createRenderbuffer")) {
360 fprintf(ifce_c, "\tGF_WebGLObject *wglo;\n");
361 is_create = GF_TRUE;
362 ret_type = 2;
363
364 } else if (!strcmp(fname, "createProgram") || !strcmp(fname, "createShader")) {
365 fprintf(ifce_c, "\tGF_WebGLObject *wglo;\n");
366 ret_type = 2;
367 } else {
368 put_arg_decl(ifce_c, fname, ret_val, "ret_val");
369 ret_type = 1;
370 }
371 }
372
373 first_char = fname[0];
374 if ((first_char < 'A') || (first_char > 'Z')) {
375 first_char += 'A' - 'a';
376 }
377
378 if (is_create) {
379 fprintf(ifce_c, "\tGF_SAFEALLOC(wglo, GF_WebGLObject);\n");
380 fprintf(ifce_c, "\tif (!wglo) return js_throw_err(ctx, WGL_OUT_OF_MEMORY);\n");
381 fprintf(ifce_c, "\twglo->par_ctx = JS_GetOpaque(this_val, WebGLRenderingContextBase_class_id);\n");
382 fprintf(ifce_c, "\tglGen%ss(1, &wglo->gl_id", fname+6);
383 } else {
384 if (!strcmp(fname, "deleteShader") || !strcmp(fname, "deleteProgram")) {
385 is_delete_fun=GF_TRUE;
386 }
387 if (!strcmp(fname, "deleteBuffer") || !strcmp(fname, "deleteTexture") || !strcmp(fname, "deleteFramebuffer") || !strcmp(fname, "deleteRenderbuffer")) {
388 fprintf(ifce_c, "\tgl%c%ss(1, &", first_char, fname+1);
389 is_delete_fun=GF_TRUE;
390 }
391 else if (!strcmp(fname, "createProgram") || !strcmp(fname, "createShader")) {
392 fprintf(ifce_c, "\tGF_SAFEALLOC(wglo, GF_WebGLObject);\n");
393 fprintf(ifce_c, "\tif (!wglo) return js_throw_err(ctx, WGL_OUT_OF_MEMORY);\n");
394 fprintf(ifce_c, "\twglo->par_ctx = JS_GetOpaque(this_val, WebGLRenderingContextBase_class_id);\n");
395 fprintf(ifce_c, "\twglo->gl_id = gl%c%s(", first_char, fname+1);
396 } else if (!strcmp(fname, "clearDepth") || !strcmp(fname, "depthRange")) {
397 fprintf(ifce_c, "#if defined(GPAC_USE_GLES2)\n");
398 fprintf(ifce_c, "\tgl%c%sf(\n", first_char, fname+1);
399 fprintf(ifce_c, "#else\n");
400 fprintf(ifce_c, "\tgl%c%s(\n", first_char, fname+1);
401 fprintf(ifce_c, "#endif\n\t\t");
402 } else {
403 fprintf(ifce_c, "\t");
404 if (ret_type==1) {
405 fprintf(ifce_c, "ret_val = ");
406 }
407 if (!strncmp(fname, "uniform", 7)) {
408
409 fprintf(ifce_c, "/*hack for GPAC textures, we create uniforms with loc -2 for such textures*/\n\tif ((s32) location>=0)\n\t\t");
410 }
411 fprintf(ifce_c, "gl%c%s(", first_char, fname+1);
412 }
413 }
414
415 Bool prev_is_transpose = GF_FALSE;
416 for (i=0; i<nb_args; i++) {
417 Bool is_array;
418 get_arg_type(arg_type[i], &is_array);
419
420 if (!strcmp(arg_name[i], "transpose")) {
421 fprintf(ifce_c, "%s_size, ", arg_name[i+1]);
422 prev_is_transpose = GF_TRUE;
423 }
424 else if (prev_is_transpose) {
425 is_array = GF_FALSE;
426 }
427
428 if (is_array && (
429 !strcmp(fname, "bufferData") || !strcmp(fname, "bufferSubData")
430 || !strcmp(fname, "compressedTexImage2D") || !strcmp(fname, "compressedTexSubImage2D")
431 || !strncmp(fname, "uniform", 7)
432
433 )) {
434 is_array = GF_FALSE;
435 fprintf(ifce_c, "%s_size, ", arg_name[i]);
436 }
437 if (!strcmp(arg_type[i], "GLintptr") && (!strcmp(fname, "vertexAttribPointer") || !strcmp(fname, "drawElements")) ) {
438 fprintf(ifce_c, "(void *)");
439 }
440
441 fprintf(ifce_c, "%s", arg_name[i]);
442
443 if (is_array) {
444 if (strstr(fname, "vertexAttrib1fv")) {}
445 else if (strstr(fname, "vertexAttrib2fv")) {}
446 else if (strstr(fname, "vertexAttrib3fv")) {}
447 else if (strstr(fname, "vertexAttrib4fv")) {}
448 else {
449 fprintf(ifce_c, ", %s_size", arg_name[i]);
450 }
451 }
452 if (i+1<nb_args)
453 fprintf(ifce_c, ", ");
454 }
455
456 fprintf(ifce_c, ");\n");
457 if (is_delete_fun) {
458 Bool is_array;
459 const char *nat_type = get_arg_type(arg_type[0], &is_array);
460 fprintf(ifce_c, "\t{\n\tGF_WebGLObject *glo = JS_GetOpaque(argv[0], %s_class_id);\n\tif (glo) {\n\tglo->gl_id=0;\n", nat_type);
461 fprintf(ifce_c, "\tJS_FreeValue(ctx, glo->obj);\n\tglo->obj = JS_UNDEFINED;\n\tgf_list_del_item(glo->par_ctx->all_objects, glo);\n");
462 fprintf(ifce_c, "\t}\n\t}\n");
463 }
464
465 if (ret_type==1) {
466
467 if (!strcmp(ret_val, "GLenum") || !strcmp(ret_val, "GLint")) {
468 fprintf(ifce_c, "\tret_val_js = JS_NewInt32(ctx, ret_val);\n");
469 } else if (!strcmp(ret_val, "GLboolean") ) {
470 fprintf(ifce_c, "\tret_val_js = JS_NewBool(ctx, ret_val);\n");
471 } else if (!strcmp(ret_val, "WebGLProgram") ) {
472 fprintf(ifce_c, "\tret_val_js = JS_NewObjectClass(ctx, WebGLProgram_class_id);\n");
473 fprintf(ifce_c, "\tJS_SetOpaque(ret_val_js, wglo);\n");
474 } else {
475 fprintf(stderr, "retval %s not supported in %s\n", ret_val, fname);
476 }
477 } else if (ret_type==2) {
478 Bool is_array;
479 const char *native_type = get_arg_type(ret_val, &is_array);
480 fprintf(ifce_c, "\tret_val_js = JS_NewObjectClass(ctx, %s_class_id);\n", native_type);
481 fprintf(ifce_c, "\tJS_SetOpaque(ret_val_js, wglo);\n");
482 fprintf(ifce_c, "\twglo->obj = JS_DupValue(ctx, ret_val_js);\n");
483 fprintf(ifce_c, "\twglo->class_id = %s_class_id;\n", native_type);
484 fprintf(ifce_c, "\tgf_list_add(wglo->par_ctx->all_objects, wglo);\n");
485 }
486
487 for (i=0; i<nb_args; i++) {
488 Bool is_array;
489 const char *native_type = get_arg_type(arg_type[i], &is_array);
490 if (!native_type) continue;
491 if (!strcmp(native_type, "const char *")) {
492 fprintf(ifce_c, "\tJS_FreeCString(ctx, %s);\n", arg_name[i]);
493 }
494
495 if (is_array && strcmp(native_type, "u8 *")) {
496 if (strstr(fname, "vertexAttrib1fv")) {
497 } else if (strstr(fname, "vertexAttrib2fv")) {
498 } else if (strstr(fname, "vertexAttrib3fv")) {
499 } else if (strstr(fname, "vertexAttrib4fv")) {
500 } else {
501 fprintf(ifce_c, "\tif (%s) gf_free(%s);\n", arg_name[i], arg_name[i]);
502 }
503 }
504 }
505
506 fprintf(ifce_c, "\treturn ret_val_js;\n");
507
508 fun_done:
509 while (nb_args>1) {
510 gf_free(arg_type[nb_args-1]);
511 gf_free(arg_name[nb_args-1]);
512 nb_args--;
513 }
514 gf_free(ret_val);
515 fprintf(ifce_c, "}\n");
516 }
517
518
load_idl(const char * file)519 static void load_idl(const char *file)
520 {
521 Bool in_ctxbase = GF_FALSE;
522 char szLine[4001], *sep;
523 char *curCtx = NULL;
524 u32 len;
525 FILE * idl = gf_fopen(file, "rt");
526 FILE *ifce_c=NULL;
527 FILE *fun_defs=NULL;
528
529 while (!feof(idl)) {
530 gf_fgets(szLine, 4000, idl);
531 if (strstr(szLine, "implements"))
532 continue;
533 len = strlen(szLine);
534 while (len && strchr(" \n", szLine[len])) {
535 szLine[len] = 0;
536 len--;
537 }
538 if (!len) continue;
539
540 if (!in_ctxbase) {
541 if (!strstr(szLine, "RenderingContextBase"))
542 continue;
543 in_ctxbase = GF_TRUE;
544 sep = strchr(szLine, ' ');
545 assert(sep);
546 curCtx = gf_strdup(sep+1);
547 start_ctx(curCtx, &ifce_c, &fun_defs);
548 continue;
549 } else {
550 if (strstr(szLine, "};")){
551 in_ctxbase = GF_FALSE;
552 end_ctx(ifce_c, fun_defs, curCtx);
553 ifce_c = NULL;
554 continue;
555 }
556 }
557
558 if (strstr(szLine, "/*")) continue;
559 sep = strstr(szLine, "const ");
560 if (sep) {
561 char *cname, *nsep;
562 sep = strchr(sep+7, ' ');
563 assert(sep);
564 sep++;
565 nsep = strchr(sep, ' ');
566 assert(nsep);
567 nsep[0] = 0;
568 cname = gf_strdup(sep);
569 sep = strchr(nsep+1, '=');
570 assert(sep);
571 sep++;
572 while (sep[0]==' ') sep++;
573 nsep = strchr(sep, ';');
574 assert(nsep);
575 nsep[0]=0;
576 put_const(fun_defs, cname, sep);
577 gf_free(cname);
578 continue;
579 }
580 sep = strstr(szLine, "typedef");
581 if (sep) continue;
582
583 sep = strstr(szLine, "attribute");
584 if (sep) {
585 char *nsep;
586 Bool is_readonly = GF_FALSE;
587 sep = szLine;
588 while (sep[0]==' ') sep++;
589 if (!strncmp(sep, "readonly", 8)) {
590 is_readonly = GF_TRUE;
591 sep+=9;
592 }
593 sep += 10;
594 sep = strchr(sep, ' ');
595 assert(sep);
596 sep+=1;
597 nsep = strchr(sep, ';');
598 assert(nsep);
599 nsep[0] = 0;
600 put_prop(fun_defs, curCtx, sep, is_readonly);
601 continue;
602 }
603 /*double type declaration for glXXXifv*/
604 if (strstr(szLine, ", sequence<"))
605 continue;
606 /*double type declaration for bufferData*/
607 if (strstr(szLine, ", GLsizeiptr size"))
608 continue;
609 /*double type declaration for texImage2D and texSubImage2D*/
610 if (strstr(szLine, ", TexImageSource"))
611 continue;
612
613 sep = strstr(szLine, "(");
614 /*this is a function*/
615 if (sep) {
616 char *nsep, *fname;
617 sep = strchr(szLine, ']');
618 if (sep) sep+=1;
619 else sep = szLine;
620 while (sep[0] == ' ') sep++;
621 sep = strchr(sep, ' ');
622 assert(sep);
623 sep++;
624 nsep = strchr(sep, '(');
625 assert(nsep);
626 nsep[0] = 0;
627 fname = gf_strdup(sep);
628 put_fun(fun_defs, sep);
629 nsep[0] = '(';
630
631 wrap_func(ifce_c, fname, szLine);
632 gf_free(fname);
633 continue;
634 }
635 fprintf(stderr, "instruction %s not handled\n", szLine);
636 }
637
638
639 gf_fclose(idl);
640 }
641
main(int argc,char ** argv)642 int main(int argc, char **argv)
643 {
644 u32 i=0;
645 for (i=1; i<argc; i++) {
646 load_idl(argv[i]);
647 }
648
649 return 0;
650 }
651
652
653