1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2008-2018. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20%%%------------------------------------------------------------------- 21%%% File : gl_gen_erl.erl 22%%% Author : Dan Gudmundsson <dgud@erix.ericsson.se> 23%%% Description : 24%%% 25%%% Created : 18 Apr 2007 by Dan Gudmundsson <dgud@erix.ericsson.se> 26%%%------------------------------------------------------------------- 27-module(gl_gen_erl). 28 29-include("gl_gen.hrl"). 30 31-compile(export_all). 32 33-import(lists, [foldl/3,foldr/3,reverse/1, keysearch/3, map/2, filter/2, max/1]). 34-import(gen_util, [lowercase/1, lowercase_all/1, uppercase/1, uppercase_all/1, 35 open_write/1, open_write/2, close/0, erl_copyright/0, w/2, 36 args/3, args/4, strip_name/2]). 37 38 39-define(HTTP_TOP, "https://www.khronos.org/registry/OpenGL-Refpages/"). 40 41gl_defines(Defs) -> 42 open_write("../include/gl.hrl"), 43 erl_copyright(), 44 w("~n%% OPENGL DEFINITIONS~n~n", []), 45 w("%% This file is generated DO NOT EDIT~n~n", []), 46 [gen_define(Def) || Def=#def{} <- Defs], 47 close(), 48 ok. 49 50glu_defines(Defs) -> 51 open_write("../include/glu.hrl"), 52 erl_copyright(), 53 w("~n%% GLU DEFINITIONS~n~n", []), 54 w("%% This file is generated DO NOT EDIT~n~n", []), 55 [gen_define(Def) || Def=#def{} <- Defs], 56 close(), 57 ok. 58 59gen_define(#def{name=N, val=Val, type=int}) -> 60 w("-define(~s, ~p).~n", [N,Val]); 61gen_define(#def{name=N, val=Val, type=float_str}) -> 62 w("-define(~s, ~s).~n", [N,Val]); 63gen_define(#def{name=N, val=Val, type=hex}) -> 64 w("-define(~s, 16#~s).~n", [N,Val]); 65gen_define(#def{name=N, val=Val, type=string}) -> 66 w("-define(~s, ?~s).~n", [N,Val]); 67gen_define(#def{name="GLEXT_64_TYPES"++_, val=undefined, type=undefined}) -> 68 ok. 69 70types() -> 71 [{"GLenum", "32/native-unsigned"}, 72 {"GLboolean", "8/native-unsigned"}, 73 {"GLbitfield","32/native-unsigned"}, % 74 %%{"GLvoid",":void "},% 75 {"GLbyte", "8/native-signed"}, % 1-byte signed 76 {"GLshort", "16/native-signed"}, % 2-byte signed 77 {"GLint", "32/native-signed"}, % 4-byte signed 78 {"GLubyte", "8/native-unsigned"}, % 1-byte unsigned 79 {"GLushort", "16/native-unsigned"}, % 2-byte unsigned 80 {"GLuint", "32/native-unsigned"}, % 4-byte unsigned 81 {"GLsizei", "32/native-signed"}, % 4-byte signed 82 {"GLfloat", "32/native-float"}, % single precision float 83 {"GLclampf", "32/native-float"}, % single precision float in [0,1] 84 {"GLdouble", "64/native-float"}, % double precision float 85 {"GLclampd", "64/native-float"}, % double precision float in [0,1] 86 {"GLsizeiptr","64/native-unsigned"}, % 64 bits int, convert on c-side 87 {"GLintptr", "64/native-unsigned"}, % 64 bits int, convert on c-sidew 88 {"GLUquadric", "64/native-unsigned"},% Handle 32bits aargh 64bits on mac64 89 {"GLhandleARB","64/native-unsigned"},% Handle 32bits aargh 64bits on mac64 90 91 {"GLsync", "64/native-unsigned"}, % Pointer to record 92 {"GLuint64", "64/native-unsigned"}, 93 {"GLint64", "64/native-signed"} 94 ]. 95 96gl_api(Fs) -> 97 open_write("../src/gen/gl.erl", [{encoding,utf8}]), 98 erl_copyright(), 99 w("~n%% OPENGL API~n~n", []), 100 w("%% This file is generated DO NOT EDIT~n~n", []), 101 w("%% @doc Standard OpenGL api.~n", []), 102 w("%% See <a href=\""++ ?HTTP_TOP ++ "\">www.khronos.org</a>~n",[]), 103 w("%%~n", []), 104 w("%% Booleans are represented by integers 0 and 1.~n~n", []), 105 106 w("-module(gl).~n~n",[]), 107 w("-compile(inline).~n", []), 108%% w("-include(\"wxe.hrl\").~n", []), 109 [w("-define(~s,~s).~n", [GL,Erl]) || {GL,Erl} <- types()], 110 111 gen_types(gl), 112 113 Exp = fun(F) -> gen_export(F) end, 114 ExportList = lists:map(Exp,Fs), 115 116 w("~n-export([~s]).~n~n", [args(fun(EF) -> EF end, ",", ExportList, 60)]), 117 w("-export([call/2, cast/2, send_bin/1]).~n",[]), 118 w("%% @hidden~n", []), 119 w("call(Op, Args) ->~n", []), 120 w(" Port = get(opengl_port), ~n", []), 121 w(" _ = erlang:port_control(Port,Op,Args),~n", []), 122 w(" rec(Op).~n", []), 123 w(" ~n", []), 124 w("%% @hidden~n", []), 125 w("cast(Op, Args) ->~n", []), 126 w(" Port = get(opengl_port), ~n", []), 127 w(" _ = erlang:port_control(Port,Op,Args),~n", []), 128 w(" ok.~n", []), 129 w(" ~n", []), 130 w("%% @hidden~n", []), 131 w("rec(Op) ->~n", []), 132 w(" receive~n", []), 133 w(" {'_egl_result_', Res} -> Res;~n", []), 134 w(" {'_egl_error_', Op, Res} -> error({error,Res,Op});~n", []), 135 w(" {'_egl_error_', Other, Res} ->~n ", []), 136 w(" Err = io_lib:format(\"~~p in op: ~~p\", [Res, Other]),~n", []), 137 w(" error_logger:error_report([{gl, error}, {message, lists:flatten(Err)}]),~n", []), 138 w(" rec(Op)~n", []), 139 w(" end.~n", []), 140 w("~n", []), 141 w("%% @hidden~n", []), 142 w("send_bin(Bin) when is_binary(Bin) ->~n", []), 143 w(" Port = get(opengl_port), ~n", []), 144 w(" erlang:port_command(Port,Bin);~n", []), 145 w("send_bin(Tuple) when is_tuple(Tuple) ->~n", []), 146 w(" Port = get(opengl_port), ~n", []), 147 w(" case element(2, Tuple) of~n", []), 148 w(" Bin when is_binary(Bin) ->~n", []), 149 w(" erlang:port_command(Port,Bin)~n", []), 150 w(" end.~n", []), 151 w("~n", []), 152 153 w("~n%% API~n~n", []), 154 [gen_funcs(F) || F <- Fs], 155 close(), 156 ok. 157 158glu_api(Fs) -> 159 open_write("../src/gen/glu.erl", [{encoding,utf8}]), 160 erl_copyright(), 161 w("~n%% OPENGL UTILITY API~n~n", []), 162 w("%% This file is generated DO NOT EDIT~n~n", []), 163 w("%% @doc A part of the standard OpenGL Utility api.~n", []), 164 w("%% See <a href=\""++ ?HTTP_TOP ++ "\">www.khronos.org</a>~n",[]), 165 w("%%~n", []), 166 w("%% Booleans are represented by integers 0 and 1.~n~n", []), 167 168 w("-module(glu).~n",[]), 169 w("-compile(inline).~n", []), 170 %%w("-include(\"wxe.hrl\").~n", []), 171 [w("-define(~s,~s).~n", [GL,Erl]) || {GL,Erl} <- types()], 172 173 gen_types(glu), 174 175 Exp = fun(F) -> gen_export(F) end, 176 ExportList = ["tesselate/2" | lists:map(Exp,Fs)], 177 w("~n-export([~s]).~n~n", [args(fun(EF) -> EF end, ",", ExportList, 60)]), 178 w("-import(gl, [call/2,cast/2,send_bin/1]).", []), 179 w("~n%% API~n~n", []), 180 181 %% w("%% @spec (Vec3, [Vec3]) -> {Triangles, VertexPos}~n",[]), 182 %% w("%% Vec3 = {float(),float(),float()}~n",[]), 183 %% w("%% Triangles = [VertexIndex::integer()]~n",[]), 184 %% w("%% VertexPos = binary()~n",[]), 185 w("%% @doc General purpose polygon triangulation.~n",[]), 186 w("%% The first argument is the normal and the second a list of~n" 187 "%% vertex positions. Returned is a list of indecies of the vertices~n" 188 "%% and a binary (64bit native float) containing an array of~n" 189 "%% vertex positions, it starts with the vertices in Vs and~n" 190 "%% may contain newly created vertices in the end.~n", []), 191 192 w("-spec tesselate(Normal, [Vs]) -> {Triangles, VertexPos}~n", []), 193 w(" when Normal :: vertex(), Vs :: vertex(),~n", []), 194 w(" Triangles :: [integer()], VertexPos :: binary().~n", []), 195 w("tesselate({Nx,Ny,Nz}, Vs) ->~n",[]), 196 w(" call(5000, <<(length(Vs)):32/native,0:32,~n" 197 " Nx:?GLdouble,Ny:?GLdouble,Nz:?GLdouble,~n" 198 " (<< <<Vx:?GLdouble,Vy:?GLdouble,Vz:?GLdouble >>~n" 199 " || {Vx,Vy,Vz} <- Vs>>)/binary >>).~n~n", []), 200 201 [gen_funcs(F) || F <- Fs], 202 close(), 203 ok. 204 205gen_funcs([F]) when is_list(F) -> 206 put(current_func,F), 207 gen_func(get(F)), 208 erase(current_func), 209 w(".~n~n",[]); 210gen_funcs(All=[F|Fs]) when is_list(F) -> 211 put(current_func,F), 212 gen_doc([get(A) || A <- All]), 213 gen_func(get(F)), 214 erase(current_func), 215 w(";~n",[]), 216 gen_funcs(Fs); 217gen_funcs([]) -> 218 w(".~n~n",[]); 219gen_funcs(F) -> 220 put(current_func,F), 221 gen_doc([get(F)]), 222 gen_func(get(F)), 223 erase(current_func), 224 w(".~n~n",[]). 225 226gen_types(Where) -> 227 case Where of 228 glu -> 229 w("-type vertex() :: {float(), float(), float()}.~n", []), 230 w("-type enum() :: non_neg_integer(). %% See wx/include/gl.hrl or glu.hrl~n", []); 231 gl -> 232 w("-type enum() :: non_neg_integer(). %% See wx/include/gl.hrl~n", []), 233 w("-type clamp() :: float(). %% 0.0..1.0~n", []), 234 w("-type offset() :: non_neg_integer(). %% Offset in memory block~n", []) 235 end, 236 w("-type matrix12() :: {float(),float(),float(),float(),~n", []), 237 w(" float(),float(),float(),float(),~n", []), 238 w(" float(),float(),float(),float()}.~n", []), 239 w("-type matrix16() :: {float(),float(),float(),float(),~n", []), 240 w(" float(),float(),float(),float(),~n", []), 241 w(" float(),float(),float(),float(),~n", []), 242 w(" float(),float(),float(),float()}.~n", []), 243 w("-type matrix() :: matrix12() | matrix16().~n", []), 244 w("-type mem() :: binary() | tuple(). %% Memory block~n", []), 245 ok. 246 247gen_export(F) -> 248 try gen_export_1(F) 249 catch E:R:S -> 250 io:format("Crash ~p:~p in ~p ~n",[E,R,S]), 251 io:format("Func = ~p~n ~p", [F, get(F)]) 252 end. 253 254gen_export_1([F|_]) when is_list(F) -> 255 gen_export2(get(F)); 256gen_export_1(F) when is_list(F) -> 257 gen_export2(get(F)). 258 259gen_export2(#func{name=Name,alt=Alt={vector,VecPos,Vec}}) -> 260 #func{params=As0} = get(Vec), 261 {As1,_As2} = lists:split(VecPos, As0), 262 Args = lists:filter(fun(Arg) -> func_arg(Arg) =/= skip end, As1), 263 Export = erl_func_name(Name) ++ "/" ++ integer_to_list(length(Args) +1), 264 DocN = doc_name(Name,Alt), 265 (get({export_arg,DocN}) == undefined) andalso put({export_arg, DocN}, Export), 266 Export; 267gen_export2(#func{name=Name,params=As0, alt=Alt}) -> 268 Args = lists:filter(fun(Arg) -> func_arg(Arg) =/= skip end, As0), 269 Export = erl_func_name(Name) ++ "/" ++ integer_to_list(length(Args)), 270 DocN = doc_name(Name,Alt), 271 (get({export_arg,DocN}) == undefined) andalso put({export_arg, DocN}, Export), 272 Export. 273 274gen_doc([#func{name=Name, params=Orig, alt={vector,VecPos,Vec}}]) -> 275 #func{type=T,params=As} = get(Vec), 276 {As1,As2} = lists:split(VecPos, As), 277 #arg{name=OrigName} = lists:last(Orig), 278 Args1 = case args(fun func_arg/1, ",", As1) of [] -> []; Else -> Else++"," end, 279 Args2 = args(fun func_arg/1, ",", As2), 280 w("%% @equiv ~s(~s)~n",[erl_func_name(Vec), Args1++Args2]), 281 SA1 = case doc_arg_types(As1) of [] -> []; E -> E++"," end, 282 SA2 = doc_arg_types(As2), 283 w("-spec ~s(~s~s) -> ~s when ~s :: {~s}.~n", 284 [erl_func_name(Name), SA1, erl_arg_name(OrigName), 285 doc_return_types(T,As), erl_arg_name(OrigName), SA2]); 286 287gen_doc([F=#func{name=Name,type=T,params=As, alt=Alt}|_]) -> 288 gen_doc(Name, Alt, gen_export2(F)), 289 Ps = [Arg || #arg{name=Arg, in=In, where=Where} <- As, 290 In =/= false, Where =/= c], 291 Args = args(fun erl_arg_name/1, ", ", Ps), 292 case Args of 293 [] -> 294 w("-spec ~s(~s) -> ~s.~n", 295 [erl_func_name(Name), Args, doc_return_types(T,As)]); 296 _ -> w("-spec ~s(~s) -> ~s when ~s.~n", 297 [erl_func_name(Name), Args, doc_return_types(T,As), doc_arg_types(As)]) 298 end. 299 300-define(LINE_LEN, 90). 301 302gen_doc(Name0, Alt, Export) -> 303 Name = doc_name(Name0, Alt), 304 case get({doc, Name}) of 305 undefined -> 306 case parse_doc(Name, Dir1 ="gl_man4", Dir2="gl_man2") of 307 {error, _} -> 308 case reverse(Name) of 309 "BRA" ++ _ -> ok; 310 "TXE" ++ _ -> ok; 311 _ -> 312 %% io:format("Missing doc: no ~s.xml (~s) found in ~s or ~s~n", 313 %% [Name, Name0, Dir1, Dir2]), 314 ok 315 end, 316 w("%% @doc ~s~n%%~n" 317 "%% See <a href=\"~s\">external</a> documentation.~n", 318 [Name, ?HTTP_TOP]); 319 {Found, Doc} -> 320 {Dir,Ext} = case Found of 321 Dir1 -> {"gl4/html", "xhtml"}; 322 Dir2 -> {"gl2.1/xhtml", "xml"} 323 end, 324 put({doc, Name}, Export), 325 format_doc(Doc, ?LINE_LEN), 326 w("~n%%~n%% See <a href=\"~s~s/~s.~s\">external</a> documentation.~n", 327 [?HTTP_TOP, Dir, Name, Ext]) 328 end; 329 Where -> 330 w("%% @doc ~n", []), 331 w("%% See {@link ~s}~n", [Where]) 332 end. 333 334parse_doc(Name, Dir1, Dir2) -> 335 case gl_scan_doc:file(filename:join(Dir1, Name++".xml"), []) of 336 {error, {_, "no such" ++ _}} -> 337 case gl_scan_doc:file(filename:join(Dir2, Name++".xml"), []) of 338 {error, _} = Err -> Err; 339 Doc -> {Dir2, Doc} 340 end; 341 Doc -> 342 {Dir1, Doc} 343 end. 344 345format_doc(Strs, Count) when Count < 0 -> 346 w("~n%% ", []), 347 format_doc(Strs, ?LINE_LEN); 348format_doc([{constant, Const}|Rest], Count) -> 349 w("`?~s'", [Const]), 350 format_doc(Rest, Count-length(Const)-8); 351format_doc([{emphasis, Const}|Rest], Count) -> 352 w("`~ts'", [Const]), 353 format_doc(Rest, Count-length(Const)-7); 354format_doc([{function, Func}|Rest], Count) -> 355 case Func of 356 "glu" ++ _ -> 357 w("``glu:~s''", [erl_func_name(Func)]); 358 "gl" ++ _ -> 359 w("``gl:~s''", [erl_func_name(Func)]); 360 _ -> 361 w("`~s'", [Func]) 362 end, 363 format_doc(Rest, Count-length(Func)-7); 364format_doc([{reffunc, Func}|Rest], Count) -> 365 Out = fun(Export) -> 366 case Func of 367 "glu" ++ _ -> w(" {@link glu:~s} ", [Export]); 368 "gl" ++ _ -> w(" {@link gl:~s} ", [Export]) 369 end 370 end, 371 case get({export_arg, Func}) of 372 undefined -> 373 case get({export_arg, doc_name(Func, undefined)}) of 374 undefined -> 375 %% io:format("Func ~p undefined (~p) ~n", 376 %% [Func, doc_name(Func, undef)]), 377 w("see `~s'", [Func]); 378 Export -> Out(Export) 379 end; 380 Export -> 381 Out(Export) 382 end, 383 format_doc(Rest, Count-length(Func)-10); 384format_doc([{parameter, Param}|Rest], Count) -> 385 w(" `~s' ", [erl_arg_name(Param)]), 386 format_doc(Rest, Count-length(Param)-7); 387format_doc([{equation, Eq}|Rest], Count) -> 388%% w("```", []), 389 format_doc([Eq], Count), 390%% w("'''", []), 391 format_doc(Rest, Count); 392format_doc([{fenced, Open, Close, Eq}|Rest], Count) -> 393 w(Open, []), 394 format_doc(Eq, Count), 395 w(Close, []), 396 format_doc(Rest, Count); 397 398format_doc([{code, Code}|Rest], Count) -> 399 w("``~ts''", [Code]), 400 format_doc(Rest, Count-length(Code)-7); 401 402format_doc([para|Rest], _Count) -> 403 w("~n%%~n%% ", []), 404 format_doc(Rest, ?LINE_LEN); 405format_doc([break|Rest], _Count) -> 406 w("<br />~n%% ", []), 407 format_doc(Rest, ?LINE_LEN); 408format_doc([{purpose, Purpose}, para | Doc], _Count) -> 409 w("%% @doc ~ts~n%%~n%% ", [uppercase(Purpose)]), 410 format_doc(Doc, ?LINE_LEN); 411format_doc([{purpose, Purpose} | Doc], _Count) -> 412 w("%% @doc ~ts~n%%~n%% ", [Purpose]), 413 format_doc(Doc, ?LINE_LEN); 414format_doc([listentry|Rest], _Count) -> 415 w("~n%%~n%% ", []), 416 format_doc(Rest, ?LINE_LEN); 417format_doc([Str|Rest], Count) -> 418 case length(Str) of 419 Len when Len < Count -> 420 w("~ts", [Str]), 421 format_doc(Rest, Count-Len); 422 _ -> 423 {Str1, Str2} = split(Str, Count, []), 424 w("~ts~n%% ", [Str1]), 425 format_doc([Str2|Rest], ?LINE_LEN) 426 end; 427format_doc([], _) -> ok. 428 429split([$ |Str], Count, Acc) when Count =< 5 -> 430 {reverse(Acc), Str}; 431split([Chr|Str], Count, Acc) -> 432 split(Str, Count-1, [Chr|Acc]); 433split([], _, Acc) -> 434 {reverse(Acc), []}. 435 436gen_func(#func{name=Name,alt={vector,VecPos,Vec}}) -> 437 #func{params=As} = get(Vec), 438 {As1,As2} = lists:split(VecPos, As), 439 Args1 = case args(fun func_arg/1, ",", As1) of [] -> []; Else -> Else++"," end, 440 Args2 = args(fun func_arg/1, ",", As2), 441 442 w("~s(~s{~s}) ->", [erl_func_name(Name),Args1,Args2]), 443 w(" ~s(~s)", [erl_func_name(Vec), Args1++Args2]); 444gen_func(_F=#func{name=Name,type=T,params=As,id=MId}) -> 445 Args = args(fun func_arg/1, ",", As), 446 w("~s(~s)~s ", [erl_func_name(Name), Args, guard_test(As)]), 447 w("->~n", []), 448 PreAs = pre_marshal(As), 449 {StrArgs,_} = marshal_args(PreAs), 450 case have_return_vals(T,As) of 451 true -> 452 w(" call(~p, <<~s>>)", [MId, StrArgs]); 453 false -> 454 w(" cast(~p, <<~s>>)", [MId, StrArgs]) 455 end. 456 457func_arg(#arg{in=In,where=W,name=Name,type=Type}) 458 when In =/= false, W =/= c -> 459 case Type of 460 #type{single={tuple,TSz0}} when TSz0 =/= undefined -> 461 TSz = if is_integer(TSz0) -> TSz0; 462 TSz0 =:= matrix12 -> 12 463 end, 464 [NameId|_] = erl_arg_name(Name), 465 Names = [[NameId|integer_to_list(Id)] || Id <- lists:seq(1,TSz)], 466 "{" ++ args(fun(ElName) -> ElName end, ",", Names) ++ "}"; 467 _ -> 468 erl_arg_name(Name) 469 end; 470func_arg(_) -> skip. 471 472doc_arg_types(Ps0) -> 473 Ps = [P || P=#arg{in=In, where=Where} <- Ps0,In =/= false, Where =/= c], 474 args(fun(Arg) -> doc_arg_type(Arg) end, ",", Ps). 475 476doc_return_types(T, Ps0) -> 477 Ps = [P || P=#arg{in=In, where=Where} <- Ps0,In =/= true, Where =/= c], 478 doc_return_types2(T, Ps). 479 480doc_return_types2(void, []) -> "'ok'"; 481doc_return_types2(void, [#arg{type=T}]) -> doc_arg_type2(T); 482doc_return_types2(T, []) -> doc_arg_type2(T); 483doc_return_types2(void, Ps) -> 484 "{" ++ args(fun(Arg) -> doc_arg_type(Arg) end,",",Ps) ++ "}"; 485doc_return_types2(T, Ps) -> 486 "{" ++ doc_arg_type2(T) ++ "," ++ 487 args(fun(Arg) -> doc_arg_type(Arg) end,",",Ps) ++ "}". 488 489doc_arg_type(#arg{name=Name,type=T}) -> 490 try 491 erl_arg_name(Name) ++ " :: " ++ doc_arg_type2(T) 492 catch _:Error:Stacktrace -> 493 io:format("Error spec: ~p ~p~n~p~n",[Name, Error, Stacktrace]), 494 exit(error) 495 end. 496 497doc_arg_type2(T=#type{single=true}) -> 498 doc_arg_type3(T); 499doc_arg_type2(T=#type{single=undefined}) -> 500 doc_arg_type3(T); 501doc_arg_type2(_T=#type{single={tuple,undefined}}) -> 502 "tuple()"; 503doc_arg_type2(#type{base=float, single={tuple,16}}) -> 504 "matrix()"; 505doc_arg_type2(#type{base=string, single=list}) -> 506 "iolist()"; 507doc_arg_type2(T=#type{single={tuple,Sz}}) -> 508 "{" ++ args(fun doc_arg_type3/1, ",", lists:duplicate(Sz,T)) ++ "}"; 509doc_arg_type2(#type{base=guard_int, single=list}) -> 510 "[integer()]|mem()"; 511doc_arg_type2(T=#type{single=list}) -> 512 "[" ++ doc_arg_type3(T) ++ "]"; 513doc_arg_type2(T=#type{single={list, _Max}}) -> 514 "[" ++ doc_arg_type3(T) ++ "]"; 515doc_arg_type2(T=#type{single={list,_,_}}) -> 516 "[" ++ doc_arg_type3(T) ++ "]"; 517doc_arg_type2(T=#type{single={tuple_list,Sz}}) -> 518 "[{" ++ args(fun doc_arg_type3/1, ",", lists:duplicate(Sz,T)) ++ "}]". 519 520doc_arg_type3(#type{name="GLenum"}) -> "enum()"; 521doc_arg_type3(#type{name="GLclamp"++_}) -> "clamp()"; 522doc_arg_type3(#type{base=int}) -> "integer()"; 523doc_arg_type3(#type{base=float}) -> "float()"; 524doc_arg_type3(#type{base=guard_int}) -> "offset()|mem()"; 525doc_arg_type3(#type{base=string}) -> "string()"; 526doc_arg_type3(#type{base=bool}) -> "0|1"; 527doc_arg_type3(#type{base=binary}) -> "binary()"; 528doc_arg_type3(#type{base=memory}) -> "mem()". 529 530guard_test(As) -> 531 Str = args(fun(#arg{name=N,type=#type{base=guard_int, single=list}}) -> 532 " is_list("++erl_arg_name(N)++")"; 533 (#arg{name=N,type=#type{base=guard_int}}) -> 534 " is_integer("++erl_arg_name(N)++")"; 535 (_) -> 536 skip 537 end, ",", As), 538 case Str of 539 [] -> []; 540 Other -> " when " ++ Other 541 end. 542 543pre_marshal([#arg{name=N,in=true, type=#type{base=binary, single=list}=T, alt=list_binary}=A|R]) -> 544 w(" send_bin(~s),~n", [erl_arg_name(N)]), 545 w(" ~sLen = byte_size(if is_binary(~s) -> ~s; is_tuple(~s) -> element(2, ~s) end) div 4,~n", 546 [erl_arg_name(N),erl_arg_name(N), erl_arg_name(N), erl_arg_name(N), erl_arg_name(N)]), 547 Type = T#type{base=int, by_val=true, single=true, ref=undefined}, 548 Arg=A#arg{name=N++"Len", where=both, type=Type}, 549 [Arg|pre_marshal(R)]; 550pre_marshal([#arg{name=N,in=true,type=#type{base=binary}}|R]) -> 551 w(" send_bin(~s),~n", [erl_arg_name(N)]), 552 pre_marshal(R); 553pre_marshal([#arg{name=N,type=#type{base=memory}}|R]) -> 554 w(" send_bin(~s),~n", [erl_arg_name(N)]), 555 pre_marshal(R); 556pre_marshal([A=#arg{name=N,type=#type{base=string,single=list}}|R]) -> 557 %% With null terminations 558 w(" ~sTemp = list_to_binary([[Str|[0]] || Str <- ~s ]),~n", 559 [erl_arg_name(N), erl_arg_name(N)]), 560 w(" ~sLen = length(~s),~n",[erl_arg_name(N), erl_arg_name(N)]), 561 [A|pre_marshal(R)]; 562pre_marshal([A=#arg{name=N,type=#type{base=string,single=true,ref={pointer,1}}}|R]) -> 563 w(" ~sLen = length(~s),~n",[erl_arg_name(N), erl_arg_name(N)]), 564 [A|pre_marshal(R)]; 565pre_marshal([A=#arg{name=N,type=#type{single=list}}|R]) -> 566 w(" ~sLen = length(~s),~n",[erl_arg_name(N), erl_arg_name(N)]), 567 [A|pre_marshal(R)]; 568pre_marshal([A=#arg{name=N,type=#type{single={tuple_list,_}}}|R]) -> 569 w(" ~sLen = length(~s),~n",[erl_arg_name(N), erl_arg_name(N)]), 570 [A|pre_marshal(R)]; 571pre_marshal([A|R]) -> 572 [A|pre_marshal(R)]; 573pre_marshal([]) -> []. 574 575marshal_args(As) -> 576 marshal_args(As, [], 0). 577 578marshal_args([#arg{where=erl}|Ps], Margs, Align) -> 579 marshal_args(Ps, Margs, Align); 580marshal_args([#arg{where=c}|Ps], Margs, Align) -> 581 marshal_args(Ps, Margs, Align); 582marshal_args([#arg{in=false}|Ps], Margs, Align) -> 583 marshal_args(Ps, Margs, Align); 584marshal_args([#arg{name=Name, type=Type}|Ps], Margs, Align0) -> 585 {Arg,Align} = marshal_arg(Type,erl_arg_name(Name),Align0), 586 marshal_args(Ps, [Arg|Margs], Align); 587marshal_args([],Margs, Align) -> 588 {args(fun(Str) -> Str end, ",", reverse(Margs)), Align}. 589 590marshal_arg(#type{size=Sz,name=Type,single={tuple,undefined}},Name,A0) -> 591 KeepA = case Sz of 8 -> "0:32,"; _ -> "" end, 592 Str0 = "(size("++Name++")):?GLuint,"++KeepA++"\n" 593 " (<< <<C:?"++Type++ ">> ||" 594 "C <- tuple_to_list("++Name++")>>)/binary", 595 case Sz of 596 4 -> 597 {Str,Align} = align(4,A0,Str0), 598 {Str++",0:((("++integer_to_list(Align div 4)++ 599 "+size("++Name++")) rem 2)*32)",0}; 600 8 -> 601 align(8,A0,Str0) 602 end; 603marshal_arg(#type{size=BSz,name=Type,single={tuple,TSz}},Name,A0) 604 when is_integer(TSz) -> 605 NameId = hd(Name), 606 Names = [[NameId|integer_to_list(Id)] || Id <- lists:seq(1,TSz)], 607 All = args(fun(ElName) -> ElName ++ ":?" ++ Type end, ",", Names), 608 align(BSz,TSz,A0,All); 609 610marshal_arg(#type{size=BSz,name=Type,single={tuple,matrix12}},Name,A0) -> 611 NameId = hd(Name), 612 Ns0 = [[NameId|integer_to_list(Id)] || Id <- lists:seq(1,3)], 613 Ns1 = [[NameId|integer_to_list(Id)] || Id <- lists:seq(4,6)], 614 Ns2 = [[NameId|integer_to_list(Id)] || Id <- lists:seq(7,9)], 615 Ns3 = [[NameId|integer_to_list(Id)] || Id <- lists:seq(10,12)], 616 All = args(fun(ElName) -> ElName ++ ":?" ++ Type end, ",", 617 Ns0 ++ ["0"] ++ Ns1 ++ ["0"] ++ Ns2 ++ ["0"] ++ Ns3 ++ ["1"]), 618 align(BSz,16,A0,All); 619 620marshal_arg(#type{size=Sz,name=Type,base=Base,single=list},Name,A0) 621 when Base =:= float; Base =:= int; Base =:= guard_int -> 622 KeepA = case Sz of 8 -> "0:32,"; _ -> "" end, 623 Str0 = Name++"Len:?GLuint,"++KeepA++"\n" 624 " (<< <<C:?"++Type++">> || C <- "++Name++">>)/binary", 625 {Str,Align} = align(max([Sz,4]),A0,Str0), 626 align_after(Sz,Align,0,1,Name,Str); 627 628marshal_arg(#type{base=guard_int},Name,A0) -> 629 align(4,A0,Name ++ ":?GLuint"); 630 631marshal_arg(#type{size=Sz,name=Type,single=true, 632 by_val=true,ref=undefined},Name,A0) -> 633 align(Sz,A0,Name ++ ":?" ++ Type); 634 635marshal_arg(#type{size=8,name="GLUquadric"=Type},Name,A0) -> 636 align(8,A0,Name ++ ":?" ++ Type); 637 638marshal_arg(#type{base=string,single=true,ref={pointer,1}},Name,A0) -> 639 Str = "(list_to_binary(["++Name++"|[0]]))/binary", % Null terminate 640 align_after(1,A0,1,1,Name,Str); 641 642marshal_arg(#type{base=string,single=list,ref={pointer,2}},Name,A0) -> 643 Str0 = 644 Name++"Len:?GLuint," 645 "(size("++Name ++ "Temp)):?GLuint," 646 "(" ++ Name ++ "Temp)/binary", 647 {Str,A} = align(4,A0,Str0), 648 {Str ++ ",0:((8-((size("++Name++"Temp)+"++ 649 integer_to_list(A) ++") rem 8)) rem 8)", 0}; 650 651marshal_arg(#type{size=Sz,name=Type,single={tuple_list,TSz}},Name,A0) -> 652 NameId = hd(Name), 653 Names = [[NameId|integer_to_list(Id)] || Id <- lists:seq(1,TSz)], 654 TTup = args(fun(ElName) -> ElName end, ",", Names), 655 TBin = args(fun(ElName) -> ElName ++ ":?" ++ Type end, ",", Names), 656 657 KeepA = case Sz of 8 -> "0:32,"; 4 -> "" end, 658 Str0 = Name++"Len:?GLuint,"++KeepA++"\n" 659 " (<< <<"++TBin++">> || {"++TTup++"} <- "++Name++">>)/binary", 660 align(Sz,A0,Str0); 661 662marshal_arg(T=#type{}, Name, Align) -> 663 io:format("{\"~s\", {\"~s\", }}.~n", [get(current_func),lowercase(Name)]), 664 %%?error({unhandled_type, {Name,T}}). 665 w(" Don't know how to marshal this type ~p ~p~n", [T,Name]), 666 align(8,Align,""). 667 668% Make sure that it is aligned before adding it, and update alignment 669align(Size, PreAlign, Str) -> 670 align(Size,1,PreAlign,Str). 671 672align(1,N,A,Str) -> {Str, (A+1*N+0) rem 8}; 673 674align(2,N,A,Str) when (A rem 2) =:= 0 -> {Str, (A+2*N+0) rem 8}; 675align(2,N,A,Str) when (A rem 2) =:= 1 -> {"0:8," ++Str, (A+2*N+1) rem 8}; 676 677align(4,N,A,Str) when (A rem 4) =:= 0 -> {Str, (A+4*N+0) rem 8}; 678align(4,N,A,Str) when (A rem 4) =:= 1 -> {"0:24,"++Str, (A+4*N+3) rem 8}; 679align(4,N,A,Str) when (A rem 4) =:= 2 -> {"0:16,"++Str, (A+4*N+2) rem 8}; 680align(4,N,A,Str) when (A rem 4) =:= 3 -> {"0:8," ++Str, (A+4*N+1) rem 8}; 681 682align(8,_,0,Str) -> {Str, 0}; 683align(8,_,1,Str) -> {"0:56,"++Str, 0}; 684align(8,_,2,Str) -> {"0:48,"++Str, 0}; 685align(8,_,3,Str) -> {"0:40,"++Str, 0}; 686align(8,_,4,Str) -> {"0:32,"++Str, 0}; 687align(8,_,5,Str) -> {"0:24,"++Str, 0}; 688align(8,_,6,Str) -> {"0:16,"++Str, 0}; 689align(8,_,7,Str) -> {"0:8," ++Str, 0}. 690 691align_after(8,0,_Add,_Multiplier,_Name,Str) -> {Str,0}; 692align_after(4,0,Add,Mult,Name,Str) -> 693 Extra = extra_align(Add,Mult), 694 Align = ",0:((("++Name++"Len"++Extra++") rem 2)*32)", 695 {Str ++ Align,0}; 696align_after(4,4,Add,Mult,Name,Str) -> 697 Extra = extra_align(Add,Mult), 698 Align = ",0:(((1+"++Name++"Len"++Extra++") rem 2)*32)", 699 {Str ++ Align,0}; 700align_after(2,A,Add,Mult,Name,Str) when (A rem 2) =:= 0 -> 701 Extra = extra_align(A+Add*2,Mult), 702 Align = ",0:((8-(("++Name++"Len*2"++Extra++") rem 8)) rem 8)", 703 {Str ++ Align,0}; 704align_after(1,A,Add,Mult,Name,Str) -> 705 Extra = extra_align(A+Add,Mult), 706 Align = ",0:((8-(("++Name++"Len"++Extra++") rem 8)) rem 8)", 707 {Str ++ Align,0}; 708align_after(Sz,A,Add,Mult,Name,Str) -> 709 io:format("~p ~p with ~p ~p ~s~n, ~p", [Sz,A,Add,Mult,Name,Str]), 710 ?error(align_error). 711 712extra_align(0,1) -> ""; 713extra_align(0,M) when M > 1 -> "* " ++ integer_to_list(M); 714extra_align(A,1) when A > 0 -> "+ " ++ integer_to_list(A); 715extra_align(A,M) when A > 0,M>1 -> 716 "* " ++ integer_to_list(M) ++ "+ " ++ integer_to_list(A). 717 718%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 719 720have_return_vals(void, Ps) -> 721 lists:any(fun(#arg{in=In, type=#type{base=B}}) -> 722 In =/= true orelse B =:= memory 723 end, Ps); 724have_return_vals(#type{}, _) -> true. 725 726erl_func_name("glu" ++ Name) -> check_name(lowercase(Name)); 727erl_func_name("gl" ++ Name) -> check_name(lowercase(Name)). 728 729erl_arg_name(Name) -> uppercase(Name). 730 731check_name("begin") -> "'begin'"; 732check_name("end") -> "'end'"; 733check_name(Other) -> Other. 734 735doc_name(N="glGetBufferParameteriv", _) -> N; 736doc_name("glEnd"++What, _) -> "glBegin"++What; 737doc_name("glDisable" ++ What, _) -> "glEnable" ++ What; 738doc_name("glPop" ++ What, _) -> "glPush" ++ What; 739doc_name("glGetBooleanv", _) -> "glGet"; 740doc_name("glGetBooleani_v", _) -> "glGet"; 741doc_name("glGetIntegerv", _) -> "glGet"; 742doc_name("glGetIntegeri_v", _) -> "glGet"; 743doc_name("glGetInteger64v", _) -> "glGet"; 744doc_name("glGetInteger64i_v", _) -> "glGet"; 745doc_name("glGetFloatv", _) -> "glGet"; 746doc_name("glGetDoublev", _) -> "glGet"; 747doc_name("glGetFloati_v", _) -> "glGet"; 748doc_name("glGetDoublei_v", _) -> "glGet"; 749doc_name("glUniformMatr" ++ _, _) -> "glUniform"; 750doc_name("glTexSubImage" ++ _, _) -> "glTexSubImage"; 751doc_name("glFramebufferText" ++ _, _) -> "glFramebufferTexture"; 752doc_name("glProgramUniformMatr" ++ _, _) -> "glProgramUniform"; 753doc_name(Name, {has_vector,_,_}) -> 754 strip_hard(reverse(Name)); 755doc_name(Name, _) -> 756 reverse(strip(reverse(Name))). 757 758strip_hard(Rev) -> 759 case strip(Rev) of 760 Rev -> reverse(strip2(Rev)); 761 Other -> reverse(Other) 762 end. 763 764strip("BRA"++R) -> "BRA"++strip(R); 765strip([$v,$b,$u,$N,N|R]) when N > 47, N < 58 ->R; 766strip([$v,$i,$u,$N,N|R]) when N > 47, N < 58 ->R; 767strip([$v,$s,$u,$N,N|R]) when N > 47, N < 58 ->R; 768strip([$v,$b,$N,N|R]) when N > 47, N < 58 -> R; 769strip([$v,$i,$N,N|R]) when N > 47, N < 58 -> R; 770strip([$v,$s,$N,N|R]) when N > 47, N < 58 -> R; 771strip([$v,$d,$N,N|R]) when N > 47, N < 58 -> R; 772strip([$v,$f,$N,N|R]) when N > 47, N < 58 -> R; 773strip([$b,$u,$N,N|R]) when N > 47, N < 58 -> R; 774strip([$v,$b,$I,N|R]) when N > 47, N < 58 -> R; 775strip([$v,$i,$I,N|R]) when N > 47, N < 58 -> R; 776strip([$v,$s,$I,N|R]) when N > 47, N < 58 -> R; 777strip([$v,$d,$I,N|R]) when N > 47, N < 58 -> R; 778strip([$v,$f,$I,N|R]) when N > 47, N < 58 -> R; 779strip([$b,$u,$I,N|R]) when N > 47, N < 58 -> R; 780 781strip([$v,$b,$u,N,$I|R]) when N > 47, N < 58 ->R; 782strip([$v,$i,$u,N,$I|R]) when N > 47, N < 58 ->R; 783strip([$v,$s,$u,N,$I|R]) when N > 47, N < 58 ->R; 784strip([$v,$b,N,$I|R]) when N > 47, N < 58 -> R; 785strip([$v,$i,N,$I|R]) when N > 47, N < 58 -> R; 786strip([$v,$s,N,$I|R]) when N > 47, N < 58 -> R; 787strip([$v,$d,N,$I|R]) when N > 47, N < 58 -> R; 788strip([$v,$f,N,$I|R]) when N > 47, N < 58 -> R; 789 790strip([$v,$b,$u,N|R]) when N > 47, N < 58 ->R; 791strip([$v,$i,$u,N|R]) when N > 47, N < 58 ->R; 792strip([$v,$s,$u,N|R]) when N > 47, N < 58 ->R; 793strip([$v,$b,N|R]) when N > 47, N < 58 -> R; 794strip([$v,$i,N|R]) when N > 47, N < 58 -> R; 795strip([$v,$s,N|R]) when N > 47, N < 58 -> R; 796strip([$v,$d,N|R]) when N > 47, N < 58 -> R; 797strip([$v,$f,N|R]) when N > 47, N < 58 -> R; 798 799strip([$b,$u,N,$I|R]) when N > 47, N < 58 ->R; 800strip([$i,$u,N,$I|R]) when N > 47, N < 58 ->R; 801strip([$s,$u,N,$I|R]) when N > 47, N < 58 ->R; 802strip([$b,N,$I|R]) when N > 47, N < 58 -> R; 803strip([$i,N,$I|R]) when N > 47, N < 58 -> R; 804strip([$s,N,$I|R]) when N > 47, N < 58 -> R; 805strip([$d,N,$I|R]) when N > 47, N < 58 -> R; 806strip([$f,N,$I|R]) when N > 47, N < 58 -> R; 807 808strip([$b,$u,N|R]) when N > 47, N < 58 ->R; 809strip([$i,$u,N|R]) when N > 47, N < 58 ->R; 810strip([$s,$u,N|R]) when N > 47, N < 58 ->R; 811strip([$b,N|R]) when N > 47, N < 58 -> R; 812strip([$i,N|R]) when N > 47, N < 58 -> R; 813strip([$s,N|R]) when N > 47, N < 58 -> R; 814strip([$d,N|R]) when N > 47, N < 58 -> R; 815strip([$f,N|R]) when N > 47, N < 58 -> R; 816 817strip([$v,$b,$u|R]) -> R; 818strip([$v,$i,$u|R]) -> R; 819strip([$v,$s,$u|R]) -> R; 820strip([$v,$b|R]) -> R; 821strip([$v,$i,$I|R]) -> R; 822strip([$v,$i|R]) -> R; 823strip([$v,$s|R]) -> R; 824strip([$v,$d|R]) -> R; 825strip([$v,$f|R]) -> R; 826 827strip(R = "delban" ++ _) -> R; 828strip([$d,$e|R]) -> [$e|R]; 829strip([$f,$e|R]) -> [$e|R]; 830strip([$i,$e|R]) -> [$e|R]; 831strip([$d,$x|R]) -> [$x|R]; 832strip([$f,$x|R]) -> [$x|R]; 833strip([$d,$d|R]) -> [$d|R]; 834strip([$f,$d|R]) -> [$d|R]; 835strip([$i,$l|R]) -> [$l|R]; 836strip([$f,$l|R]) -> [$l|R]; 837strip([$i,$r|R]) -> [$r|R]; 838strip([$f,$r|R]) -> [$r|R]; 839strip([$i,$g|R]) -> [$g|R]; 840strip([$f,$g|R]) -> [$g|R]; 841strip([$i,$n|R]) -> [$n|R]; 842strip([$f,$n|R]) -> [$n|R]; 843strip([$d,$n|R]) -> [$n|R]; 844 845%% strip([$D,$3|R]) -> R; 846%% strip([$D,$2|R]) -> R; 847%% strip([$D,$1|R]) -> R; 848 849strip([$I|R]) -> R; 850strip([$L|R]) -> R; 851strip([$v,R]) -> R; 852strip([N|R]) when N > 47, N < 58 -> R; 853strip([_|R="tceRlg"]) -> R; 854strip([_|R="thgiLlg"]) -> R; 855strip(R) -> R. 856 857strip2([$b,$u|R]) -> R; 858strip2([$i,$u|R]) -> R; 859strip2([$s,$u|R]) -> R; 860strip2([$b|R]) -> R; 861strip2([$i|R]) -> R; 862strip2([$s|R]) -> R; 863strip2([$d|R]) -> R; 864strip2([$f|R]) -> R; 865strip2(R) -> R. 866 867gen_debug(GL, GLU) -> 868 open_write("../src/gen/gl_debug.hrl"), 869 erl_copyright(), 870 w("%% This file is generated DO NOT EDIT~n~n", []), 871 w("gldebug_table() ->~n[~n", []), 872 [printd(F,gl) || F <- GL], 873 [printd(F,glu) || F <- GLU], 874 w(" {-1, {mod, func, -1}}~n",[]), 875 w("].~n~n", []), 876 close(). 877 878printd([F|R],Mod) when is_list(F) -> 879 printd(F,Mod), 880 printd(R,Mod); 881printd([],_) -> ok; 882printd(F,Mod) -> 883 case get(F) of 884 #func{alt={vector,_VecPos,_Vec}} -> ok; 885 #func{where=erl} -> ok; 886 #func{id=Id, name=Method} -> 887 w(" {~p, {~s, ~s, 0}},~n", [Id, Mod, erl_func_name(Method)]); 888 _Other -> 889 io:format("F= ~p => ~p~n", [F, _Other]) 890 end. 891