| /* | |
| * GPAC - Multimedia Framework C SDK | |
| * | |
| * Authors: Cyril Concolato | |
| * Copyright (c) Telecom ParisTech 2004-2012 | |
| * All rights reserved | |
| * | |
| * This file is part of GPAC / SVG Scene Graph Generator sub-project | |
| * | |
| * GPAC is free software; you can redistribute it and/or modify | |
| * it under the terms of the GNU Lesser General Public License as published by | |
| * the Free Software Foundation; either version 2, or (at your option) | |
| * any later version. | |
| * | |
| * GPAC is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; see the file COPYING. If not, write to | |
| * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
| * | |
| */ | |
| #include <gpac/tools.h> | |
| #include <gpac/list.h> | |
| static void start_ctx(char *ctx_name, FILE **ifce_c, FILE **fun_c) | |
| { | |
| char szFile[GF_MAX_PATH]; | |
| sprintf(szFile, "../../../src/jsmods/%s.c", ctx_name); | |
| FILE *res = gf_fopen(szFile, "wt"); | |
| *ifce_c = res; | |
| *fun_c = gf_file_temp(NULL); | |
| fprintf(res, "/* !! AUTOGENERATED FILE - DO NOT MODIFY !! \n"); | |
| fprintf(res, "\n%s implementation for QJS\n*/\n\n", ctx_name); | |
| } | |
| static void end_ctx(FILE *ifce_c, FILE *func_c, char *ctx_name) | |
| { | |
| fprintf(ifce_c, "static const JSCFunctionListEntry %s_funcs[] =\n\{\n", ctx_name); | |
| gf_fseek(func_c, 0, SEEK_SET); | |
| while (!feof(func_c)) { | |
| char szLine[4001]; | |
| szLine[0] = 0; | |
| gf_fgets(szLine, 4000, func_c); | |
| gf_fputs(szLine, ifce_c); | |
| } | |
| gf_fclose(func_c); | |
| fprintf(ifce_c, "};\n"); | |
| gf_fclose(ifce_c); | |
| gf_free(ctx_name); | |
| } | |
| static void put_const(FILE *fun_defs, char *c_name, char *c_val) | |
| { | |
| fprintf(fun_defs, "\tJS_PROP_INT32_DEF(\"%s\", %s, JS_PROP_CONFIGURABLE),\n", c_name, c_val); | |
| } | |
| static void put_fun(FILE *fun_defs, char *f_name) | |
| { | |
| fprintf(fun_defs, "\tJS_CFUNC_DEF(\"%s\", 0, wgl_%s),\n", f_name, f_name); | |
| } | |
| static void put_prop(FILE *fun_defs, char *ctx_name, char *pname, Bool is_readonly) | |
| { | |
| if (is_readonly) { | |
| fprintf(fun_defs, "\tJS_CGETSET_MAGIC_DEF(\"%s\", %s_getProperty, NULL, %s_PROP_%s),\n", pname, ctx_name, ctx_name, pname); | |
| } else { | |
| fprintf(fun_defs, "\tJS_CGETSET_MAGIC_DEF(\"%s\", %s_getProperty, %s_setProperty, %s_PROP_%s),\n", pname, ctx_name, ctx_name, ctx_name, pname); | |
| } | |
| } | |
| static const char *get_arg_type(char *arg_type, Bool *is_array) | |
| { | |
| *is_array = GF_FALSE; | |
| if (!strcmp(arg_type, "GLenum")) return "u32"; | |
| if (!strcmp(arg_type, "DOMString")) return "const char *"; | |
| if (!strcmp(arg_type, "DOMString?")) return "const char *"; | |
| if (!strcmp(arg_type, "GLuint")) return "u32"; | |
| if (!strcmp(arg_type, "GLint")) return "s32"; | |
| if (!strcmp(arg_type, "GLuint")) return "u32"; | |
| if (!strcmp(arg_type, "GLclampf")) return "Float"; | |
| if (!strcmp(arg_type, "GLfloat")) return "Float"; | |
| if (!strcmp(arg_type, "GLboolean")) return "Bool"; | |
| if (!strcmp(arg_type, "boolean")) return "Bool"; | |
| if (!strcmp(arg_type, "GLsizei")) return "u32"; | |
| if (!strcmp(arg_type, "GLbitfield")) return "u32"; | |
| if (!strcmp(arg_type, "GLshort")) return "s16"; | |
| if (!strcmp(arg_type, "GLushort")) return "u16"; | |
| if (!strcmp(arg_type, "GLsizeiptr")) return "u64"; | |
| if (!strcmp(arg_type, "GLintptr")) return "u64"; | |
| if (!strcmp(arg_type, "GLbyte")) return "s8"; | |
| if (!strcmp(arg_type, "GLubyte")) return "u8"; | |
| if (!strcmp(arg_type, "WebGLProgram?")) return "WebGLProgram"; | |
| if (!strcmp(arg_type, "WebGLShader?")) return "WebGLShader"; | |
| if (!strcmp(arg_type, "WebGLBuffer?")) return "WebGLBuffer"; | |
| if (!strcmp(arg_type, "WebGLFramebuffer?")) return "WebGLFramebuffer"; | |
| if (!strcmp(arg_type, "WebGLRenderbuffer?")) return "WebGLRenderbuffer"; | |
| if (!strcmp(arg_type, "WebGLTexture?")) return "WebGLTexture"; | |
| if (!strcmp(arg_type, "WebGLUniformLocation?")) return "WebGLUniformLocation"; | |
| if (!strcmp(arg_type, "TexImageSource?")) return "TexImageSource"; | |
| if (!strcmp(arg_type, "WebGLContextAttributes?")) return "WebGLContextAttributes"; | |
| if (!strcmp(arg_type, "boolean?")) return "Bool"; | |
| if (!strcmp(arg_type, "WebGLActiveInfo?")) return "JSValue"; | |
| if (!strcmp(arg_type, "Float32Array")) { | |
| *is_array = GF_TRUE; | |
| return "Float *"; | |
| } | |
| if (!strcmp(arg_type, "Int32Array")) { | |
| *is_array = GF_TRUE; | |
| return "s32 *"; | |
| } | |
| if (!strcmp(arg_type, "sequence<DOMString>?")) { | |
| return "JSValue"; | |
| } | |
| if (!strcmp(arg_type, "sequence<WebGLShader>?")) { | |
| return "JSValue"; | |
| } | |
| if (!strcmp(arg_type, "ArrayBufferView") | |
| || !strcmp(arg_type, "ArrayBufferView?") | |
| || !strcmp(arg_type, "BufferDataSource?") | |
| ) { | |
| *is_array = GF_TRUE; | |
| return "u8 *"; | |
| } | |
| if (!strcmp(arg_type, "object?") | |
| || !strcmp(arg_type, "WebGLShaderPrecisionFormat?") | |
| || !strcmp(arg_type, "any") | |
| ) { | |
| return NULL; | |
| } | |
| fprintf(stderr, "arg type %s not supported\n", arg_type); | |
| return "JSValue"; | |
| } | |
| static void put_arg_get(FILE *ifce_c, char *fname, int idx, char *arg_type, char *arg_name) | |
| { | |
| Bool is_array; | |
| const char *native_type = get_arg_type(arg_type, &is_array); | |
| if (!native_type) return; | |
| if (!strcmp(native_type, "Bool")) { | |
| fprintf(ifce_c, "\tWGL_GET_BOOL(%s, argv[%d]);\n", arg_name, idx); | |
| } | |
| else if (!strcmp(native_type, "s32")) { | |
| fprintf(ifce_c, "\tWGL_GET_S32(%s, argv[%d]);\n", arg_name, idx); | |
| } | |
| else if (!strcmp(native_type, "u32")) { | |
| fprintf(ifce_c, "\tWGL_GET_U32(%s, argv[%d]);\n", arg_name, idx); | |
| } | |
| else if (!strcmp(native_type, "u64")) { | |
| fprintf(ifce_c, "\tWGL_GET_U64(%s, argv[%d]);\n", arg_name, idx); | |
| } | |
| else if (!strcmp(native_type, "s64")) { | |
| fprintf(ifce_c, "\tWGL_GET_S64(%s, argv[%d]);\n", arg_name, idx); | |
| } | |
| else if (!strcmp(native_type, "s16")) { | |
| fprintf(ifce_c, "\tWGL_GET_S16(%s, argv[%d]);\n", arg_name, idx); | |
| } | |
| else if (!strcmp(native_type, "u16")) { | |
| fprintf(ifce_c, "\tWGL_GET_U16(%s, argv[%d]);\n", arg_name, idx); | |
| } | |
| else if (!strcmp(arg_type, "GLclampf")) { | |
| fprintf(ifce_c, "\tWGL_GET_FLOAT_CLAMP(%s, argv[%d]);\n", arg_name, idx); | |
| } | |
| else if (!strcmp(native_type, "Float")) { | |
| fprintf(ifce_c, "\tWGL_GET_FLOAT(%s, argv[%d]);\n", arg_name, idx); | |
| } | |
| else if (!strcmp(native_type, "const char *")) { | |
| fprintf(ifce_c, "\tWGL_GET_STRING(%s, argv[%d]);\n", arg_name, idx); | |
| } | |
| else if (!strcmp(native_type, "WebGLProgram") | |
| || !strcmp(native_type, "WebGLShader") | |
| || !strcmp(native_type, "WebGLBuffer") | |
| || !strcmp(native_type, "WebGLFramebuffer") | |
| || !strcmp(native_type, "WebGLRenderbuffer") | |
| || !strcmp(native_type, "WebGLTexture") | |
| || !strcmp(native_type, "WebGLUniformLocation") | |
| ) { | |
| fprintf(ifce_c, "\tWGL_GET_GLID(%s, argv[%d], %s_class_id);\n", arg_name, idx, native_type); | |
| } | |
| else if (!strcmp(arg_type, "BufferDataSource?")) { | |
| fprintf(ifce_c, "\tif(!JS_IsObject(argv[%d])) {\n", idx); | |
| fprintf(ifce_c, "\t\tWGL_GET_U32(%s_size, argv[%d]);\n", arg_name, idx); | |
| fprintf(ifce_c, "\t} else {\n"); | |
| fprintf(ifce_c, "\t\t%s = wgl_GetArrayBuffer(ctx, &%s_size, argv[%d]);\n", arg_name, arg_name, idx); | |
| fprintf(ifce_c, "\t}\n"); | |
| } | |
| else if (is_array && !strcmp(native_type, "u8 *")) { | |
| fprintf(ifce_c, "\tif(!JS_IsArray(ctx, argv[%d])) return js_throw_err(ctx, WGL_INVALID_VALUE);\n", idx); | |
| fprintf(ifce_c, "\t%s = wgl_GetArrayBuffer(ctx, &%s_size, argv[%d]);\n", arg_name, arg_name, idx); | |
| } | |
| else if (is_array && (!strcmp(native_type, "Float *") || !strcmp(native_type, "s32 *")) ) { | |
| u32 vlen = 1; | |
| if (strstr(fname, "2fv")) vlen = 2; | |
| else if (strstr(fname, "3fv")) vlen = 3; | |
| else if (strstr(fname, "4fv")) vlen = 4; | |
| if (!strcmp(native_type, "s32 *")) | |
| 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); | |
| else { | |
| Bool is_matrix = GF_FALSE; | |
| if (strstr(fname, "Matrix")) is_matrix = GF_TRUE; | |
| if (strstr(fname, "vertexAttrib")) { | |
| 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); | |
| } else { | |
| 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); | |
| } | |
| } | |
| } | |
| else { | |
| fprintf(stderr, "arg type %s not supported\n", arg_type); | |
| } | |
| } | |
| static void put_arg_decl(FILE *ifce_c, char *fname, char *arg_type, char *arg_name) | |
| { | |
| Bool is_array = GF_FALSE; | |
| const char *native_type = get_arg_type(arg_type, &is_array); | |
| if (!native_type) | |
| return; | |
| if (is_array) { | |
| if (strstr(fname, "vertexAttrib1fv")) { | |
| fprintf(ifce_c, "\tFloat %s[1];\n", arg_name); | |
| } else if (strstr(fname, "vertexAttrib2fv")) { | |
| fprintf(ifce_c, "\tFloat %s[2];\n", arg_name); | |
| } else if (strstr(fname, "vertexAttrib3fv")) { | |
| fprintf(ifce_c, "\tFloat %s[3];\n", arg_name); | |
| } else if (strstr(fname, "vertexAttrib4fv")) { | |
| fprintf(ifce_c, "\tFloat %s[4];\n", arg_name); | |
| } else { | |
| fprintf(ifce_c, "\t%s %s = NULL;\n", native_type, arg_name); | |
| fprintf(ifce_c, "\tu32 %s_size = 0;\n", arg_name); | |
| } | |
| } else { | |
| if (strstr(arg_name, " *")) | |
| fprintf(ifce_c, "\t%s %s = NULL;\n", native_type, arg_name); | |
| else if (!strcmp(native_type, "JSValue")) | |
| fprintf(ifce_c, "\t%s %s = JS_UNDEFINED;\n", native_type, arg_name); | |
| else if (!strncmp(native_type, "WebGL", 5)) | |
| fprintf(ifce_c, "\tGLuint %s = 0;\n", arg_name); | |
| else | |
| fprintf(ifce_c, "\t%s %s = 0;\n", native_type, arg_name); | |
| } | |
| } | |
| /*all functions that cannot be mapped directly due to to heavy syntax pacthing or our own hacking*/ | |
| 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,pixelStorei"; | |
| static void wrap_func(FILE *ifce_c, char *fname, char *fun_def) | |
| { | |
| char *sep, *nsep; | |
| u32 len, i, nb_args; | |
| u32 first_char; | |
| u32 ret_type=0; | |
| Bool is_create=GF_FALSE; | |
| Bool is_delete_fun=GF_FALSE; | |
| char *ret_val=NULL, *exc_value=NULL, *arg_type[50], *arg_name[50]; | |
| if (strstr(not_autogen_funcs, fname)) { | |
| fprintf(ifce_c, "\nstatic JSValue wgl_%s(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);\n", fname); | |
| return; | |
| } | |
| fprintf(ifce_c, "\nstatic JSValue wgl_%s(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)\n{\n", fname); | |
| nb_args = 0; | |
| memset(arg_type, 0, sizeof(char *)*50); | |
| memset(arg_name, 0, sizeof(char *)*50); | |
| sep = fun_def; | |
| while (sep[0]==' ') sep++; | |
| /*parse exception*/ | |
| if (sep[0]=='[') { | |
| nsep = strchr(sep, ']'); | |
| assert(nsep); | |
| nsep[0]=0; | |
| exc_value = gf_strdup(sep); | |
| nsep[0]=']'; | |
| sep = nsep+1; | |
| while (sep[0]==' ') sep++; | |
| } | |
| /*parse return value*/ | |
| nsep = strchr(sep, ' '); | |
| assert(nsep); | |
| nsep[0] = 0; | |
| ret_val = strdup(sep); | |
| sep = nsep+1; | |
| len = strlen(fname); | |
| assert(!strncmp(sep, fname, len) ); | |
| sep += len+1; | |
| while (sep) { | |
| char *next_arg; | |
| nsep = strchr(sep, ','); | |
| if (!nsep) { | |
| nsep = strchr(sep, ')'); | |
| if (!nsep) break; | |
| } | |
| nsep[0]=0; | |
| next_arg = nsep+1; | |
| if (nb_args>=50) { | |
| assert(0); | |
| } | |
| nsep = strchr(sep, ' '); | |
| if (!nsep) | |
| break; | |
| assert(nsep); | |
| nsep[0] = 0; | |
| arg_type[nb_args] = gf_strdup(sep); | |
| arg_name[nb_args] = gf_strdup(nsep+1); | |
| nb_args++; | |
| sep = next_arg; | |
| while (sep[0]==' ') sep++; | |
| } | |
| fprintf(ifce_c, "\tJSValue ret_val_js = JS_UNDEFINED;\n"); | |
| for (i=0; i<nb_args; i++) { | |
| put_arg_decl(ifce_c, fname, arg_type[i], arg_name[i]); | |
| } | |
| fprintf(ifce_c, "\tWGL_CHECK_CONTEXT\n"); | |
| if (nb_args) { | |
| fprintf(ifce_c, "\tif (argc<%d) return js_throw_err(ctx, WGL_INVALID_VALUE);\n", nb_args); | |
| for (i=0; i<nb_args; i++) { | |
| put_arg_get(ifce_c, fname, i, arg_type[i], arg_name[i]); | |
| } | |
| } | |
| /*hack a few funcs with different signatures*/ | |
| if (!strcmp(fname, "getActiveAttrib")) { | |
| fprintf(ifce_c, "\tret_val_js = webgl_getActiveAttrib(ctx, program, index);\n\treturn ret_val_js;\n"); | |
| goto fun_done; | |
| } | |
| if (!strcmp(fname, "getActiveUniform")) { | |
| fprintf(ifce_c, "\tret_val_js = webgl_getActiveUniform(ctx, program, index);\n\treturn ret_val_js;\n"); | |
| goto fun_done; | |
| } | |
| if (!strcmp(fname, "getAttachedShaders")) { | |
| fprintf(ifce_c, "\tret_val_js = webgl_getAttachedShaders(ctx, JS_GetOpaque(this_val, WebGLRenderingContextBase_class_id), program);\n\treturn ret_val_js;\n"); | |
| goto fun_done; | |
| } | |
| if (!strcmp(fname, "getBufferParameter")) { | |
| fprintf(ifce_c, "\tret_val_js = webgl_getBufferParameter(ctx, target, pname);\n\treturn ret_val_js;\n"); | |
| goto fun_done; | |
| } | |
| if (ret_val && strcmp(ret_val, "void")) { | |
| if (!strcmp(fname, "createBuffer") || !strcmp(fname, "createFramebuffer") || !strcmp(fname, "createTexture") || !strcmp(fname, "createRenderbuffer")) { | |
| fprintf(ifce_c, "\tGF_WebGLObject *wglo;\n"); | |
| is_create = GF_TRUE; | |
| ret_type = 2; | |
| } else if (!strcmp(fname, "createProgram") || !strcmp(fname, "createShader")) { | |
| fprintf(ifce_c, "\tGF_WebGLObject *wglo;\n"); | |
| ret_type = 2; | |
| } else { | |
| put_arg_decl(ifce_c, fname, ret_val, "ret_val"); | |
| ret_type = 1; | |
| } | |
| } | |
| first_char = fname[0]; | |
| if ((first_char < 'A') || (first_char > 'Z')) { | |
| first_char += 'A' - 'a'; | |
| } | |
| if (is_create) { | |
| fprintf(ifce_c, "\tGF_SAFEALLOC(wglo, GF_WebGLObject);\n"); | |
| fprintf(ifce_c, "\tif (!wglo) return js_throw_err(ctx, WGL_OUT_OF_MEMORY);\n"); | |
| fprintf(ifce_c, "\twglo->par_ctx = JS_GetOpaque(this_val, WebGLRenderingContextBase_class_id);\n"); | |
| fprintf(ifce_c, "\tglGen%ss(1, &wglo->gl_id", fname+6); | |
| } else { | |
| if (!strcmp(fname, "deleteShader") || !strcmp(fname, "deleteProgram")) { | |
| is_delete_fun=GF_TRUE; | |
| } | |
| if (!strcmp(fname, "deleteBuffer") || !strcmp(fname, "deleteTexture") || !strcmp(fname, "deleteFramebuffer") || !strcmp(fname, "deleteRenderbuffer")) { | |
| fprintf(ifce_c, "\tgl%c%ss(1, &", first_char, fname+1); | |
| is_delete_fun=GF_TRUE; | |
| } | |
| else if (!strcmp(fname, "createProgram") || !strcmp(fname, "createShader")) { | |
| fprintf(ifce_c, "\tGF_SAFEALLOC(wglo, GF_WebGLObject);\n"); | |
| fprintf(ifce_c, "\tif (!wglo) return js_throw_err(ctx, WGL_OUT_OF_MEMORY);\n"); | |
| fprintf(ifce_c, "\twglo->par_ctx = JS_GetOpaque(this_val, WebGLRenderingContextBase_class_id);\n"); | |
| fprintf(ifce_c, "\twglo->gl_id = gl%c%s(", first_char, fname+1); | |
| } else if (!strcmp(fname, "clearDepth") || !strcmp(fname, "depthRange")) { | |
| fprintf(ifce_c, "#if defined(GPAC_USE_GLES2)\n"); | |
| fprintf(ifce_c, "\tgl%c%sf(\n", first_char, fname+1); | |
| fprintf(ifce_c, "#else\n"); | |
| fprintf(ifce_c, "\tgl%c%s(\n", first_char, fname+1); | |
| fprintf(ifce_c, "#endif\n\t\t"); | |
| } else { | |
| fprintf(ifce_c, "\t"); | |
| if (ret_type==1) { | |
| fprintf(ifce_c, "ret_val = "); | |
| } | |
| if (!strncmp(fname, "uniform", 7)) { | |
| fprintf(ifce_c, "/*hack for GPAC textures, we create uniforms with loc -2 for such textures*/\n\tif ((s32) location>=0)\n\t\t"); | |
| } | |
| fprintf(ifce_c, "gl%c%s(", first_char, fname+1); | |
| } | |
| } | |
| Bool prev_is_transpose = GF_FALSE; | |
| for (i=0; i<nb_args; i++) { | |
| Bool is_array; | |
| get_arg_type(arg_type[i], &is_array); | |
| if (!strcmp(arg_name[i], "transpose")) { | |
| fprintf(ifce_c, "%s_size, ", arg_name[i+1]); | |
| prev_is_transpose = GF_TRUE; | |
| } | |
| else if (prev_is_transpose) { | |
| is_array = GF_FALSE; | |
| } | |
| if (is_array && ( | |
| !strcmp(fname, "bufferData") || !strcmp(fname, "bufferSubData") | |
| || !strcmp(fname, "compressedTexImage2D") || !strcmp(fname, "compressedTexSubImage2D") | |
| || !strncmp(fname, "uniform", 7) | |
| )) { | |
| is_array = GF_FALSE; | |
| fprintf(ifce_c, "%s_size, ", arg_name[i]); | |
| } | |
| if (!strcmp(arg_type[i], "GLintptr") && (!strcmp(fname, "vertexAttribPointer") || !strcmp(fname, "drawElements")) ) { | |
| fprintf(ifce_c, "(void *)"); | |
| } | |
| fprintf(ifce_c, "%s", arg_name[i]); | |
| if (is_array) { | |
| if (strstr(fname, "vertexAttrib1fv")) {} | |
| else if (strstr(fname, "vertexAttrib2fv")) {} | |
| else if (strstr(fname, "vertexAttrib3fv")) {} | |
| else if (strstr(fname, "vertexAttrib4fv")) {} | |
| else { | |
| fprintf(ifce_c, ", %s_size", arg_name[i]); | |
| } | |
| } | |
| if (i+1<nb_args) | |
| fprintf(ifce_c, ", "); | |
| } | |
| fprintf(ifce_c, ");\n"); | |
| if (is_delete_fun) { | |
| Bool is_array; | |
| const char *nat_type = get_arg_type(arg_type[0], &is_array); | |
| 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); | |
| 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\tgf_free(glo);\n\tJS_SetOpaque(argv[0], NULL);\n"); | |
| fprintf(ifce_c, "\t}\n\t}\n"); | |
| } | |
| if (ret_type==1) { | |
| if (!strcmp(ret_val, "GLenum") || !strcmp(ret_val, "GLint")) { | |
| fprintf(ifce_c, "\tret_val_js = JS_NewInt32(ctx, ret_val);\n"); | |
| } else if (!strcmp(ret_val, "GLboolean") ) { | |
| fprintf(ifce_c, "\tret_val_js = JS_NewBool(ctx, ret_val);\n"); | |
| } else if (!strcmp(ret_val, "WebGLProgram") ) { | |
| fprintf(ifce_c, "\tret_val_js = JS_NewObjectClass(ctx, WebGLProgram_class_id);\n"); | |
| fprintf(ifce_c, "\tJS_SetOpaque(ret_val_js, wglo);\n"); | |
| } else { | |
| fprintf(stderr, "retval %s not supported in %s\n", ret_val, fname); | |
| } | |
| } else if (ret_type==2) { | |
| Bool is_array; | |
| const char *native_type = get_arg_type(ret_val, &is_array); | |
| fprintf(ifce_c, "\tret_val_js = JS_NewObjectClass(ctx, %s_class_id);\n", native_type); | |
| fprintf(ifce_c, "\tJS_SetOpaque(ret_val_js, wglo);\n"); | |
| fprintf(ifce_c, "\twglo->obj = JS_DupValue(ctx, ret_val_js);\n"); | |
| fprintf(ifce_c, "\twglo->class_id = %s_class_id;\n", native_type); | |
| fprintf(ifce_c, "\tgf_list_add(wglo->par_ctx->all_objects, wglo);\n"); | |
| } | |
| for (i=0; i<nb_args; i++) { | |
| Bool is_array; | |
| const char *native_type = get_arg_type(arg_type[i], &is_array); | |
| if (!native_type) continue; | |
| if (!strcmp(native_type, "const char *")) { | |
| fprintf(ifce_c, "\tJS_FreeCString(ctx, %s);\n", arg_name[i]); | |
| } | |
| if (is_array && strcmp(native_type, "u8 *")) { | |
| if (strstr(fname, "vertexAttrib1fv")) { | |
| } else if (strstr(fname, "vertexAttrib2fv")) { | |
| } else if (strstr(fname, "vertexAttrib3fv")) { | |
| } else if (strstr(fname, "vertexAttrib4fv")) { | |
| } else { | |
| fprintf(ifce_c, "\tif (%s) gf_free(%s);\n", arg_name[i], arg_name[i]); | |
| } | |
| } | |
| } | |
| fprintf(ifce_c, "\treturn ret_val_js;\n"); | |
| fun_done: | |
| while (nb_args>1) { | |
| gf_free(arg_type[nb_args-1]); | |
| gf_free(arg_name[nb_args-1]); | |
| nb_args--; | |
| } | |
| gf_free(ret_val); | |
| fprintf(ifce_c, "}\n"); | |
| } | |
| static void load_idl(const char *file) | |
| { | |
| Bool in_ctxbase = GF_FALSE; | |
| char szLine[4001], *sep; | |
| char *curCtx = NULL; | |
| u32 len; | |
| FILE * idl = gf_fopen(file, "rt"); | |
| FILE *ifce_c=NULL; | |
| FILE *fun_defs=NULL; | |
| while (!feof(idl)) { | |
| gf_fgets(szLine, 4000, idl); | |
| if (strstr(szLine, "implements")) | |
| continue; | |
| len = strlen(szLine); | |
| while (len && strchr(" \n", szLine[len])) { | |
| szLine[len] = 0; | |
| len--; | |
| } | |
| if (!len) continue; | |
| if (!in_ctxbase) { | |
| if (!strstr(szLine, "RenderingContextBase")) | |
| continue; | |
| in_ctxbase = GF_TRUE; | |
| sep = strchr(szLine, ' '); | |
| assert(sep); | |
| curCtx = gf_strdup(sep+1); | |
| start_ctx(curCtx, &ifce_c, &fun_defs); | |
| continue; | |
| } else { | |
| if (strstr(szLine, "};")){ | |
| in_ctxbase = GF_FALSE; | |
| end_ctx(ifce_c, fun_defs, curCtx); | |
| ifce_c = NULL; | |
| continue; | |
| } | |
| } | |
| if (strstr(szLine, "/*")) continue; | |
| sep = strstr(szLine, "const "); | |
| if (sep) { | |
| char *cname, *nsep; | |
| sep = strchr(sep+7, ' '); | |
| assert(sep); | |
| sep++; | |
| nsep = strchr(sep, ' '); | |
| assert(nsep); | |
| nsep[0] = 0; | |
| cname = gf_strdup(sep); | |
| sep = strchr(nsep+1, '='); | |
| assert(sep); | |
| sep++; | |
| while (sep[0]==' ') sep++; | |
| nsep = strchr(sep, ';'); | |
| assert(nsep); | |
| nsep[0]=0; | |
| put_const(fun_defs, cname, sep); | |
| gf_free(cname); | |
| continue; | |
| } | |
| sep = strstr(szLine, "typedef"); | |
| if (sep) continue; | |
| sep = strstr(szLine, "attribute"); | |
| if (sep) { | |
| char *nsep; | |
| Bool is_readonly = GF_FALSE; | |
| sep = szLine; | |
| while (sep[0]==' ') sep++; | |
| if (!strncmp(sep, "readonly", 8)) { | |
| is_readonly = GF_TRUE; | |
| sep+=9; | |
| } | |
| sep += 10; | |
| sep = strchr(sep, ' '); | |
| assert(sep); | |
| sep+=1; | |
| nsep = strchr(sep, ';'); | |
| assert(nsep); | |
| nsep[0] = 0; | |
| put_prop(fun_defs, curCtx, sep, is_readonly); | |
| continue; | |
| } | |
| /*double type declaration for glXXXifv*/ | |
| if (strstr(szLine, ", sequence<")) | |
| continue; | |
| /*double type declaration for bufferData*/ | |
| if (strstr(szLine, ", GLsizeiptr size")) | |
| continue; | |
| /*double type declaration for texImage2D and texSubImage2D*/ | |
| if (strstr(szLine, ", TexImageSource")) | |
| continue; | |
| sep = strstr(szLine, "("); | |
| /*this is a function*/ | |
| if (sep) { | |
| char *nsep, *fname; | |
| sep = strchr(szLine, ']'); | |
| if (sep) sep+=1; | |
| else sep = szLine; | |
| while (sep[0] == ' ') sep++; | |
| sep = strchr(sep, ' '); | |
| assert(sep); | |
| sep++; | |
| nsep = strchr(sep, '('); | |
| assert(nsep); | |
| nsep[0] = 0; | |
| fname = gf_strdup(sep); | |
| put_fun(fun_defs, sep); | |
| nsep[0] = '('; | |
| wrap_func(ifce_c, fname, szLine); | |
| gf_free(fname); | |
| continue; | |
| } | |
| fprintf(stderr, "instruction %s not handled\n", szLine); | |
| } | |
| gf_fclose(idl); | |
| } | |
| int main(int argc, char **argv) | |
| { | |
| u32 i=0; | |
| for (i=1; i<argc; i++) { | |
| load_idl(argv[i]); | |
| } | |
| return 0; | |
| } | |