diff options
380 files changed, 7968 insertions, 21139 deletions
diff --git a/bootstrap/lib/compiler/ebin/beam_asm.beam b/bootstrap/lib/compiler/ebin/beam_asm.beam Binary files differindex 936e6886a6..9f25d31bb2 100644 --- a/bootstrap/lib/compiler/ebin/beam_asm.beam +++ b/bootstrap/lib/compiler/ebin/beam_asm.beam diff --git a/bootstrap/lib/compiler/ebin/beam_utils.beam b/bootstrap/lib/compiler/ebin/beam_utils.beam Binary files differindex 0f44d8e4d7..4d475cd899 100644 --- a/bootstrap/lib/compiler/ebin/beam_utils.beam +++ b/bootstrap/lib/compiler/ebin/beam_utils.beam diff --git a/bootstrap/lib/compiler/ebin/compile.beam b/bootstrap/lib/compiler/ebin/compile.beam Binary files differindex a92341690d..d2f4ed83bb 100644 --- a/bootstrap/lib/compiler/ebin/compile.beam +++ b/bootstrap/lib/compiler/ebin/compile.beam diff --git a/bootstrap/lib/compiler/ebin/core_pp.beam b/bootstrap/lib/compiler/ebin/core_pp.beam Binary files differindex 8f4137db70..f0573bd200 100644 --- a/bootstrap/lib/compiler/ebin/core_pp.beam +++ b/bootstrap/lib/compiler/ebin/core_pp.beam diff --git a/bootstrap/lib/compiler/ebin/core_scan.beam b/bootstrap/lib/compiler/ebin/core_scan.beam Binary files differindex e9f74a1d1c..398c538178 100644 --- a/bootstrap/lib/compiler/ebin/core_scan.beam +++ b/bootstrap/lib/compiler/ebin/core_scan.beam diff --git a/bootstrap/lib/compiler/ebin/v3_codegen.beam b/bootstrap/lib/compiler/ebin/v3_codegen.beam Binary files differindex c6c1593790..a1047fb87f 100644 --- a/bootstrap/lib/compiler/ebin/v3_codegen.beam +++ b/bootstrap/lib/compiler/ebin/v3_codegen.beam diff --git a/bootstrap/lib/compiler/ebin/v3_kernel.beam b/bootstrap/lib/compiler/ebin/v3_kernel.beam Binary files differindex 6143af9050..189a8c07b2 100644 --- a/bootstrap/lib/compiler/ebin/v3_kernel.beam +++ b/bootstrap/lib/compiler/ebin/v3_kernel.beam diff --git a/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam b/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam Binary files differindex 6b127e86d0..e1b8c58c8f 100644 --- a/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam +++ b/bootstrap/lib/compiler/ebin/v3_kernel_pp.beam diff --git a/bootstrap/lib/kernel/ebin/disk_log.beam b/bootstrap/lib/kernel/ebin/disk_log.beam Binary files differindex 4dc0ef29f2..e8a6acd235 100644 --- a/bootstrap/lib/kernel/ebin/disk_log.beam +++ b/bootstrap/lib/kernel/ebin/disk_log.beam diff --git a/bootstrap/lib/kernel/ebin/disk_log_1.beam b/bootstrap/lib/kernel/ebin/disk_log_1.beam Binary files differindex 420a4e818b..bcd3c548a5 100644 --- a/bootstrap/lib/kernel/ebin/disk_log_1.beam +++ b/bootstrap/lib/kernel/ebin/disk_log_1.beam diff --git a/bootstrap/lib/kernel/ebin/erl_boot_server.beam b/bootstrap/lib/kernel/ebin/erl_boot_server.beam Binary files differindex ef3fe6fdea..d9de814e60 100644 --- a/bootstrap/lib/kernel/ebin/erl_boot_server.beam +++ b/bootstrap/lib/kernel/ebin/erl_boot_server.beam diff --git a/bootstrap/lib/kernel/ebin/erl_reply.beam b/bootstrap/lib/kernel/ebin/erl_reply.beam Binary files differindex 6266aaa37c..d9dee00b6a 100644 --- a/bootstrap/lib/kernel/ebin/erl_reply.beam +++ b/bootstrap/lib/kernel/ebin/erl_reply.beam diff --git a/bootstrap/lib/kernel/ebin/error_logger.beam b/bootstrap/lib/kernel/ebin/error_logger.beam Binary files differindex 4129e6af6e..2415215395 100644 --- a/bootstrap/lib/kernel/ebin/error_logger.beam +++ b/bootstrap/lib/kernel/ebin/error_logger.beam diff --git a/bootstrap/lib/kernel/ebin/erts_debug.beam b/bootstrap/lib/kernel/ebin/erts_debug.beam Binary files differindex a47aec4a2e..75064d3452 100644 --- a/bootstrap/lib/kernel/ebin/erts_debug.beam +++ b/bootstrap/lib/kernel/ebin/erts_debug.beam diff --git a/bootstrap/lib/kernel/ebin/group.beam b/bootstrap/lib/kernel/ebin/group.beam Binary files differindex 57851fcb6e..5c5f3bfa73 100644 --- a/bootstrap/lib/kernel/ebin/group.beam +++ b/bootstrap/lib/kernel/ebin/group.beam diff --git a/bootstrap/lib/kernel/ebin/inet_config.beam b/bootstrap/lib/kernel/ebin/inet_config.beam Binary files differindex ab06763c7d..6e02c48609 100644 --- a/bootstrap/lib/kernel/ebin/inet_config.beam +++ b/bootstrap/lib/kernel/ebin/inet_config.beam diff --git a/bootstrap/lib/kernel/ebin/inet_dns.beam b/bootstrap/lib/kernel/ebin/inet_dns.beam Binary files differindex cebe72a7f0..8935d52e52 100644 --- a/bootstrap/lib/kernel/ebin/inet_dns.beam +++ b/bootstrap/lib/kernel/ebin/inet_dns.beam diff --git a/bootstrap/lib/kernel/ebin/inet_parse.beam b/bootstrap/lib/kernel/ebin/inet_parse.beam Binary files differindex a5b4d7611f..cd27ee7265 100644 --- a/bootstrap/lib/kernel/ebin/inet_parse.beam +++ b/bootstrap/lib/kernel/ebin/inet_parse.beam diff --git a/bootstrap/lib/kernel/ebin/inet_res.beam b/bootstrap/lib/kernel/ebin/inet_res.beam Binary files differindex 74b3a11f59..f203f7c08a 100644 --- a/bootstrap/lib/kernel/ebin/inet_res.beam +++ b/bootstrap/lib/kernel/ebin/inet_res.beam diff --git a/bootstrap/lib/kernel/ebin/kernel.app b/bootstrap/lib/kernel/ebin/kernel.app index b888d914e8..244fad678f 100644 --- a/bootstrap/lib/kernel/ebin/kernel.app +++ b/bootstrap/lib/kernel/ebin/kernel.app @@ -120,6 +120,6 @@ {applications, []}, {env, [{error_logger, tty}]}, {mod, {kernel, []}}, - {runtime_dependencies, ["erts-9.1", "stdlib-3.0", "sasl-3.0"]} + {runtime_dependencies, ["erts-9.1", "stdlib-3.4", "sasl-3.0"]} ] }. diff --git a/bootstrap/lib/kernel/ebin/os.beam b/bootstrap/lib/kernel/ebin/os.beam Binary files differindex 0bc6403871..cedf7bf49e 100644 --- a/bootstrap/lib/kernel/ebin/os.beam +++ b/bootstrap/lib/kernel/ebin/os.beam diff --git a/bootstrap/lib/stdlib/ebin/beam_lib.beam b/bootstrap/lib/stdlib/ebin/beam_lib.beam Binary files differindex 8255fc6f82..39d80d9e36 100644 --- a/bootstrap/lib/stdlib/ebin/beam_lib.beam +++ b/bootstrap/lib/stdlib/ebin/beam_lib.beam diff --git a/bootstrap/lib/stdlib/ebin/dets_utils.beam b/bootstrap/lib/stdlib/ebin/dets_utils.beam Binary files differindex 6840be1e57..d858a59f8b 100644 --- a/bootstrap/lib/stdlib/ebin/dets_utils.beam +++ b/bootstrap/lib/stdlib/ebin/dets_utils.beam diff --git a/bootstrap/lib/stdlib/ebin/edlin.beam b/bootstrap/lib/stdlib/ebin/edlin.beam Binary files differindex b6f5e62671..1cabe095b3 100644 --- a/bootstrap/lib/stdlib/ebin/edlin.beam +++ b/bootstrap/lib/stdlib/ebin/edlin.beam diff --git a/bootstrap/lib/stdlib/ebin/epp.beam b/bootstrap/lib/stdlib/ebin/epp.beam Binary files differindex 36c2b2219e..22c0978854 100644 --- a/bootstrap/lib/stdlib/ebin/epp.beam +++ b/bootstrap/lib/stdlib/ebin/epp.beam diff --git a/bootstrap/lib/stdlib/ebin/erl_lint.beam b/bootstrap/lib/stdlib/ebin/erl_lint.beam Binary files differindex dc4c689263..d018b33132 100644 --- a/bootstrap/lib/stdlib/ebin/erl_lint.beam +++ b/bootstrap/lib/stdlib/ebin/erl_lint.beam diff --git a/bootstrap/lib/stdlib/ebin/erl_pp.beam b/bootstrap/lib/stdlib/ebin/erl_pp.beam Binary files differindex e77e0f9136..5c5a46d8bb 100644 --- a/bootstrap/lib/stdlib/ebin/erl_pp.beam +++ b/bootstrap/lib/stdlib/ebin/erl_pp.beam diff --git a/bootstrap/lib/stdlib/ebin/erl_scan.beam b/bootstrap/lib/stdlib/ebin/erl_scan.beam Binary files differindex 86307bc790..d36202515a 100644 --- a/bootstrap/lib/stdlib/ebin/erl_scan.beam +++ b/bootstrap/lib/stdlib/ebin/erl_scan.beam diff --git a/bootstrap/lib/stdlib/ebin/escript.beam b/bootstrap/lib/stdlib/ebin/escript.beam Binary files differindex 30dea42a21..10982c84ce 100644 --- a/bootstrap/lib/stdlib/ebin/escript.beam +++ b/bootstrap/lib/stdlib/ebin/escript.beam diff --git a/bootstrap/lib/stdlib/ebin/ets.beam b/bootstrap/lib/stdlib/ebin/ets.beam Binary files differindex 40be147afa..c2b113b79e 100644 --- a/bootstrap/lib/stdlib/ebin/ets.beam +++ b/bootstrap/lib/stdlib/ebin/ets.beam diff --git a/bootstrap/lib/stdlib/ebin/file_sorter.beam b/bootstrap/lib/stdlib/ebin/file_sorter.beam Binary files differindex f2a1fd74d0..74c7c5ce01 100644 --- a/bootstrap/lib/stdlib/ebin/file_sorter.beam +++ b/bootstrap/lib/stdlib/ebin/file_sorter.beam diff --git a/bootstrap/lib/stdlib/ebin/filename.beam b/bootstrap/lib/stdlib/ebin/filename.beam Binary files differindex a94acbb852..13f1c8029e 100644 --- a/bootstrap/lib/stdlib/ebin/filename.beam +++ b/bootstrap/lib/stdlib/ebin/filename.beam diff --git a/bootstrap/lib/stdlib/ebin/io_lib_format.beam b/bootstrap/lib/stdlib/ebin/io_lib_format.beam Binary files differindex e85995c1de..c02da85965 100644 --- a/bootstrap/lib/stdlib/ebin/io_lib_format.beam +++ b/bootstrap/lib/stdlib/ebin/io_lib_format.beam diff --git a/bootstrap/lib/stdlib/ebin/lib.beam b/bootstrap/lib/stdlib/ebin/lib.beam Binary files differindex 6ad7dff7da..98a7f91ab8 100644 --- a/bootstrap/lib/stdlib/ebin/lib.beam +++ b/bootstrap/lib/stdlib/ebin/lib.beam diff --git a/bootstrap/lib/stdlib/ebin/otp_internal.beam b/bootstrap/lib/stdlib/ebin/otp_internal.beam Binary files differindex 912dfba644..166574e0f6 100644 --- a/bootstrap/lib/stdlib/ebin/otp_internal.beam +++ b/bootstrap/lib/stdlib/ebin/otp_internal.beam diff --git a/bootstrap/lib/stdlib/ebin/qlc.beam b/bootstrap/lib/stdlib/ebin/qlc.beam Binary files differindex 4a315e8d42..592f7b4740 100644 --- a/bootstrap/lib/stdlib/ebin/qlc.beam +++ b/bootstrap/lib/stdlib/ebin/qlc.beam diff --git a/bootstrap/lib/stdlib/ebin/qlc_pt.beam b/bootstrap/lib/stdlib/ebin/qlc_pt.beam Binary files differindex ac343d8abd..1a7d678227 100644 --- a/bootstrap/lib/stdlib/ebin/qlc_pt.beam +++ b/bootstrap/lib/stdlib/ebin/qlc_pt.beam diff --git a/bootstrap/lib/stdlib/ebin/shell.beam b/bootstrap/lib/stdlib/ebin/shell.beam Binary files differindex a0e2b73018..fab94d5509 100644 --- a/bootstrap/lib/stdlib/ebin/shell.beam +++ b/bootstrap/lib/stdlib/ebin/shell.beam diff --git a/bootstrap/lib/stdlib/ebin/slave.beam b/bootstrap/lib/stdlib/ebin/slave.beam Binary files differindex 299c24448d..abab0acf33 100644 --- a/bootstrap/lib/stdlib/ebin/slave.beam +++ b/bootstrap/lib/stdlib/ebin/slave.beam diff --git a/bootstrap/lib/stdlib/ebin/sofs.beam b/bootstrap/lib/stdlib/ebin/sofs.beam Binary files differindex a2cc62d4af..aa8ed3d99c 100644 --- a/bootstrap/lib/stdlib/ebin/sofs.beam +++ b/bootstrap/lib/stdlib/ebin/sofs.beam diff --git a/bootstrap/lib/stdlib/ebin/string.beam b/bootstrap/lib/stdlib/ebin/string.beam Binary files differindex a281027902..8bb21b24f2 100644 --- a/bootstrap/lib/stdlib/ebin/string.beam +++ b/bootstrap/lib/stdlib/ebin/string.beam diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 48aac15827..06f568c832 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -440,6 +440,16 @@ Z = erlang:adler32_combine(X,Y,iolist_size(Data2)).</code> <seealso marker="#binary_to_atom/2"><c>binary_to_atom/2</c></seealso>, but the atom must exist.</p> <p>Failure: <c>badarg</c> if the atom does not exist.</p> + <note> + <p>Note that the compiler may optimize away atoms. For + example, the compiler will rewrite + <c>atom_to_list(some_atom)</c> to <c>"some_atom"</c>. If + that expression is the only mention of the atom + <c>some_atom</c> in the containing module, the atom will not + be created when the module is loaded, and a subsequent call + to <c>binary_to_existing_atom(<<"some_atom">>, utf8)</c> + will fail.</p> + </note> </desc> </func> @@ -2621,6 +2631,15 @@ os_prompt%</pre> but only if there already exists such atom.</p> <p>Failure: <c>badarg</c> if there does not already exist an atom whose text representation is <c><anno>String</anno></c>.</p> + <note> + <p>Note that the compiler may optimize away atoms. For + example, the compiler will rewrite + <c>atom_to_list(some_atom)</c> to <c>"some_atom"</c>. If + that expression is the only mention of the atom + <c>some_atom</c> in the containing module, the atom will not + be created when the module is loaded, and a subsequent call + to <c>list_to_existing_atom("some_atom")</c> will fail.</p> + </note> </desc> </func> diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index 10b963a4e8..e89f2680ea 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -31,6 +31,184 @@ </header> <p>This document describes the changes made to the ERTS application.</p> +<section><title>Erts 9.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Changed <c>erlang:apply/2</c> to raise a <c>badarg</c> + exception if the second argument is not a proper list. + Previous behavior was a misleading <c>undef</c> + exception.</p> + <p> + Own Id: OTP-14490 Aux Id: ERL-432 </p> + </item> + <item> + <p>On macOS, <c>crypto</c> would crash if <c>observer</c> + had been started before <c>crypto</c>. On the beta for + macOS 10.13 (High Sierra), <c>crypto</c> would crash. + Both of those bugs have been fixed.</p> + <p> + Own Id: OTP-14499 Aux Id: ERL-251 ERL-439 </p> + </item> + <item> + <p> + Fixed bug in enif_whereis_pid/port that could cause heap + corruption in rare cases.</p> + <p> + Own Id: OTP-14523</p> + </item> + <item> + <p> + Fix so that trace messages generated when in a dirty nif + are flushed correctly when the dirty nif is done + executing.</p> + <p> + Own Id: OTP-14538</p> + </item> + <item> + <p> + Fix escape code handling when using ANSI color codes in + the shell.</p> + <p> + Own Id: OTP-14549 Aux Id: PR1536 </p> + </item> + <item> + <p> + Upgraded the ERTS internal PCRE library from version 8.40 + to version 8.41. See <url + href="http://pcre.org/original/changelog.txt">http://pcre.org/original/changelog.txt</url> + for information about changes made to PCRE. This library + implements major parts of the <seealso + marker="stdlib:re"><c>re</c></seealso> regular + expressions module.</p> + <p> + Own Id: OTP-14574</p> + </item> + <item> + <p> + Fixed a bug causing <c>statistics(runtime)</c> to produce + negative values and a bug in + <c>statistics(wall_clock)</c> causing it to produce + values one second too long.</p> + <p> + <c>statistics(runtime)</c> now also use + <c>getrusage()</c> as source when available preventing + the returned value from wrapping as frequent as before.</p> + <p> + Own Id: OTP-14597 Aux Id: ERL-465 </p> + </item> + <item> + <p> + Fixed small memory leak that could occur when sending to + a terminating port.</p> + <p> + Own Id: OTP-14609</p> + </item> + <item> + <p> + Fix bug causing VM crash when a module with + <c>-on_load</c> directive is loaded while + <c>erlang:trace(on_load, ...)</c> is enabled.</p> + <p> + Own Id: OTP-14612</p> + </item> + <item> + <p>A warning that the compiler may optimize away atoms + have been added to the documentation of + <c>list_to_existing_atom/1</c> and + <c>binary_to_existing_atom/2</c>.</p> + <p> + Own Id: OTP-14614 Aux Id: ERL-453 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>Lock counting can now be fully toggled at runtime in + the lock counting emulator (<c>-emu_type lcnt</c>). + Everything is enabled by default to match the old + behavior, but specific categories can be toggled at will + with minimal runtime overhead when disabled. Refer to the + documentation on <c>lcnt:rt_mask/1</c> for details.</p> + <p> + Own Id: OTP-13170</p> + </item> + <item> + <p>The <c>zlib</c> module has been refactored and all its + operations will now yield appropriately, allowing them to + be used freely in concurrent applications.</p> <p>The + following functions have been deprecated, but will not + produce compiler warnings until OTP 21: + <c>zlib:adler32</c>, <c>zlib:crc32</c>, + <c>zlib:inflateChunk</c>, <c>zlib:getBufSize</c>, + <c>zlib:setBufSize</c>.</p> <p>The behavior of throwing + an error when a dictionary is required for decompression + has also been deprecated. Refer to the documentation on + <c>inflateSetDictionary/2</c> for details.</p> + <p> + Own Id: OTP-14185</p> + </item> + <item> + <p><c>lcnt:collect</c> and <c>lcnt:clear</c> will no + longer block all other threads in the runtime system.</p> + <p> + Own Id: OTP-14412</p> + </item> + <item> + <p>Add <c>erlang:iolist_to_iovec/1</c>, which converts an + iolist() to an erlang:iovec(), which suitable for use + with <c>enif_inspect_iovec</c>.</p> + <p> + Own Id: OTP-14520</p> + </item> + <item> + <p>When provided with bad arguments, the <c>zlib</c> + module will now raise named exceptions instead of just + <c>badarg</c>. For example, <c>not_initialized</c> when + using <c>zlib:inflate/2</c> with an uninitialized + stream.</p> + <p> + Own Id: OTP-14527</p> + </item> + <item> + <p> + <c>erlang:halt/2</c> allows any Unicode string as slogan + for the crash dump.</p> + <p> + Own Id: OTP-14553</p> + </item> + <item> + <p>Add new nif API functions for managing an I/O Queue. + The added functions are:</p> <list type="bulleted"> + <item><seealso marker="erl_nif#enif_ioq_create"> + <c>enif_ioq_create()</c></seealso></item> <item><seealso + marker="erl_nif#enif_ioq_destroy"> + <c>enif_ioq_destroy()</c></seealso></item> <item><seealso + marker="erl_nif#enif_ioq_enq_binary"> + <c>enif_ioq_enq_binary()</c></seealso></item> + <item><seealso marker="erl_nif#enif_ioq_enqv"> + <c>enif_ioq_enqv()</c></seealso></item> <item><seealso + marker="erl_nif#enif_ioq_deq"> + <c>enif_ioq_deq()</c></seealso></item> <item><seealso + marker="erl_nif#enif_ioq_peek"> + <c>enif_ioq_peek()</c></seealso></item> <item><seealso + marker="erl_nif#enif_inspect_iovec"> + <c>enif_inspect_iovec()</c></seealso></item> + <item><seealso marker="erl_nif#enif_free_iovec"> + <c>enif_free_iovec()</c></seealso></item> </list> + <p> + Own Id: OTP-14598</p> + </item> + </list> + </section> + +</section> + <section><title>Erts 9.0.5</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/erts/emulator/beam/arith_instrs.tab b/erts/emulator/beam/arith_instrs.tab index 7c9cd47e28..3db19df3c4 100644 --- a/erts/emulator/beam/arith_instrs.tab +++ b/erts/emulator/beam/arith_instrs.tab @@ -51,8 +51,7 @@ plus.fetch(Op1, Op2) { plus.execute(Fail, Live, Dst) { if (ERTS_LIKELY(is_both_small(PlusOp1, PlusOp2))) { Sint i = signed_val(PlusOp1) + signed_val(PlusOp2); - ASSERT(MY_IS_SSMALL(i) == IS_SSMALL(i)); - if (ERTS_LIKELY(MY_IS_SSMALL(i))) { + if (ERTS_LIKELY(IS_SSMALL(i))) { $Dst = make_small(i); $NEXT0(); } @@ -74,8 +73,7 @@ minus.fetch(Op1, Op2) { minus.execute(Fail, Live, Dst) { if (ERTS_LIKELY(is_both_small(MinusOp1, MinusOp2))) { Sint i = signed_val(MinusOp1) - signed_val(MinusOp2); - ASSERT(MY_IS_SSMALL(i) == IS_SSMALL(i)); - if (ERTS_LIKELY(MY_IS_SSMALL(i))) { + if (ERTS_LIKELY(IS_SSMALL(i))) { $Dst = make_small(i); $NEXT0(); } @@ -100,8 +98,7 @@ increment.execute(IncrementVal, Live, Dst) { increment_val = $IncrementVal; if (ERTS_LIKELY(is_small(increment_reg_val))) { Sint i = signed_val(increment_reg_val) + increment_val; - ASSERT(MY_IS_SSMALL(i) == IS_SSMALL(i)); - if (ERTS_LIKELY(MY_IS_SSMALL(i))) { + if (ERTS_LIKELY(IS_SSMALL(i))) { $Dst = make_small(i); $NEXT0(); } @@ -142,7 +139,7 @@ i_int_div(Fail, Live, Op1, Op2, Dst) { $BIF_ERROR_ARITY_2($Fail, BIF_intdiv_2, op1, op2); } else if (ERTS_LIKELY(is_both_small(op1, op2))) { Sint ires = signed_val(op1) / signed_val(op2); - if (ERTS_LIKELY(MY_IS_SSMALL(ires))) { + if (ERTS_LIKELY(IS_SSMALL(ires))) { $Dst = make_small(ires); $NEXT0(); } diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index 7f8dc42aca..e48415ecc4 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -259,7 +259,7 @@ struct m { Binary* code; Eterm module; Module* modp; - Uint exception; + Eterm exception; }; static Eterm staging_epilogue(Process* c_p, int, Eterm res, int, struct m*, int, int); @@ -278,7 +278,7 @@ exception_list(Process* p, Eterm tag, struct m* mp, Sint exceptions) Eterm res = NIL; while (exceptions > 0) { - if (mp->exception) { + if (is_value(mp->exception)) { res = CONS(hp, mp->module, res); hp += 2; exceptions--; @@ -379,9 +379,9 @@ finish_loading_1(BIF_ALIST_1) exceptions = 0; for (i = 0; i < n; i++) { - p[i].exception = 0; + p[i].exception = THE_NON_VALUE; if (p[i].modp->seen) { - p[i].exception = 1; + p[i].exception = am_duplicated; exceptions++; } p[i].modp->seen = 1; @@ -415,9 +415,9 @@ finish_loading_1(BIF_ALIST_1) exceptions = 0; for (i = 0; i < n; i++) { - p[i].exception = 0; + p[i].exception = THE_NON_VALUE; if (p[i].modp->curr.code_hdr && p[i].modp->old.code_hdr) { - p[i].exception = 1; + p[i].exception = am_not_purged; exceptions++; } } @@ -438,7 +438,7 @@ finish_loading_1(BIF_ALIST_1) retval = erts_finish_loading(p[i].code, BIF_P, 0, &mod); ASSERT(retval == NIL || retval == am_on_load); if (retval == am_on_load) { - p[i].exception = 1; + p[i].exception = am_on_load; exceptions++; } } @@ -469,7 +469,8 @@ staging_epilogue(Process* c_p, int commit, Eterm res, int is_blocking, erts_commit_staging_code_ix(); for (i=0; i < nmods; i++) { - if (mods[i].modp->curr.code_hdr) { + if (mods[i].modp->curr.code_hdr + && mods[i].exception != am_on_load) { set_default_trace_pattern(mods[i].module); } #ifdef HIPE @@ -686,6 +687,7 @@ BIF_RETTYPE delete_module_1(BIF_ALIST_1) Eterm retval; mod.module = BIF_ARG_1; mod.modp = modp; + mod.exception = THE_NON_VALUE; retval = staging_epilogue(BIF_P, success, res, is_blocking, &mod, 1, 0); return retval; } diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c index 4e91bfffe8..7819e9907d 100644 --- a/erts/emulator/beam/beam_debug.c +++ b/erts/emulator/beam/beam_debug.c @@ -629,13 +629,20 @@ print_op(fmtfn_t to, void *to_arg, int op, int size, BeamInstr* addr) unpacked = ap; ap = addr + size; + + /* + * In the code below, never use ap[-1], ap[-2], ... + * (will not work if the arguments have been packed). + * + * Instead use unpacked[-1], unpacked[-2], ... + */ switch (op) { case op_i_select_val_lins_xfI: case op_i_select_val_lins_yfI: case op_i_select_val_bins_xfI: case op_i_select_val_bins_yfI: { - int n = ap[-1]; + int n = unpacked[-1]; int ix = n; Sint32* jump_tab = (Sint32 *)(ap + n); @@ -656,7 +663,7 @@ print_op(fmtfn_t to, void *to_arg, int op, int size, BeamInstr* addr) case op_i_select_tuple_arity_xfI: case op_i_select_tuple_arity_yfI: { - int n = ap[-1]; + int n = unpacked[-1]; int ix = n - 1; /* without sentinel */ Sint32* jump_tab = (Sint32 *)(ap + n); @@ -698,7 +705,7 @@ print_op(fmtfn_t to, void *to_arg, int op, int size, BeamInstr* addr) case op_i_jump_on_val_xfIW: case op_i_jump_on_val_yfIW: { - int n = ap[-2]; + int n = unpacked[-2]; Sint32* jump_tab = (Sint32 *) ap; size += (n+1) / 2; @@ -712,7 +719,7 @@ print_op(fmtfn_t to, void *to_arg, int op, int size, BeamInstr* addr) case op_i_jump_on_val_zero_xfI: case op_i_jump_on_val_zero_yfI: { - int n = ap[-1]; + int n = unpacked[-1]; Sint32* jump_tab = (Sint32 *) ap; size += (n+1) / 2; diff --git a/erts/emulator/beam/big.h b/erts/emulator/beam/big.h index 48efce20e7..7556205063 100644 --- a/erts/emulator/beam/big.h +++ b/erts/emulator/beam/big.h @@ -70,7 +70,20 @@ typedef Uint dsize_t; /* Vector size type */ /* Check for small */ #define IS_USMALL(sgn,x) ((sgn) ? ((x) <= MAX_SMALL+1) : ((x) <= MAX_SMALL)) -#define IS_SSMALL(x) (((x) >= MIN_SMALL) && ((x) <= MAX_SMALL)) + +/* + * It seems that both clang and gcc will generate sub-optimal code + * for the more obvious way to write the range check: + * + * #define IS_SSMALL(x) (((x) >= MIN_SMALL) && ((x) <= MAX_SMALL)) + * + * Note that IS_SSMALL() may be used in the 32-bit emulator with + * a Uint64 argument. Therefore, we must test the size of the argument + * to ensure that the cast does not discard the high-order 32 bits. + */ +#define _IS_SSMALL32(x) (((Uint32) ((((x)) >> (SMALL_BITS-1)) + 1)) < 2) +#define _IS_SSMALL64(x) (((Uint64) ((((x)) >> (SMALL_BITS-1)) + 1)) < 2) +#define IS_SSMALL(x) (sizeof(x) == sizeof(Uint32) ? _IS_SSMALL32(x) : _IS_SSMALL64(x)) /* The heap size needed for a bignum */ #define BIG_NEED_SIZE(x) ((x) + 1) diff --git a/erts/emulator/beam/erl_arith.c b/erts/emulator/beam/erl_arith.c index f2a3e411ec..b6625db0d3 100644 --- a/erts/emulator/beam/erl_arith.c +++ b/erts/emulator/beam/erl_arith.c @@ -114,7 +114,7 @@ BIF_RETTYPE intdiv_2(BIF_ALIST_2) } if (is_both_small(BIF_ARG_1,BIF_ARG_2)){ Sint ires = signed_val(BIF_ARG_1) / signed_val(BIF_ARG_2); - if (MY_IS_SSMALL(ires)) + if (IS_SSMALL(ires)) BIF_RET(make_small(ires)); } BIF_RET(erts_int_div(BIF_P, BIF_ARG_1, BIF_ARG_2)); @@ -340,8 +340,7 @@ erts_mixed_plus(Process* p, Eterm arg1, Eterm arg2) switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): ires = signed_val(arg1) + signed_val(arg2); - ASSERT(MY_IS_SSMALL(ires) == IS_SSMALL(ires)); - if (MY_IS_SSMALL(ires)) { + if (IS_SSMALL(ires)) { return make_small(ires); } else { hp = HAlloc(p, 2); @@ -486,8 +485,7 @@ erts_mixed_minus(Process* p, Eterm arg1, Eterm arg2) switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): ires = signed_val(arg1) - signed_val(arg2); - ASSERT(MY_IS_SSMALL(ires) == IS_SSMALL(ires)); - if (MY_IS_SSMALL(ires)) { + if (IS_SSMALL(ires)) { return make_small(ires); } else { hp = HAlloc(p, 2); @@ -1181,8 +1179,7 @@ erts_gc_mixed_plus(Process* p, Eterm* reg, Uint live) switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): ires = signed_val(arg1) + signed_val(arg2); - ASSERT(MY_IS_SSMALL(ires) == IS_SSMALL(ires)); - if (MY_IS_SSMALL(ires)) { + if (IS_SSMALL(ires)) { return make_small(ires); } else { if (ERTS_NEED_GC(p, 2)) { @@ -1349,8 +1346,7 @@ erts_gc_mixed_minus(Process* p, Eterm* reg, Uint live) switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) { case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE): ires = signed_val(arg1) - signed_val(arg2); - ASSERT(MY_IS_SSMALL(ires) == IS_SSMALL(ires)); - if (MY_IS_SSMALL(ires)) { + if (IS_SSMALL(ires)) { return make_small(ires); } else { if (ERTS_NEED_GC(p, 2)) { diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index 8344c164fa..97a1ca915f 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -337,7 +337,7 @@ erts_heap_sizes(Process* p) for (i = num_heap_sizes-1; i >= 0; i--) { n += 2; - if (!MY_IS_SSMALL(heap_sizes[i])) { + if (!IS_SSMALL(heap_sizes[i])) { big += BIG_UINT_HEAP_SIZE; } } @@ -352,7 +352,7 @@ erts_heap_sizes(Process* p) Eterm num; Sint sz = heap_sizes[i]; - if (MY_IS_SSMALL(sz)) { + if (IS_SSMALL(sz)) { num = make_small(sz); } else { num = uint_to_big(sz, bigp); diff --git a/erts/emulator/beam/erl_io_queue.c b/erts/emulator/beam/erl_io_queue.c index a01b676d39..190ba6bbb9 100644 --- a/erts/emulator/beam/erl_io_queue.c +++ b/erts/emulator/beam/erl_io_queue.c @@ -973,9 +973,10 @@ static int iol2v_append_binary(iol2v_state_t *state, Eterm bin_term) { UWord binary_size; Uint byte_offset, bit_offset, bit_size; + byte *binary_data; + Eterm *parent_header; Eterm parent_binary; - byte *binary_data; ASSERT(state->bytereds_available > state->bytereds_spent); @@ -1001,14 +1002,14 @@ static int iol2v_append_binary(iol2v_state_t *state, Eterm bin_term) { erts_emasculate_writable_binary(pb); } - binary_data = pb->bytes; + binary_data = &((byte*)pb->bytes)[byte_offset]; } else { ErlHeapBin *hb = (ErlHeapBin*)parent_header; ASSERT(thing_subtag(*parent_header) == HEAP_BINARY_SUBTAG); ASSERT(is_bin_small); - binary_data = &((unsigned char*)&hb->data)[byte_offset]; + binary_data = &((byte*)&hb->data)[byte_offset]; } if (!is_bin_small && (state->acc_size == 0 || !is_acc_small)) { diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 938dd1b9ac..61fdf86a56 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -8432,11 +8432,13 @@ erts_start_schedulers(void) erts_atomic_init_nob(&runq_supervisor_sleeping, 0); if (0 != ethr_event_init(&runq_supervision_event)) erts_exit(ERTS_ERROR_EXIT, "Failed to create run-queue supervision event\n"); - if (0 != ethr_thr_create(&runq_supervisor_tid, - runq_supervisor, - NULL, - &opts)) - erts_exit(ERTS_ERROR_EXIT, "Failed to create run-queue supervision thread\n"); + res = ethr_thr_create(&runq_supervisor_tid, + runq_supervisor, + NULL, + &opts); + if (0 != res) + erts_exit(ERTS_ERROR_EXIT, "Failed to create run-queue supervision thread, " + "error = %d\n", res); } @@ -8471,7 +8473,7 @@ erts_start_schedulers(void) opts.suggested_stack_size = erts_dcpu_sched_thread_suggested_stack_size; res = ethr_thr_create(&esdp->tid,sched_dirty_cpu_thread_func,(void*)esdp,&opts); if (res != 0) - erts_exit(ERTS_ERROR_EXIT, "Failed to create dirty cpu scheduler thread %d\n", ix); + erts_exit(ERTS_ERROR_EXIT, "Failed to create dirty cpu scheduler thread %d, error = %d\n", ix, res); } for (ix = 0; ix < erts_no_dirty_io_schedulers; ix++) { ErtsSchedulerData *esdp = ERTS_DIRTY_IO_SCHEDULER_IX(ix); @@ -8479,7 +8481,7 @@ erts_start_schedulers(void) opts.suggested_stack_size = erts_dio_sched_thread_suggested_stack_size; res = ethr_thr_create(&esdp->tid,sched_dirty_io_thread_func,(void*)esdp,&opts); if (res != 0) - erts_exit(ERTS_ERROR_EXIT, "Failed to create dirty io scheduler thread %d\n", ix); + erts_exit(ERTS_ERROR_EXIT, "Failed to create dirty io scheduler thread %d, error = %d\n", ix, res); } } @@ -8489,7 +8491,7 @@ erts_start_schedulers(void) res = ethr_thr_create(&tid, aux_thread, NULL, &opts); if (res != 0) - erts_exit(ERTS_ERROR_EXIT, "Failed to create aux thread\n"); + erts_exit(ERTS_ERROR_EXIT, "Failed to create aux thread, error = %d\n", res); for (ix = 0; ix < erts_no_poll_threads; ix++) { erts_snprintf(opts.name, 16, "%d_poller", ix); diff --git a/erts/emulator/beam/erl_term.h b/erts/emulator/beam/erl_term.h index 842802f8d9..6daf043117 100644 --- a/erts/emulator/beam/erl_term.h +++ b/erts/emulator/beam/erl_term.h @@ -270,7 +270,6 @@ _ET_DECLARE_CHECKED(Eterm*,list_val,Wterm) #define is_byte(x) (((x) & ((~(Uint)0 << (_TAG_IMMED1_SIZE+8)) + _TAG_IMMED1_MASK)) == _TAG_IMMED1_SMALL) #define is_valid_bit_size(x) (((Sint)(x)) >= 0 && ((x) & 0x7F) == _TAG_IMMED1_SMALL) #define is_not_valid_bit_size(x) (!is_valid_bit_size((x))) -#define MY_IS_SSMALL(x) (((Uint) ((((x)) >> (SMALL_BITS-1)) + 1)) < 2) #define _unchecked_unsigned_val(x) ((x) >> _TAG_IMMED1_SIZE) _ET_DECLARE_CHECKED(Uint,unsigned_val,Eterm) #define unsigned_val(x) _ET_APPLY(unsigned_val,(x)) diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c index 60cf09dc07..970158933f 100644 --- a/erts/emulator/beam/external.c +++ b/erts/emulator/beam/external.c @@ -3115,7 +3115,7 @@ dec_term(ErtsDistExternal *edep, #if defined(ARCH_64) *objp = make_small(sn); #else - if (MY_IS_SSMALL(sn)) { + if (IS_SSMALL(sn)) { *objp = make_small(sn); } else { *objp = small_to_big(sn, hp); diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index a1b15a2199..4e1d2f0d7f 100644 --- a/erts/emulator/drivers/common/efile_drv.c +++ b/erts/emulator/drivers/common/efile_drv.c @@ -1261,6 +1261,50 @@ static void free_read_line(void *data) EF_FREE(d); } +void read_file_zero_size(struct t_data* d); +#define ZERO_FILE_CHUNK (64 * 1024) + +/* [ERL-327] Some special files like /proc/... have reported size 0 */ +void read_file_zero_size(struct t_data* d) { + size_t total_read_size = 0; + size_t allocated_size = ZERO_FILE_CHUNK; /* allocd in invoke_read_file */ + for (;;) { + size_t read_result; + + /* Read until we hit EOF (read less than FILE_SEGMENT_READ) */ + d->result_ok = efile_read(&d->errInfo, + EFILE_MODE_READ, + (int) d->fd, + (d->c.read_file.binp->orig_bytes + + total_read_size), + ZERO_FILE_CHUNK, + &read_result); + if (!d->result_ok) { + break; + } + + total_read_size += read_result; + d->c.read_file.offset += read_result; + if (read_result < ZERO_FILE_CHUNK) { + break; + } + + /* Grow before the next read call */ + allocated_size = total_read_size + ZERO_FILE_CHUNK; + d->c.read_file.binp = driver_realloc_binary(d->c.read_file.binp, + allocated_size); + } + + /* Finalize the memory usage. Hopefully it was read fully on the first + * go, so the binary allocation overhead becomes: + * alloc ZERO_FILE_CHUNK (64kb) -> realloc real_size */ + if (allocated_size != total_read_size) { + d->c.read_file.binp = driver_realloc_binary(d->c.read_file.binp, + total_read_size); + } + d->again = 0; +} + static void invoke_read_file(void *data) { struct t_data *d = (struct t_data *) data; @@ -1279,9 +1323,15 @@ static void invoke_read_file(void *data) } d->fd = fd; d->c.read_file.size = (int) size; - if (size < 0 || size != d->c.read_file.size || - ! (d->c.read_file.binp = - driver_alloc_binary(d->c.read_file.size))) { + + /* For zero sized files allocate a reasonable chunk to attempt reading + * anyway. Note: This will eat ZERO_FILE_CHUNK bytes for any 0 file + * and free them immediately after (if the file was empty). */ + ERTS_ASSERT(size >= 0); + d->c.read_file.binp = driver_alloc_binary(size != 0 ? (size_t)size + : ZERO_FILE_CHUNK); + + if (size < 0 || size != d->c.read_file.size || !d->c.read_file.binp) { d->result_ok = 0; d->errInfo.posix_errno = ENOMEM; goto close; @@ -1290,6 +1340,11 @@ static void invoke_read_file(void *data) } /* Invariant: d->c.read_file.size >= d->c.read_file.offset */ + if (d->c.read_file.size == 0) { + read_file_zero_size(d); + goto close; + } + read_size = (size_t) (d->c.read_file.size - d->c.read_file.offset); if (! read_size) goto close; chop = d->again && read_size >= FILE_SEGMENT_READ*2; diff --git a/erts/emulator/pcre/README.pcre_update.md b/erts/emulator/pcre/README.pcre_update.md index 8caf575d31..599e3d0d12 100644 --- a/erts/emulator/pcre/README.pcre_update.md +++ b/erts/emulator/pcre/README.pcre_update.md @@ -2,7 +2,7 @@ ## The basic changes to the PCRE library -To work with the Erlang VM, PCRE has been changed in two important ways: +To work with the Erlang VM, PCRE has been changed in three important ways: 1. The main execution machine in pcre\_exec has been modified so that matching can be interrupted and restarted. This functionality utilizes diff --git a/erts/emulator/test/efile_SUITE.erl b/erts/emulator/test/efile_SUITE.erl index f0e1bcf04b..08d5597d78 100644 --- a/erts/emulator/test/efile_SUITE.erl +++ b/erts/emulator/test/efile_SUITE.erl @@ -19,16 +19,20 @@ -module(efile_SUITE). -export([all/0, suite/0]). --export([iter_max_files/1, async_dist/1]). +-export([async_dist/1, + iter_max_files/1, + proc_zero_sized_files/1 + ]). -export([do_iter_max_files/2, do_async_dist/1]). -include_lib("common_test/include/ct.hrl"). +-include_lib("stdlib/include/assert.hrl"). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [iter_max_files, async_dist]. + [iter_max_files, async_dist, proc_zero_sized_files]. do_async_dist(Dir) -> X = 100, @@ -162,3 +166,44 @@ open_files(Name) -> % io:format("Error reason: ~p", [_Reason]), [] end. + +%% @doc If /proc filesystem exists (no way to know if it is real proc or just +%% a /proc directory), let's read some zero sized files 500 times each, while +%% ensuring that response isn't empty << >> +proc_zero_sized_files(Config) when is_list(Config) -> + {Type, Flavor} = os:type(), + %% Some files which exist on Linux but might be missing on other systems + Inputs = ["/proc/cpuinfo", + "/proc/meminfo", + "/proc/partitions", + "/proc/swaps", + "/proc/version", + "/proc/uptime", + %% curproc is present on freebsd + "/proc/curproc/cmdline"], + case filelib:is_dir("/proc") of + false -> {skip, "/proc not found"}; % skip the test if no /proc + _ when Type =:= unix andalso Flavor =:= sunos -> + %% SunOS has a /proc, but no zero sized special files + {skip, "sunos does not have any zero sized special files"}; + true -> + %% Take away files which do not exist in proc + Inputs1 = lists:filter(fun filelib:is_file/1, Inputs), + + %% Fail if none of mentioned files exist in /proc, did we just get + %% a normal /proc directory without any special files? + ?assertNotEqual([], Inputs1), + + %% For 6 inputs and 500 attempts each this do run anywhere + %% between 500 and 3000 function calls. + lists:foreach( + fun(Filename) -> do_proc_zero_sized(Filename, 500) end, + Inputs1) + end. + +%% @doc Test one file N times to also trigger possible leaking fds and memory +do_proc_zero_sized(_Filename, 0) -> ok; +do_proc_zero_sized(Filename, N) -> + Data = file:read_file(Filename), + ?assertNotEqual(<<>>, Data), + do_proc_zero_sized(Filename, N-1). diff --git a/erts/emulator/test/emulator_smoke.spec b/erts/emulator/test/emulator_smoke.spec index b2d0de8835..fc98ba6823 100644 --- a/erts/emulator/test/emulator_smoke.spec +++ b/erts/emulator/test/emulator_smoke.spec @@ -7,3 +7,4 @@ [consistency],"Not reliable in October and March"}. {cases,'Dir',crypto_SUITE,[t_md5]}. {cases,'Dir',float_SUITE,[fpe,cmp_integer]}. +{cases,'Dir',erts_debug_SUITE,[df]}. diff --git a/erts/emulator/test/iovec_SUITE.erl b/erts/emulator/test/iovec_SUITE.erl index 28df36d293..49dc64b0d2 100644 --- a/erts/emulator/test/iovec_SUITE.erl +++ b/erts/emulator/test/iovec_SUITE.erl @@ -24,7 +24,8 @@ -export([integer_lists/1, binary_lists/1, empty_lists/1, empty_binary_lists/1, mixed_lists/1, improper_lists/1, illegal_lists/1, cons_bomb/1, - iolist_to_iovec_idempotence/1, iolist_to_iovec_correctness/1]). + sub_binary_lists/1, iolist_to_iovec_idempotence/1, + iolist_to_iovec_correctness/1]). -include_lib("common_test/include/ct.hrl"). @@ -34,8 +35,8 @@ suite() -> all() -> [integer_lists, binary_lists, empty_lists, empty_binary_lists, mixed_lists, - illegal_lists, improper_lists, cons_bomb, iolist_to_iovec_idempotence, - iolist_to_iovec_correctness]. + sub_binary_lists, illegal_lists, improper_lists, cons_bomb, + iolist_to_iovec_idempotence, iolist_to_iovec_correctness]. init_per_suite(Config) -> Config. @@ -46,15 +47,16 @@ end_per_suite(Config) -> integer_lists(Config) when is_list(Config) -> Variations = gen_variations([I || I <- lists:seq(1, 255)]), + equivalence_test(fun erlang:iolist_to_iovec/1, Variations). - equivalence_test(fun erlang:iolist_to_iovec/1, Variations), - - ok. +sub_binary_lists(Config) when is_list(Config) -> + Parent = <<0:256/unit:8, "gazurka">>, + <<0:196/unit:8, Child/binary>> = Parent, + equivalence_test(fun erlang:iolist_to_iovec/1, gen_variations(Child)). binary_lists(Config) when is_list(Config) -> Variations = gen_variations([<<I:8>> || I <- lists:seq(1, 255)]), - equivalence_test(fun erlang:iolist_to_iovec/1, Variations), - ok. + equivalence_test(fun erlang:iolist_to_iovec/1, Variations). empty_lists(Config) when is_list(Config) -> Variations = gen_variations([[] || _ <- lists:seq(1, 256)]), @@ -70,8 +72,7 @@ empty_binary_lists(Config) when is_list(Config) -> mixed_lists(Config) when is_list(Config) -> Variations = gen_variations([<<>>, lists:seq(1, 40), <<12, 45, 78>>]), - equivalence_test(fun erlang:iolist_to_iovec/1, Variations), - ok. + equivalence_test(fun erlang:iolist_to_iovec/1, Variations). illegal_lists(Config) when is_list(Config) -> BitStrs = gen_variations(["gurka", <<1:1>>, "gaffel"]), @@ -82,18 +83,15 @@ illegal_lists(Config) when is_list(Config) -> Variations = BitStrs ++ BadInts ++ Atoms ++ BadTails, - illegality_test(fun erlang:iolist_to_iovec/1, Variations), - - ok. + illegality_test(fun erlang:iolist_to_iovec/1, Variations). improper_lists(Config) when is_list(Config) -> Variations = [ [[[[1 | <<2>>] | <<3>>] | <<4>>] | <<5>>], - [[<<"test">>, 3] | <<"improper tail">>], - [1, 2, 3 | <<"improper tail">>] + [[<<1>>, 2] | <<3, 4, 5>>], + [1, 2, 3 | <<4, 5>>] ], - equivalence_test(fun erlang:iolist_to_iovec/1, Variations), - ok. + equivalence_test(fun erlang:iolist_to_iovec/1, Variations). cons_bomb(Config) when is_list(Config) -> IntBase = gen_variations([I || I <- lists:seq(1, 255)]), @@ -108,8 +106,7 @@ cons_bomb(Config) when is_list(Config) -> end, Variations = gen_variations([IntBase, BinBase, MixBase], Rounds), - equivalence_test(fun erlang:iolist_to_iovec/1, Variations), - ok. + equivalence_test(fun erlang:iolist_to_iovec/1, Variations). iolist_to_iovec_idempotence(Config) when is_list(Config) -> IntVariations = gen_variations([I || I <- lists:seq(1, 255)]), @@ -134,11 +131,15 @@ iolist_to_iovec_correctness(Config) when is_list(Config) -> ok. illegality_test(Fun, Variations) -> - [{'EXIT',{badarg, _}} = (catch Fun(Variation)) || Variation <- Variations]. + [{'EXIT',{badarg, _}} = (catch Fun(Variation)) || Variation <- Variations], + ok. equivalence_test(Fun, [Head | _] = Variations) -> + %% Check that each variation is equal to the others, and that the sum of + %% them is equal to the input. Comparand = Fun(Head), - [is_iolist_equal(Comparand, Fun(Variation)) || Variation <- Variations], + [true = is_iolist_equal(Comparand, Fun(V)) || V <- Variations], + true = is_iolist_equal(Variations, Fun(Variations)), ok. is_iolist_equal(A, B) -> diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops index bb31db7eb5..a9b2c8861c 100755 --- a/erts/emulator/utils/beam_makeops +++ b/erts/emulator/utils/beam_makeops @@ -80,7 +80,10 @@ my %gen_opnum; my %num_specific; my %gen_to_spec; my %specific_op; -my %group_size; # Group size for specific operators. + +# Information about each specific operator. Key is the print name (e.g. get_list_xxy). +# Value is a hash. +my %spec_op_info; my %gen_arity; my @gen_arity; @@ -523,6 +526,37 @@ sub emulator_output { my $key; # Loop variable. # + # Generate code and meta information for all instructions. + # + foreach $key (keys %specific_op) { + foreach (@{$specific_op{$key}}) { + my($name, $hotness, @args) = @$_; + my $sign = join('', @args); + my $print_name = print_name($name, @args); + + my($size, $code, $pack_spec) = cg_basic($name, @args); + if (defined $code) { + $code = "OpCase($print_name):\n$code"; + push @generated_code, [$hotness,$code,($print_name)]; + } + + # Note: Some of the information below will be modified + # for combined instructions. + my %info = ('size' => $size, + 'pack_spec' => $pack_spec, + 'adj' => 0, + 'args' => \@args); + $spec_op_info{$print_name} = \%info; + } + } + + # + # Combine micro instruction into instruction blocks and generate + # code for them. + # + combine_micro_instructions(); + + # # Information about opcodes (beam_opcodes.c). # $name = "$outdir/beam_opcodes.c"; @@ -551,14 +585,9 @@ sub emulator_output { print "\n"; # - # Combine micro instruction into instruction blocks. - # - combine_micro_instructions(); - - # # Generate code for specific ops. # - my($spec_opnum) = 0; + my $spec_opnum = 0; print "const OpEntry opc[] = {\n"; foreach $key (sort keys %specific_op) { $gen_to_spec{$key} = $spec_opnum; @@ -576,35 +605,21 @@ sub emulator_output { # The primitive types should sort before other types. - my($sort_key) = $sign; + my $sort_key = $sign; eval "\$sort_key =~ tr/$genop_types/./"; $sort_key .= ":$sign"; - $items{$sort_key} = [$name, $hot, $sign, @args]; + my $print_name = print_name($name, @args); + $items{$sort_key} = $print_name; } # # Now call the generator for the sorted result. # - foreach (sort keys %items) { - my($name, $hot, $sign, @args) = @{$items{$_}}; + foreach my $sort_key (sort keys %items) { + my $print_name = $items{$sort_key}; + my $info = $spec_op_info{$print_name}; + my(@args) = @{$info->{'args'}}; my $arity = @args; - my($instr) = "${name}_$sign"; - $instr =~ s/_$//; - - # - # Call a generator to calculate size and generate macros - # for the emulator. - # - my($size, $code, $pack) = - basic_generator($name, 1, '', 0, undef, @args); - - # - # Save the generated $code for later. - # - if (defined $code) { - $code = "OpCase($instr):\n$code"; - push @generated_code, [$hot,$code,($instr)]; - } # # Calculate the bit mask which should be used to match this @@ -626,7 +641,6 @@ sub emulator_output { } printf "/* %3d */ ", $spec_opnum; - my $print_name = $sign ne '' ? "${name}_$sign" : $name; my $init = "{"; my $sep = ""; foreach (@bits) { @@ -634,12 +648,12 @@ sub emulator_output { $sep = ","; } $init .= "}"; - my $adj = 0; - if (defined $group_size{$print_name}) { - $adj = $size - $group_size{$print_name}; - } - init_item($print_name, $init, $involves_r, $size, $adj, $pack, $sign); - $op_to_name[$spec_opnum] = $instr; + my $adj = $info->{'adj'}; + my $size = $info->{'size'}; + my $pack_spec = $info->{'pack_spec'}; + my $sign = join '', @args; + init_item($print_name, $init, $involves_r, $size, $adj, $pack_spec, $sign); + $op_to_name[$spec_opnum] = $print_name; $spec_opnum++; } } @@ -835,6 +849,12 @@ sub emulator_output { print_code(COLD); } +sub print_name { + my($name,@args) = @_; + my $sign = join '', @args; + $sign ne '' ? "${name}_$sign" : $name; +} + sub init_item { my($sep) = ""; @@ -1108,8 +1128,9 @@ sub combine_instruction_group { my $offset = 0; my @rest = @args; my @new_subs; - my $opcase = $specific; - $opcase .= "_" . join '', @args if @args; + my $print_name = print_name($specific, @args); + my $opcase = $print_name; + my $last = $subs[$#subs]; foreach my $s (@subs) { my $code = $c_code{$s}; my(undef,undef,@c_args) = @{$code}; @@ -1117,7 +1138,7 @@ sub combine_instruction_group { foreach (0..$#c_args) { push @first, shift @rest; } - my($size,undef) = basic_generator($s, 0, '', 0, undef, @first); + my $size = cg_combined_size($s, 1, @first); $offsets{$s} = $offset unless defined $offsets{$s} and $offsets{$s} >= $offset; $offset += $size - 1; @@ -1126,6 +1147,7 @@ sub combine_instruction_group { push @new_subs, [$opcase,$label,$s,$size-1,@first]; $opcase = ''; } + $spec_op_info{$print_name}->{'size'} = $offset + 1; $group_size = $offset if $group_size < $offset; push @instrs, [$specific_key,@new_subs]; } @@ -1162,6 +1184,8 @@ sub combine_instruction_group { # Now generate the code for the entire group. my $offset = 0; my @opcase_labels; + my %down; + my %up; for(my $i = 0; $i < @slots; $i++) { my $key = $slots[$i]; @@ -1182,11 +1206,11 @@ sub combine_instruction_group { my $seen_key = "$label:$next:" . scalar(@first); next if $opcase eq '' and $seen{$seen_key}; $seen{$seen_key} = 1; + $seen_key .= $opcase; if ($opcase ne '') { $gcode .= "OpCase($opcase):\n"; push @opcase_labels, $opcase; - $group_size{$opcase} = $group_size + 1; } if ($num_references{$label}) { $gcode .= "$label:\n"; @@ -1204,14 +1228,42 @@ sub combine_instruction_group { $transfer_to_next .= "goto $next;\n\n"; } - my(undef,$gen_code) = - basic_generator($s, 0, $flags, $offset, - $group_size-$offset-$dec, @first); + my($gen_code,$down,$up) = + cg_combined_code($s, 1, $flags, $offset, + $group_size-$offset-$dec, @first); + my $spec_label = "$opcase$label"; + $down{$spec_label} = $down; + $up{$spec_label} = $up; $gcode .= $gen_code . $transfer_to_next; } $offset = $order_to_offset{$slots[$i+1]} if $i < $#slots; } + foreach my $print_name (@opcase_labels) { + my $info = $spec_op_info{$print_name}; + $info->{'adj'} = $info->{'size'} - $group_size - 1; + } + + # + # Assemble pack specifications for all instructions in the group. + # + foreach my $instr (@instrs) { + my(undef,@subs) = @{$instr}; + my $down = ''; + my $up = ''; + for (my $i = 0; $i < @subs; $i++) { + my($opcase,$label) = @{$subs[$i]}; + my $spec_label = "$opcase$label"; + if (defined $down{$spec_label}) { + $down = $down{$spec_label} . $down; + $up = $up . $up{$spec_label}; + } + } + my $print_name = $subs[0]->[0]; + my $info = $spec_op_info{$print_name}; + $info->{'pack_spec'} = build_pack_spec("$down:$up"); + } + ($group_hotness,"{\n$gcode\n}\n\n",@opcase_labels); } @@ -1223,12 +1275,42 @@ sub micro_label { # -# Basic implementation of instruction in emulator loop -# (assuming no packing). +# Basic code generation for one instruction. # -sub basic_generator { - my($name,$hot,$extra_comments,$offset,$group_size,@args) = @_; +sub cg_basic { + my($name,@args) = @_; + my($size,$code,$pack_spec) = code_gen($name, 1, '', 0, undef, @args); + $pack_spec = build_pack_spec($pack_spec); + ($size,$code,$pack_spec); +} + +# +# Calculate size for a micro instruction. +# + +sub cg_combined_size { + my($name,$pack,@args) = @_; + my($size) = code_gen($name, $pack, '', 0, undef, @args); + $size; +} + +# +# Generate code for a micro instruction. +# + +sub cg_combined_code { + my($size,$code,$pack_spec) = code_gen(@_); + if ($pack_spec eq '') { + ($code,'',''); + } else { + my($down,$up) = split /:/, $pack_spec; + ($code,$down,$up); + } +} + +sub code_gen { + my($name,$pack,$extra_comments,$offset,$group_size,@args) = @_; my $size = 0; my $flags = ''; my @f; @@ -1242,8 +1324,8 @@ sub basic_generator { # my $c_code_ref = $c_code{$name}; - if ($hot and defined $c_code_ref and $name ne 'catch') { - ($var_decls, $pack_spec, @args) = do_pack(@args); + if ($pack and defined $c_code_ref and $name ne 'catch') { + ($var_decls, $pack_spec, @args) = do_pack($offset, @args); } # @@ -1519,7 +1601,7 @@ sub needs_do_wrapper { } sub do_pack { - my(@args) = @_; + my($offset,@args) = @_; my($packable_args) = 0; my @bits_needed; # Bits needed for each argument. @@ -1569,7 +1651,7 @@ sub do_pack { # # Nothing to pack unless there are at least 2 packable arguments. # - return ('', '', @args) if $packable_args < 2; + return ('', ':', @args) if $packable_args < 2; # # Determine how many arguments we should pack into each word. @@ -1644,13 +1726,12 @@ sub do_pack { # beginning). my $up = ''; # Pack commands (storing back while # moving forward). - my $did_some_packing = 0; # Nothing packed yet. # Skip an unpackable argument. my $skip_unpackable = sub { my($arg) = @_; - if ($arg_size{$arg} and $did_some_packing) { + if ($arg_size{$arg}) { # Save the argument on the pack engine's stack. my $push = 'g'; if ($type_bit{$arg} & $type_bit{'q'}) { @@ -1662,11 +1743,6 @@ sub do_pack { } $down = "$push${down}"; $up = "${up}p"; - } else { - # The argument has either zero size (e.g. r(0)), - # or is to the left of the first packed argument - # and will never be accessed. No need to do - # anything. } }; @@ -1700,11 +1776,10 @@ sub do_pack { my $this_size = $arg_size{$reg}; if ($bits_needed[$arg_num]) { $this_size = 0; - $did_some_packing = 1; if ($ap == 0) { $pack_prefix .= "Eterm $packed_var = " . - arg_offset($size) . ";\n"; + arg_offset($size+$offset) . ";\n"; $up .= "p"; $down = "P$down"; $this_size = 1; @@ -1731,7 +1806,7 @@ sub do_pack { $arg_num++; } - my $pack_spec = $down . $up; + my $pack_spec = "$down:$up"; return ($pack_prefix, $pack_spec, @args); } @@ -1744,6 +1819,17 @@ sub make_unpack { $e; } +sub build_pack_spec { + my $pack_spec = shift; + return '' if $pack_spec eq ''; + my($down,$up) = split /:/, $pack_spec; + while ($down =~ /[gfq]$/ and $up =~ /^p/) { + $down = substr($down, 0, -1); + $up = substr($up, 1); + } + "$down$up"; +} + sub quote { local($_) = @_; return "'$_'" if $_ eq 'try'; diff --git a/erts/test/erlexec_SUITE.erl b/erts/test/erlexec_SUITE.erl index 44d7f63387..db993abe52 100644 --- a/erts/test/erlexec_SUITE.erl +++ b/erts/test/erlexec_SUITE.erl @@ -59,7 +59,7 @@ otp_8209(Config) when is_list(Config) -> {ok,[[PName]]} = init:get_argument(progname), SNameS = "erlexec_test_01", SName = list_to_atom(SNameS++"@"++ - hd(tl(string:tokens(atom_to_list(node()),"@")))), + hd(tl(string:lexemes(atom_to_list(node()),"@")))), Cmd = PName ++ " dummy_param -sname "++SNameS++" -setcookie "++ atom_to_list(erlang:get_cookie()), open_port({spawn,Cmd},[]), @@ -75,7 +75,7 @@ cleanup_node(SNameS,0) -> {error, {would_not_die,list_to_atom(SNameS)}}; cleanup_node(SNameS,N) -> SName = list_to_atom(SNameS++"@"++ - hd(tl(string:tokens(atom_to_list(node()),"@")))), + hd(tl(string:lexemes(atom_to_list(node()),"@")))), case rpc:call(SName,init,stop,[]) of {badrpc,_} -> ok; @@ -322,7 +322,7 @@ zdbbl_dist_buf_busy_limit(Config) when is_list(Config) -> {ok,[[PName]]} = init:get_argument(progname), SNameS = "erlexec_test_02", SName = list_to_atom(SNameS++"@"++ - hd(tl(string:tokens(atom_to_list(node()),"@")))), + hd(tl(string:lexemes(atom_to_list(node()),"@")))), Cmd = PName ++ " -sname "++SNameS++" -setcookie "++ atom_to_list(erlang:get_cookie()) ++ " +zdbbl " ++ integer_to_list(LimKB), @@ -400,7 +400,7 @@ emu_args(CmdLineArgs) -> {ok,[[Erl]]} = init:get_argument(progname), EmuCL = os:cmd(Erl ++ " -emu_args_exit " ++ CmdLineArgs), io:format("EmuCL = ~ts", [EmuCL]), - split_emu_clt(string:tokens(EmuCL, [$ ,$\t,$\n,$\r])). + split_emu_clt(string:lexemes(EmuCL, [$ ,$\t,$\n,$\r])). split_emu_clt(EmuCLT) -> split_emu_clt(EmuCLT, [], [], [], emu). diff --git a/erts/test/install_SUITE.erl b/erts/test/install_SUITE.erl index d6c6d6f30e..324b398caa 100644 --- a/erts/test/install_SUITE.erl +++ b/erts/test/install_SUITE.erl @@ -580,7 +580,7 @@ end_per_testcase(_Case, _Config) -> ok. make_dirs(Root, Suffix) -> - do_make_dirs(Root, string:tokens(Suffix, [$/])). + do_make_dirs(Root, string:lexemes(Suffix, [$/])). do_make_dirs(_Root, []) -> ""; @@ -709,4 +709,4 @@ join("") -> join([""|Ds]) -> join(Ds); join([D|Ds]) -> - "/" ++ string:strip(D, both, $/) ++ join(Ds). + "/" ++ string:trim(D, both, [$/]) ++ join(Ds). diff --git a/erts/test/nt_SUITE.erl b/erts/test/nt_SUITE.erl index 624e5484ba..3081b58835 100644 --- a/erts/test/nt_SUITE.erl +++ b/erts/test/nt_SUITE.erl @@ -117,7 +117,7 @@ wait_for_node(Name) -> do_wait_for_it(FullName,30). make_full_name(Name) -> - [_,Suffix] = string:tokens(atom_to_list(node()),"@"), + [_,Suffix] = string:lexemes(atom_to_list(node()),"@"), list_to_atom(Name ++ "@" ++ Suffix). @@ -171,7 +171,7 @@ service_env(Config) when is_list(Config) -> ["ERLSRV_SERVICE_NAME"]), "erlsrv.exe" = filename:basename( hd( - string:tokens( + string:lexemes( rpc:call(make_full_name(Name), os, getenv, diff --git a/erts/test/otp_SUITE.erl b/erts/test/otp_SUITE.erl index 54fcfd935f..3abe45c141 100644 --- a/erts/test/otp_SUITE.erl +++ b/erts/test/otp_SUITE.erl @@ -336,7 +336,7 @@ not_recommended_calls(Config, Apps0, MFA) -> _ -> AppStrings = [atom_to_list(A) || A <- SkippedApps], Mess = io_lib:format("Application(s) not present: ~s\n", - [string:join(AppStrings, ", ")]), + [lists:join(", ", AppStrings)]), {comment, Mess} end; _ -> @@ -463,7 +463,7 @@ runtime_dependencies(Config) -> have_rdep(_App, [], _Dep) -> false; have_rdep(App, [RDep | RDeps], Dep) -> - [AppStr, _VsnStr] = string:tokens(RDep, "-"), + [AppStr, _VsnStr] = string:lexemes(RDep, "-"), case Dep == list_to_atom(AppStr) of true -> io:format("~p -> ~s~n", [App, RDep]), diff --git a/erts/test/run_erl_SUITE.erl b/erts/test/run_erl_SUITE.erl index fe1ccba1e2..08edd930b4 100644 --- a/erts/test/run_erl_SUITE.erl +++ b/erts/test/run_erl_SUITE.erl @@ -255,7 +255,7 @@ do_run_erl(Config, Case, Opt) -> net_kernel:monitor_nodes(true), open_port({spawn,Cmd}, []), - [_,Host] = string:tokens(atom_to_list(node()), "@"), + [_,Host] = string:lexemes(atom_to_list(node()), "@"), Node = list_to_atom(NodeName++"@"++Host), receive diff --git a/erts/test/upgrade_SUITE.erl b/erts/test/upgrade_SUITE.erl index a5639d927d..31ceb06314 100644 --- a/erts/test/upgrade_SUITE.erl +++ b/erts/test/upgrade_SUITE.erl @@ -287,7 +287,7 @@ create_relfile(Node,CreateDir,RelName0,RelVsn) -> true -> case filename:split(Path) -- SplitLibDir of [AppVsn,"ebin"] -> - case string:tokens(AppVsn,"-") of + case string:lexemes(AppVsn,"-") of [AppStr,Vsn] -> App = list_to_atom(AppStr), case lists:member(App,Exclude) of diff --git a/erts/test/z_SUITE.erl b/erts/test/z_SUITE.erl index d474c71c4f..cd7a894eb5 100644 --- a/erts/test/z_SUITE.erl +++ b/erts/test/z_SUITE.erl @@ -132,22 +132,9 @@ core_search_conf(RunByTS, DBTop, XDir) -> file_inspect(#core_search_conf{file = File}, Core) -> FRes0 = os:cmd(File ++ " " ++ Core), - FRes = case string:str(FRes0, Core) of - 0 -> - FRes0; - S -> - L = length(FRes0), - E = length(Core), - case S of - 1 -> - lists:sublist(FRes0, E+1, L+1); - _ -> - lists:sublist(FRes0, 1, S-1) - ++ - " " - ++ - lists:sublist(FRes0, E+1, L+1) - end + FRes = case string:split(FRes0, Core) of + [S1] -> S1; + [S1,S2] -> lists:flatten(S1 ++ " " ++ S2) end, case re:run(FRes, "text|ascii", [caseless,{capture,none}]) of match -> @@ -194,9 +181,6 @@ mod_time_list(F) -> [0,0,0,0,0,0] end. -str_strip(S) -> - string:strip(string:strip(string:strip(S), both, $\n), both, $\r). - dump_core(#core_search_conf{ cerl = false }, _) -> ok; dump_core(_, {ignore, _Core}) -> @@ -232,7 +216,7 @@ format_core(#core_search_conf{file = false}, Core, Ignore) -> io:format(" ~s~s " ++ time_fstr() ++ "~s~n", [Ignore, Core] ++ mod_time_list(Core)); format_core(#core_search_conf{file = File}, Core, Ignore) -> - FRes = str_strip(os:cmd(File ++ " " ++ Core)), + FRes = string:trim(os:cmd(File ++ " " ++ Core)), case catch re:run(FRes, Core, [caseless,{capture,none}]) of match -> io:format(" ~s~s " ++ time_fstr() ++ "~n", diff --git a/erts/vsn.mk b/erts/vsn.mk index c231c9c27d..380be1b534 100644 --- a/erts/vsn.mk +++ b/erts/vsn.mk @@ -18,7 +18,7 @@ # %CopyrightEnd% # -VSN = 9.0.5 +VSN = 9.1 # Port number 4365 in 4.2 # Port number 4366 in 4.3 diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml index 5399528271..ae6660c143 100644 --- a/lib/asn1/doc/src/notes.xml +++ b/lib/asn1/doc/src/notes.xml @@ -32,6 +32,24 @@ <p>This document describes the changes made to the asn1 application.</p> +<section><title>Asn1 5.0.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Compiling an ASN.1 module using the option {n2n, + EnumTypeName} when EnumTypeName contains a hypen like for + example Cause-Misc caused syntax errors when compiling + the generated Erlang code. This is now corrected.</p> + <p> + Own Id: OTP-14495 Aux Id: ERL-437 </p> + </item> + </list> + </section> + +</section> + <section><title>Asn1 5.0.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl index 83d12600b7..321980e5e4 100644 --- a/lib/asn1/src/asn1ct_check.erl +++ b/lib/asn1/src/asn1ct_check.erl @@ -1576,13 +1576,15 @@ printable_string_1(#'Externalvaluereference'{value=Type}) -> printable_string_1({Atom,Line}) when is_atom(Atom), is_integer(Line) -> q(Atom); printable_string_1({object,definedsyntax,L}) -> - q(string:join([printable_string_1(Item) || Item <- L], " ")); + Str = lists:join($\s, [printable_string_1(Item) || Item <- L]), + q(lists:flatten(Str)); printable_string_1([_|_]=Def) -> case lists:all(fun is_integer/1, Def) of true -> lists:flatten(io_lib:format("~p", [Def])); false -> - q(string:join([printable_string_1(Item) || Item <- Def], " ")) + Str = lists:join($\s, [printable_string_1(Item) || Item <- Def]), + q(lists:flatten(Str)) end; printable_string_1(Def) -> lists:flatten(io_lib:format("~p", [Def])). diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl index 806f8420ec..84c7f39d55 100644 --- a/lib/asn1/src/asn1ct_gen.erl +++ b/lib/asn1/src/asn1ct_gen.erl @@ -796,7 +796,7 @@ result_line(NoOkWrapper, Items) -> result_line_1([SingleItem]) -> SingleItem; result_line_1(Items) -> - ["{",string:join(Items, ","),"}"]. + ["{",lists:join(",",Items),"}"]. try_catch() -> [" catch",nl, @@ -943,7 +943,7 @@ open_hrl(OutFile,Module) -> hrl_protector(OutFile) -> BaseName = filename:basename(OutFile), - P = "_" ++ string:to_upper(BaseName) ++ "_HRL_", + P = "_" ++ string:uppercase(BaseName) ++ "_HRL_", [if $A =< C, C =< $Z -> C; $a =< C, C =< $a -> C; diff --git a/lib/asn1/src/asn1rtt_real_common.erl b/lib/asn1/src/asn1rtt_real_common.erl index 3a79209015..81c1f54d74 100644 --- a/lib/asn1/src/asn1rtt_real_common.erl +++ b/lib/asn1/src/asn1rtt_real_common.erl @@ -125,7 +125,7 @@ encode_real(_C, {_,Base,_}) -> encode_real(C, Real) when is_list(Real) -> %% The Real string may come in as a NR1, NR2 or NR3 string. {Mantissa, Exponent} = - case string:tokens(Real,"Ee") of + case string:lexemes(Real,"Ee") of [NR2] -> {NR2,0}; [NR3MB,NR3E] -> @@ -144,7 +144,7 @@ encode_real(C, Real) when is_list(Real) -> NewMan = remove_trailing_zeros(Dec), {NewMan,length(ZeroDecimal(NewMan))}; _ -> - case string:tokens(Mantissa,",.") of + case string:lexemes(Mantissa,",.") of [Num] -> %% No decimal-mark {integer_to_list(list_to_integer(Num)),0}; [Num,Dec] -> diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk index 5900f3037e..ef83b9e3dc 100644 --- a/lib/asn1/vsn.mk +++ b/lib/asn1/vsn.mk @@ -1 +1 @@ -ASN1_VSN = 5.0.2 +ASN1_VSN = 5.0.3 diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml index 37a1846160..b039023e0f 100644 --- a/lib/common_test/doc/src/notes.xml +++ b/lib/common_test/doc/src/notes.xml @@ -33,6 +33,21 @@ <file>notes.xml</file> </header> +<section><title>Common_Test 1.15.2</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + General Unicode improvements.</p> + <p> + Own Id: OTP-14462</p> + </item> + </list> + </section> + +</section> + <section><title>Common_Test 1.15.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/common_test/src/common_test.app.src b/lib/common_test/src/common_test.app.src index 430a4fa2fb..0aa4aacf16 100644 --- a/lib/common_test/src/common_test.app.src +++ b/lib/common_test/src/common_test.app.src @@ -92,7 +92,7 @@ "sasl-2.4.2", "snmp-5.1.2", "ssh-4.0", - "stdlib-2.5", + "stdlib-3.4", "syntax_tools-1.7", "tools-2.8", "xmerl-1.3.8" diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl index a12c0c9101..875301a8b2 100644 --- a/lib/common_test/src/ct.erl +++ b/lib/common_test/src/ct.erl @@ -1030,7 +1030,7 @@ make_and_load(Dir, Suite) -> EnvInclude = case os:getenv("CT_INCLUDE_PATH") of false -> []; - CtInclPath -> string:tokens(CtInclPath, [$:,$ ,$,]) + CtInclPath -> string:lexemes(CtInclPath, [$:,$ ,$,]) end, StartInclude = case init:get_argument(include) of diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl index d48ae830bb..b3f983dd46 100644 --- a/lib/common_test/src/ct_config.erl +++ b/lib/common_test/src/ct_config.erl @@ -659,7 +659,7 @@ decrypt_config_file(EncryptFileName, TargetFileName, {key,Key}) -> get_crypt_key_from_file(File) -> case file:read_file(File) of {ok,Bin} -> - case catch string:tokens(binary_to_list(Bin), [$\n,$\r]) of + case catch string:lexemes(binary_to_list(Bin), [$\n,$\r]) of [Key] -> Key; _ -> @@ -693,7 +693,7 @@ get_crypt_key_from_file() -> noent -> Result; _ -> - case catch string:tokens(binary_to_list(Result), [$\n,$\r]) of + case catch string:lexemes(binary_to_list(Result), [$\n,$\r]) of [Key] -> io:format("~nCrypt key file: ~ts~n", [FullName]), Key; diff --git a/lib/common_test/src/ct_config_plain.erl b/lib/common_test/src/ct_config_plain.erl index e72b55971b..e77381d7cf 100644 --- a/lib/common_test/src/ct_config_plain.erl +++ b/lib/common_test/src/ct_config_plain.erl @@ -106,7 +106,7 @@ read_config_terms1({done,{eof,EL},_}, L, _, _) -> read_config_terms1({done,{error,Info,EL},_}, L, _, _) -> {error,{Info,{L,EL}}}; read_config_terms1({more,_}, L, Terms, Rest) -> - case string:tokens(Rest, [$\n,$\r,$\t]) of + case string:lexemes(Rest, [$\n,$\r,$\t]) of [] -> lists:reverse(Terms); _ -> diff --git a/lib/common_test/src/ct_conn_log_h.erl b/lib/common_test/src/ct_conn_log_h.erl index cf0a228e1b..3e83020f45 100644 --- a/lib/common_test/src/ct_conn_log_h.erl +++ b/lib/common_test/src/ct_conn_log_h.erl @@ -224,7 +224,7 @@ now_to_time({_,_,MicroS}=Now) -> {calendar:now_to_local_time(Now),MicroS}. pretty_head({{{Y,Mo,D},{H,Mi,S}},MicroS},ConnMod,Text0) -> - Text = string:to_upper(atom_to_list(ConnMod) ++ Text0), + Text = string:uppercase(atom_to_list(ConnMod) ++ Text0), io_lib:format("= ~s ==== ~s-~s-~w::~s:~s:~s,~s ", [Text,t(D),month(Mo),Y,t(H),t(Mi),t(S), micro2milli(MicroS)]). @@ -275,7 +275,7 @@ pad0(N,Str) -> lists:duplicate(N-M,$0) ++ Str. pad_char_end(N,Str,Char) -> - case length(lists:flatten(Str)) of + case string:length(Str) of M when M<N -> Str ++ lists:duplicate(N-M,Char); _ -> Str end. diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 6066470233..7f7e9ae6f9 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -921,9 +921,10 @@ error_notification(Mod,Func,_Args,{Error,Loc}) -> end, ErrorStr = case ErrorSpec of {badmatch,Descr} -> - Descr1 = lists:flatten(io_lib:format("~tP",[Descr,10])), - if length(Descr1) > 50 -> - Descr2 = string:substr(Descr1,1,50), + Descr1 = io_lib:format("~tP",[Descr,10]), + DescrLength = string:length(Descr1), + if DescrLength > 50 -> + Descr2 = string:slice(Descr1,0,50), io_lib:format("{badmatch,~ts...}",[Descr2]); true -> io_lib:format("{badmatch,~ts}",[Descr1]) diff --git a/lib/common_test/src/ct_ftp.erl b/lib/common_test/src/ct_ftp.erl index 8effb06e7e..ee4a6a6c45 100644 --- a/lib/common_test/src/ct_ftp.erl +++ b/lib/common_test/src/ct_ftp.erl @@ -285,7 +285,7 @@ init(KeyOrName,{IP,Port},{Username,Password}) -> {ok,FtpPid} -> log(heading(init,KeyOrName), "Opened ftp connection:\nIP: ~tp\nUsername: ~tp\nPassword: ~p\n", - [IP,Username,lists:duplicate(length(Password),$*)]), + [IP,Username,lists:duplicate(string:length(Password),$*)]), {ok,FtpPid,#state{ftp_pid=FtpPid,target_name=KeyOrName}}; Error -> Error diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index ba7660fe6a..028c265420 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -1188,26 +1188,23 @@ print_style(Fd, IoFormat, StyleSheet) -> case file:read_file(StyleSheet) of {ok,Bin} -> Str = b2s(Bin,encoding(StyleSheet)), - Pos0 = case string:str(Str,"<style>") of - 0 -> string:str(Str,"<STYLE>"); - N0 -> N0 - end, - Pos1 = case string:str(Str,"</style>") of - 0 -> string:str(Str,"</STYLE>"); - N1 -> N1 - end, - if (Pos0 == 0) and (Pos1 /= 0) -> - print_style_error(Fd, IoFormat, - StyleSheet, missing_style_start_tag); - (Pos0 /= 0) and (Pos1 == 0) -> - print_style_error(Fd, IoFormat, - StyleSheet,missing_style_end_tag); - Pos0 /= 0 -> - Style = string:sub_string(Str,Pos0,Pos1+7), - IoFormat(Fd,"~ts\n",[Style]); - Pos0 == 0 -> - IoFormat(Fd,"<style>\n~ts</style>\n",[Str]) - end; + case re:run(Str,"<style>.*</style>", + [dotall,caseless,{capture,all,list}]) of + nomatch -> + case re:run(Str,"</?style>",[caseless,{capture,all,list}]) of + nomatch -> + IoFormat(Fd,"<style>\n~ts</style>\n",[Str]); + {match,["</"++_]} -> + print_style_error(Fd, IoFormat, + StyleSheet, + missing_style_start_tag); + {match,[_]} -> + print_style_error(Fd, IoFormat, + StyleSheet,missing_style_end_tag) + end; + {match,[Style]} -> + IoFormat(Fd,"~ts\n",[Style]) + end; {error,Reason} -> print_style_error(Fd,IoFormat,StyleSheet,Reason) end. @@ -1414,9 +1411,9 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip, {Lbl,Timestamp,Node,AllInfo} = case All of {true,OldRuns} -> - [_Prefix,NodeOrDate|_] = string:tokens(Link,"."), - Node1 = case string:chr(NodeOrDate,$@) of - 0 -> "-"; + [_Prefix,NodeOrDate|_] = string:lexemes(Link,"."), + Node1 = case string:find(NodeOrDate,[$@]) of + nomatch -> "-"; _ -> NodeOrDate end, @@ -1523,7 +1520,7 @@ not_built(BaseName,_LogDir,_All,Missing) -> %% Top.ObjDir | Top.ObjDir.suites | Top.ObjDir.Suite | %% Top.ObjDir.Suite.cases | Top.ObjDir.Suite.Case Failed = - case string:tokens(BaseName,".") of + case string:lexemes(BaseName,".") of [T,O] when is_list(T) -> % all under Top.ObjDir locate_info({T,O},all,Missing); [T,O,"suites"] -> @@ -2051,9 +2048,9 @@ sort_all_runs(Dirs) -> %% "YYYY-MM-DD_HH.MM.SS" lists:sort(fun(Dir1,Dir2) -> [SS1,MM1,HH1,Date1|_] = - lists:reverse(string:tokens(Dir1,[$.,$_])), + lists:reverse(string:lexemes(Dir1,[$.,$_])), [SS2,MM2,HH2,Date2|_] = - lists:reverse(string:tokens(Dir2,[$.,$_])), + lists:reverse(string:lexemes(Dir2,[$.,$_])), {Date1,HH1,MM1,SS1} > {Date2,HH2,MM2,SS2} end, Dirs). @@ -2063,9 +2060,9 @@ sort_ct_runs(Dirs) -> lists:sort( fun(Dir1,Dir2) -> [SS1,MM1,DateHH1 | _] = - lists:reverse(string:tokens(filename:dirname(Dir1),[$.])), + lists:reverse(string:lexemes(filename:dirname(Dir1),[$.])), [SS2,MM2,DateHH2 | _] = - lists:reverse(string:tokens(filename:dirname(Dir2),[$.])), + lists:reverse(string:lexemes(filename:dirname(Dir2),[$.])), {DateHH1,MM1,SS1} =< {DateHH2,MM2,SS2} end, Dirs). @@ -2211,27 +2208,15 @@ runentry(Dir, Totals={Node,Label,Logs, 0 -> "-"; N -> integer_to_list(N) end, - StripExt = - fun(File) -> - string:sub_string(File,1, - length(File)- - length(?logdir_ext)) ++ ", " - end, - Polish = fun(S) -> case lists:reverse(S) of - [32,$,|Rev] -> lists:reverse(Rev); - [$,|Rev] -> lists:reverse(Rev); - _ -> S - end - end, - TestNames = Polish(lists:flatten(lists:map(StripExt,Logs))), + + RootNames = lists:map(fun(F) -> filename:rootname(F,?logdir_ext) end, Logs), + TestNames = lists:flatten(lists:join(", ", RootNames)), TestNamesTrunc = - if TestNames=="" -> - ""; - length(TestNames) < ?testname_width -> + if length(TestNames) < ?testname_width -> TestNames; true -> - Trunc = Polish(string:substr(TestNames,1, - ?testname_width-3)), + Trunc = string:trim(string:slice(TestNames,0,?testname_width-3), + trailing,",\s"), lists:flatten(io_lib:format("~ts...",[Trunc])) end, TotMissingStr = @@ -2374,7 +2359,7 @@ force_rename(From,To,Number) -> timestamp(Dir) -> - TsR = lists:reverse(string:tokens(Dir,".-_")), + TsR = lists:reverse(string:lexemes(Dir,".-_")), [S,Min,H,D,M,Y] = [list_to_integer(N) || N <- lists:sublist(TsR,6)], format_time({{Y,M,D},{H,Min,S}}). @@ -2923,7 +2908,7 @@ cache_vsn() -> VSNfile = filename:join([EbinDir,"..","vsn.mk"]), case file:read_file(VSNfile) of {ok,Bin} -> - [_,VSN] = string:tokens(binary_to_list(Bin),[$=,$\n,$ ]), + [_,VSN] = string:lexemes(binary_to_list(Bin),[$=,$\n,$ ]), VSN; _ -> undefined @@ -3320,7 +3305,7 @@ insert_javascript({tablesorter,TableName, end, [{"CTDateSorter",DateCols}, {"CTTextSorter",TextCols}, {"CTValSorter",ValCols}]))), - Headers1 = string:substr(Headers, 1, length(Headers)-2), + Headers1 = string:trim(Headers, trailing, ",\n"), ["<script type=\"text/javascript\">\n", "// Parser for date format, e.g: Wed Jul 4 2012 11:24:15\n", diff --git a/lib/common_test/src/ct_master.erl b/lib/common_test/src/ct_master.erl index 6e6d1879c2..44d3fb8f64 100644 --- a/lib/common_test/src/ct_master.erl +++ b/lib/common_test/src/ct_master.erl @@ -807,7 +807,7 @@ filter_accessible(InitOptions, Inaccessible)-> start_nodes(InitOptions)-> lists:foreach(fun({NodeName, Options})-> - [NodeS,HostS]=string:tokens(atom_to_list(NodeName), "@"), + [NodeS,HostS]=string:lexemes(atom_to_list(NodeName), "@"), Node=list_to_atom(NodeS), Host=list_to_atom(HostS), HasNodeStart = lists:keymember(node_start, 1, Options), diff --git a/lib/common_test/src/ct_master_logs.erl b/lib/common_test/src/ct_master_logs.erl index d8ecd641ed..fd92f73f63 100644 --- a/lib/common_test/src/ct_master_logs.erl +++ b/lib/common_test/src/ct_master_logs.erl @@ -297,7 +297,7 @@ sort_all_runs(Dirs) -> %% "YYYY-MM-DD_HH.MM.SS" KeyList = lists:map(fun(Dir) -> - case lists:reverse(string:tokens(Dir,[$.,$_])) of + case lists:reverse(string:lexemes(Dir,[$.,$_])) of [SS,MM,HH,Date|_] -> {{Date,HH,MM,SS},Dir}; _Other -> @@ -312,18 +312,8 @@ runentry(Dir) -> {MasterStr,NodesStr} = case read_details_file(Dir) of {Master,Nodes} when is_list(Nodes) -> - [_,Host] = string:tokens(atom_to_list(Master),"@"), - NodesList = - lists:reverse(lists:map(fun(N) -> - atom_to_list(N) ++ ", " - end,Nodes)), - case NodesList of - [N|NListR] -> - N1 = string:sub_string(N,1,length(N)-2), - {Host,lists:flatten(lists:reverse([N1|NListR]))}; - [] -> - {Host,""} - end; + [_,Host] = string:lexemes(atom_to_list(Master),"@"), + {Host,lists:concat(lists:join(", ",Nodes))}; _Error -> {"unknown",""} end, @@ -348,7 +338,7 @@ all_runs_header() -> xhtml("", "</tr></thead>\n<tbody>\n")]]. timestamp(Dir) -> - [S,Min,H,D,M,Y|_] = lists:reverse(string:tokens(Dir,".-_")), + [S,Min,H,D,M,Y|_] = lists:reverse(string:lexemes(Dir,".-_")), [S1,Min1,H1,D1,M1,Y1] = [list_to_integer(N) || N <- [S,Min,H,D,M,Y]], format_time({{Y1,M1,D1},{H1,Min1,S1}}). diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl index 2c4b97df20..29188a648e 100644 --- a/lib/common_test/src/ct_netconfc.erl +++ b/lib/common_test/src/ct_netconfc.erl @@ -1467,7 +1467,7 @@ decode_data(Other) -> {error,{unexpected_rpc_reply,Other}}. get_qualified_name(Tag) -> - case string:tokens(atom_to_list(Tag),":") of + case string:lexemes(atom_to_list(Tag),":") of [TagStr] -> {[],TagStr}; [PrefixStr,TagStr] -> {PrefixStr,TagStr} end. diff --git a/lib/common_test/src/ct_release_test.erl b/lib/common_test/src/ct_release_test.erl index 551a7e06d7..4af9afb45b 100644 --- a/lib/common_test/src/ct_release_test.erl +++ b/lib/common_test/src/ct_release_test.erl @@ -817,7 +817,7 @@ get_runtime_deps([App|Apps],StartApps,Acc,Visited) -> RuntimeDeps = lists:flatmap( fun(Str) -> - [RuntimeAppStr,_] = string:tokens(Str,"-"), + [RuntimeAppStr,_] = string:lexemes(Str,"-"), RuntimeApp = list_to_atom(RuntimeAppStr), case {lists:keymember(RuntimeApp,1,Acc), lists:member(RuntimeApp,StartApps)} of diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 14f28f9ca3..9436236719 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -147,7 +147,7 @@ script_start(Args) -> CTVsn = case filename:basename(code:lib_dir(common_test)) of CTBase when is_list(CTBase) -> - case string:tokens(CTBase, "-") of + case string:lexemes(CTBase, "-") of ["common_test",Vsn] -> " v"++Vsn; _ -> "" end @@ -315,7 +315,7 @@ script_start1(Parent, Args) -> {undefined,InclDirs}; CtInclPath -> AllInclDirs = - string:tokens(CtInclPath,[$:,$ ,$,]) ++ InclDirs, + string:lexemes(CtInclPath,[$:,$ ,$,]) ++ InclDirs, application:set_env(common_test, include, AllInclDirs), {undefined,AllInclDirs} end; @@ -1096,7 +1096,7 @@ run_test2(StartOpts) -> application:set_env(common_test, include, InclDirs), {undefined,InclDirs}; CtInclPath -> - InclDirs1 = string:tokens(CtInclPath, [$:,$ ,$,]), + InclDirs1 = string:lexemes(CtInclPath, [$:,$ ,$,]), AllInclDirs = InclDirs1++InclDirs, application:set_env(common_test, include, AllInclDirs), {undefined,AllInclDirs} @@ -1482,7 +1482,7 @@ run_testspec2(TestSpec) -> false -> Opts#opts.include; CtInclPath -> - EnvInclude = string:tokens(CtInclPath, [$:,$ ,$,]), + EnvInclude = string:lexemes(CtInclPath, [$:,$ ,$,]), EnvInclude++Opts#opts.include end, application:set_env(common_test, include, AllInclude), diff --git a/lib/common_test/src/ct_ssh.erl b/lib/common_test/src/ct_ssh.erl index ca62357e1c..491d56dfc1 100644 --- a/lib/common_test/src/ct_ssh.erl +++ b/lib/common_test/src/ct_ssh.erl @@ -996,7 +996,8 @@ init(KeyOrName, {ConnType,Addr,Port}, AllOpts) -> try_log(heading(init,KeyOrName), "Opened ~w connection:\n" "Host: ~tp (~p)\nUser: ~tp\nPassword: ~p\n", - [ConnType,Addr,Port,User,lists:duplicate(length(Password),$*)]), + [ConnType,Addr,Port,User, + lists:duplicate(string:length(Password),$*)]), {ok,SSHRef,#state{ssh_ref=SSHRef, conn_type=ConnType, target=KeyOrName}} end. diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl index abf131f4df..3c0fead5b2 100644 --- a/lib/common_test/src/ct_util.erl +++ b/lib/common_test/src/ct_util.erl @@ -795,25 +795,25 @@ parse_table(Data) -> {Heading,Lines}. get_headings(["|" ++ Headings | Rest]) -> - {remove_space(string:tokens(Headings, "|"),[]), Rest}; + {remove_space(string:lexemes(Headings, "|"),[]), Rest}; get_headings([_ | Rest]) -> get_headings(Rest); get_headings([]) -> {{},[]}. parse_row(["|" ++ _ = Row | T], Rows, NumCols) when NumCols > 1 -> - case string:tokens(Row, "|") of + case string:lexemes(Row, "|") of Values when length(Values) =:= NumCols -> parse_row(T,[remove_space(Values,[])|Rows], NumCols); Values when length(Values) < NumCols -> parse_row([Row ++"\n"++ hd(T) | tl(T)], Rows, NumCols) end; -parse_row(["|" ++ _ = Row | T], Rows, 1 = NumCols) -> - case string:rchr(Row, $|) of - 1 -> +parse_row(["|" ++ X = Row | T], Rows, 1 = NumCols) -> + case string:find(X, [$|]) of + nomatch -> parse_row([Row ++"\n"++hd(T) | tl(T)], Rows, NumCols); _Else -> - parse_row(T, [remove_space(string:tokens(Row,"|"),[])|Rows], + parse_row(T, [remove_space(string:lexemes(Row,"|"),[])|Rows], NumCols) end; parse_row([_Skip | T], Rows, NumCols) -> @@ -822,7 +822,7 @@ parse_row([], Rows, _NumCols) -> lists:reverse(Rows). remove_space([Str|Rest],Acc) -> - remove_space(Rest,[string:strip(string:strip(Str),both,$')|Acc]); + remove_space(Rest,[string:trim(string:trim(Str,both,[$\s]),both,[$'])|Acc]); remove_space([],Acc) -> list_to_tuple(lists:reverse(Acc)). @@ -832,7 +832,7 @@ remove_space([],Acc) -> %%% %%% @doc is_test_dir(Dir) -> - lists:last(string:tokens(filename:basename(Dir), "_")) == "test". + lists:last(string:lexemes(filename:basename(Dir), "_")) == "test". %%%----------------------------------------------------------------- %%% @spec @@ -1077,7 +1077,7 @@ open_url(iexplore, Args, URL) -> _ = case win32reg:values(R) of {ok, Paths} -> Path = proplists:get_value(default, Paths), - [Cmd | _] = string:tokens(Path, "%"), + [Cmd | _] = string:lexemes(Path, "%"), Cmd1 = Cmd ++ " " ++ Args ++ " " ++ URL, io:format(?def_gl, "~nOpening ~ts with command:~n ~ts~n", [URL,Cmd1]), open_port({spawn,Cmd1}, []); diff --git a/lib/common_test/src/cth_surefire.erl b/lib/common_test/src/cth_surefire.erl index da68bd105e..4407ff56c1 100644 --- a/lib/common_test/src/cth_surefire.erl +++ b/lib/common_test/src/cth_surefire.erl @@ -184,15 +184,14 @@ end_tc(Name, _Config, _Res, State = #state{ curr_suite = Suite, Log = case Log0 of "" -> - LowerSuiteName = string:to_lower(atom_to_list(Suite)), + LowerSuiteName = string:lowercase(atom_to_list(Suite)), filename:join(CurrLogDir,LowerSuiteName++"."++Name++".html"); _ -> Log0 end, Url = make_url(UrlBase,Log), ClassName = atom_to_list(Suite), - PGroup = string:join([ atom_to_list(Group)|| - Group <- lists:reverse(Groups)],"."), + PGroup = lists:concat(lists:join(".",lists:reverse(Groups))), TimeTakes = io_lib:format("~f",[timer:now_diff(?now,TS) / 1000000]), State#state{ test_cases = [#testcase{ log = Log, url = Url, @@ -317,9 +316,9 @@ make_url(undefined,_) -> make_url(_,[]) -> undefined; make_url(UrlBase0,Log) -> - UrlBase = string:strip(UrlBase0,right,$/), + UrlBase = string:trim(UrlBase0,trailing,[$/]), RelativeLog = get_relative_log_url(Log), - string:join([UrlBase,RelativeLog],"/"). + lists:flatten(lists:join($/,[UrlBase,RelativeLog])). get_test_root(Log) -> LogParts = filename:split(Log), @@ -329,7 +328,7 @@ get_relative_log_url(Log) -> LogParts = filename:split(Log), Start = length(LogParts)-?log_depth, Length = ?log_depth+1, - string:join(lists:sublist(LogParts,Start,Length),"/"). + lists:flatten(lists:join($/,lists:sublist(LogParts,Start,Length))). count_tcs([#testcase{name=ConfCase}|TCs],Ok,F,S) when ConfCase=="init_per_suite"; diff --git a/lib/common_test/src/test_server.erl b/lib/common_test/src/test_server.erl index dc6b7a536c..35a73e6d2e 100644 --- a/lib/common_test/src/test_server.erl +++ b/lib/common_test/src/test_server.erl @@ -462,11 +462,12 @@ run_test_case_msgloop(#st{ref=Ref,pid=Pid,end_conf_pid=EndConfPid0}=St0) -> %% it as a comment, potentially replacing user data Error = lists:flatten(io_lib:format("Aborted: ~tp", [Reason])), - Error1 = lists:flatten([string:strip(S,left) || - S <- string:tokens(Error, - [$\n])]), - Comment = if length(Error1) > 63 -> - string:substr(Error1,1,60) ++ "..."; + Error1 = lists:flatten([string:trim(S,leading,"\s") || + S <- string:lexemes(Error, + [$\n])]), + ErrorLength = string:length(Error1), + Comment = if ErrorLength > 63 -> + string:slice(Error1,0,60) ++ "..."; true -> Error1 end, @@ -2697,9 +2698,9 @@ is_cover() -> is_debug() -> case catch erlang:system_info(debug_compiled) of {'EXIT', _} -> - case string:str(erlang:system_info(system_version), "debug") of - Int when is_integer(Int), Int > 0 -> true; - _ -> false + case string:find(erlang:system_info(system_version), "debug") of + nomatch -> false; + _ -> true end; Res -> Res @@ -2735,9 +2736,9 @@ has_superfluous_schedulers() -> %% We might want to do more tests on a commercial platform, for instance %% ensuring that all applications have documentation). is_commercial() -> - case string:str(erlang:system_info(system_version), "source") of - Int when is_integer(Int), Int > 0 -> false; - _ -> true + case string:find(erlang:system_info(system_version), "source") of + nomatch -> true; + _ -> false end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/common_test/src/test_server_ctrl.erl b/lib/common_test/src/test_server_ctrl.erl index 71978c7267..c70ea4ef9d 100644 --- a/lib/common_test/src/test_server_ctrl.erl +++ b/lib/common_test/src/test_server_ctrl.erl @@ -1464,13 +1464,14 @@ get_suites([], Mods) -> lists:reverse(Mods). add_mod(Mod, Mods) -> - case string:rstr(atom_to_list(Mod), "_SUITE") of - 0 -> false; - _ -> % test suite + case lists:reverse(atom_to_list(Mod)) of + "ETIUS_" ++ _ -> % test suite case lists:member(Mod, Mods) of true -> false; false -> true - end + end; + _ -> + false end. @@ -2611,7 +2612,7 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0, NumStr -> %% Ex: "123 456 789" or "123,456,789" -> {123,456,789} list_to_tuple([list_to_integer(NS) || - NS <- string:tokens(NumStr, [$ ,$:,$,])]) + NS <- string:lexemes(NumStr, [$ ,$:,$,])]) end, {shuffle_cases(Ref, Cs0, UseSeed),{shuffle,UseSeed}} end; @@ -3979,11 +3980,12 @@ progress(skip, CaseNum, Mod, Func, GrName, Loc, Reason, Time, true -> "~w" end, [Time]), ReasonStr = escape_chars(reason_to_string(Reason1)), - ReasonStr1 = lists:flatten([string:strip(S,left) || - S <- string:tokens(ReasonStr,[$\n])]), + ReasonStr1 = lists:flatten([string:trim(S,leading,"\s") || + S <- string:lexemes(ReasonStr,[$\n])]), + ReasonLength = string:length(ReasonStr1), ReasonStr2 = - if length(ReasonStr1) > 80 -> - string:substr(ReasonStr1, 1, 77) ++ "..."; + if ReasonLength > 80 -> + string:slice(ReasonStr1, 0, 77) ++ "..."; true -> ReasonStr1 end, @@ -4067,11 +4069,12 @@ progress(failed, CaseNum, Mod, Func, GrName, unknown, Reason, Time, true -> "~w" end, [Time]), ErrorReason = escape_chars(lists:flatten(io_lib:format("~tp", [Reason]))), - ErrorReason1 = lists:flatten([string:strip(S,left) || - S <- string:tokens(ErrorReason,[$\n])]), + ErrorReason1 = lists:flatten([string:trim(S,leading,"\s") || + S <- string:lexemes(ErrorReason,[$\n])]), + ErrorReasonLength = string:length(ErrorReason1), ErrorReason2 = - if length(ErrorReason1) > 63 -> - string:substr(ErrorReason1, 1, 60) ++ "..."; + if ErrorReasonLength > 63 -> + string:slice(ErrorReason1, 0, 60) ++ "..."; true -> ErrorReason1 end, diff --git a/lib/common_test/src/test_server_node.erl b/lib/common_test/src/test_server_node.erl index c0d7e12721..f0f9cea6e0 100644 --- a/lib/common_test/src/test_server_node.erl +++ b/lib/common_test/src/test_server_node.erl @@ -315,9 +315,11 @@ start_node_peer(SlaveName, OptList, From, TI) -> Prog0 = start_node_get_option_value(erl, OptList, default), Prog = quote_progname(pick_erl_program(Prog0)), Args = - case string:str(SuppliedArgs,"-setcookie") of - 0 -> "-setcookie " ++ TI#target_info.cookie ++ " " ++ SuppliedArgs; - _ -> SuppliedArgs + case string:find(SuppliedArgs,"-setcookie") of + nomatch -> + "-setcookie " ++ TI#target_info.cookie ++ " " ++ SuppliedArgs; + _ -> + SuppliedArgs end, Cmd = lists:concat([Prog, " -detached ", @@ -612,7 +614,7 @@ pick_erl_program(L) -> %% emulator and flags as the test node. The return from lib:progname() %% could then typically be '/<full_path_to>/cerl -gcov'). quote_progname(Progname) -> - do_quote_progname(string:tokens(Progname," ")). + do_quote_progname(string:lexemes(Progname," ")). do_quote_progname([Prog]) -> "\""++Prog++"\""; diff --git a/lib/common_test/src/unix_telnet.erl b/lib/common_test/src/unix_telnet.erl index 8ac467014c..5992f26e6d 100644 --- a/lib/common_test/src/unix_telnet.erl +++ b/lib/common_test/src/unix_telnet.erl @@ -121,7 +121,8 @@ connect1(Name,Ip,Port,Timeout,KeepAlive,TCPNoDelay,Username,Password) -> prompt,?prx,[]) of {ok,{prompt,?password},_} -> ok = ct_telnet_client:send_data(Pid,Password), - Stars = lists:duplicate(length(Password),$*), + Stars = + lists:duplicate(string:length(Password),$*), log(Name,send,"Password: ~s",[Stars]), % ok = ct_telnet_client:send_data(Pid,""), case ct_telnet:silent_teln_expect(Name,Pid,[], diff --git a/lib/common_test/test/ct_config_SUITE.erl b/lib/common_test/test/ct_config_SUITE.erl index 250700741c..5ffc735d6a 100644 --- a/lib/common_test/test/ct_config_SUITE.erl +++ b/lib/common_test/test/ct_config_SUITE.erl @@ -213,8 +213,8 @@ reformat_events(Events, EH) -> skip_dynamic() -> case os:getenv("TS_EXTRA_PLATFORM_LABEL") of TSExtraPlatformLabel when is_list(TSExtraPlatformLabel) -> - case string:str(TSExtraPlatformLabel,"TimeWarpingOS") of - 0 -> false; + case string:find(TSExtraPlatformLabel,"TimeWarpingOS") of + nomatch -> false; _ -> true end; _ -> diff --git a/lib/common_test/test/ct_hooks_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE.erl index 8ba14e63bc..3c1e887f65 100644 --- a/lib/common_test/test/ct_hooks_SUITE.erl +++ b/lib/common_test/test/ct_hooks_SUITE.erl @@ -257,7 +257,7 @@ cth_log(Config) when is_list(Config) -> lists:foreach( fun(UnexpIoLog) -> {ok,Bin} = file:read_file(UnexpIoLog), - Ts = string:tokens(binary_to_list(Bin),[$\n]), + Ts = string:lexemes(binary_to_list(Bin),[$\n]), Matches = lists:foldl(fun([$=,$E,$R,$R,$O,$R|_], N) -> N+1; ([$L,$o,$g,$g,$e,$r|_], N) -> diff --git a/lib/common_test/test/ct_log_SUITE.erl b/lib/common_test/test/ct_log_SUITE.erl index 93affda398..9655b6f09a 100644 --- a/lib/common_test/test/ct_log_SUITE.erl +++ b/lib/common_test/test/ct_log_SUITE.erl @@ -174,7 +174,7 @@ verify(Config) -> TcLogFile = proplists:get_value(the_logfile, SavedCfg), Pid = proplists:get_value(the_pid, SavedCfg), StrPid = lists:flatten(io_lib:format("~p",[Pid])), - EscPid = "<" ++ string:substr(StrPid, 2, length(StrPid)-2) ++ ">", + EscPid = "<" ++ string:slice(StrPid, 1, length(StrPid)-2) ++ ">", String = proplists:get_value(the_string, SavedCfg), ct:log("Read from prev testcase: ~p & ~p", [TcLogFile,Pid]), {ok,Dev} = file:open(TcLogFile, [read]), diff --git a/lib/common_test/test/ct_pre_post_test_io_SUITE.erl b/lib/common_test/test/ct_pre_post_test_io_SUITE.erl index 7ffe6f045b..0b85392009 100644 --- a/lib/common_test/test/ct_pre_post_test_io_SUITE.erl +++ b/lib/common_test/test/ct_pre_post_test_io_SUITE.erl @@ -164,7 +164,7 @@ pre_post_io(Config) -> fun(PrePostIoFile) -> ct:log("Reading Pre/Post Test IO Log file: ~ts", [PrePostIoFile]), {ok,Bin} = file:read_file(PrePostIoFile), - Ts = string:tokens(binary_to_list(Bin),[$\n]), + Ts = string:lexemes(binary_to_list(Bin),[$\n]), PrePostIOEntries = lists:foldl(fun([$L,$o,$g,$g,$e,$r|_], {pre,PreLogN,PreErrN,0,0}) -> @@ -203,7 +203,7 @@ pre_post_io(Config) -> fun(UnexpIoFile) -> ct:log("Reading Unexpected IO Log file: ~ts", [UnexpIoFile]), {ok,Bin} = file:read_file(UnexpIoFile), - Ts = string:tokens(binary_to_list(Bin),[$\n]), + Ts = string:lexemes(binary_to_list(Bin),[$\n]), UnexpIOEntries = lists:foldl(fun([$L,$o,$g,$g,$e,$r|_], [LogN,ErrN]) -> [LogN+1,ErrN]; diff --git a/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl b/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl index 1b171801a3..b1d191873d 100644 --- a/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl +++ b/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl @@ -126,12 +126,12 @@ default(Config) -> auto_per_tc(Config) -> PrivDir = proplists:get_value(priv_dir, Config), - ["log_private",_] = string:tokens(filename:basename(PrivDir), "."), + ["log_private",_] = string:lexemes(filename:basename(PrivDir), "."), {ok,_} = file:list_dir(PrivDir). manual_per_tc(Config) -> PrivDir = proplists:get_value(priv_dir, Config), - ["log_private",_] = string:tokens(filename:basename(PrivDir), "."), + ["log_private",_] = string:lexemes(filename:basename(PrivDir), "."), {error,_} = file:list_dir(PrivDir), ok = ct:make_priv_dir(), {ok,_} = file:list_dir(PrivDir). diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl index 44c27e54c2..2ba7c7c13f 100644 --- a/lib/common_test/test/ct_test_support.erl +++ b/lib/common_test/test/ct_test_support.erl @@ -88,7 +88,7 @@ start_slave(Config, Level) -> start_slave(ct, Config, Level). start_slave(NodeName, Config, Level) -> - [_,Host] = string:tokens(atom_to_list(node()), "@"), + [_,Host] = string:lexemes(atom_to_list(node()), "@"), test_server:format(0, "Trying to start ~s~n", [atom_to_list(NodeName)++"@"++Host]), PR = proplists:get_value(printable_range,Config,io:printable_range()), @@ -1088,8 +1088,8 @@ locate({TEH,Name,{'DEF','RUNDIR'}}, Node, [Ev|Evs], Config) -> {TEH,#event{name=Name, node=Node, data=EvData}} -> {_,{_,LogDir}} = lists:keysearch(logdir, 1, get_opts(Config)), D = filename:join(LogDir, "ct_run." ++ atom_to_list(Node)), - case string:str(EvData, D) of - 0 -> exit({badmatch,EvData}); + case string:find(EvData, D) of + nomatch -> exit({badmatch,EvData}); _ -> ok end, {Config,Evs}; @@ -1104,8 +1104,8 @@ locate({TEH,Name,{'DEF',{'START_TIME','LOGDIR'}}}, Node, [Ev|Evs], Config) -> {DT={{_,_,_},{_,_,_}},Dir} when is_list(Dir) -> {_,{_,LogDir}} = lists:keysearch(logdir, 1, get_opts(Config)), D = filename:join(LogDir, "ct_run." ++ atom_to_list(Node)), - case string:str(Dir, D) of - 0 -> exit({badmatch,Dir}); + case string:find(Dir, D) of + nomatch -> exit({badmatch,Dir}); _ -> ok end, {[{start_time,DT}|Config],Evs}; @@ -1373,7 +1373,7 @@ delete_dirs(LogDir) -> Dirs2Del = lists:foldl(fun(Dir, Del) -> [S,Mi,H,D,Mo,Y|_] = - lists:reverse(string:tokens(Dir, [$.,$-,$_])), + lists:reverse(string:lexemes(Dir, [$.,$-,$_])), S2I = fun(Str) -> list_to_integer(Str) end, DT = {{S2I(Y),S2I(Mo),S2I(D)}, {S2I(H),S2I(Mi),S2I(S)}}, Then = calendar:datetime_to_gregorian_seconds(DT), diff --git a/lib/common_test/test/ct_unicode_SUITE.erl b/lib/common_test/test/ct_unicode_SUITE.erl index 355503a5dc..6f6ec97ceb 100644 --- a/lib/common_test/test/ct_unicode_SUITE.erl +++ b/lib/common_test/test/ct_unicode_SUITE.erl @@ -191,7 +191,7 @@ check_logs(Dirs) -> [] -> ok; Match -> - MatchStr = string:join(Match,"\n"), + MatchStr = lists:join("\n",Match), ct:log("ERROR: Escaped unicode characters found in:~n~ts",[MatchStr]), ct:fail(escaped_unicode_characters_found) end. diff --git a/lib/common_test/test/ct_userconfig_callback.erl b/lib/common_test/test/ct_userconfig_callback.erl index c723f4ca1c..14e3d9a688 100644 --- a/lib/common_test/test/ct_userconfig_callback.erl +++ b/lib/common_test/test/ct_userconfig_callback.erl @@ -21,7 +21,7 @@ -export([check_parameter/1, read_config/1]). read_config(Str) -> - KeyVals = string:tokens(Str, " "), + KeyVals = string:lexemes(Str, " "), {ok,read_config1(KeyVals)}. read_config1([Key,Val | KeyVals]) -> diff --git a/lib/common_test/test/erl2html2_SUITE.erl b/lib/common_test/test/erl2html2_SUITE.erl index 53a63578b2..b2336ff0bc 100644 --- a/lib/common_test/test/erl2html2_SUITE.erl +++ b/lib/common_test/test/erl2html2_SUITE.erl @@ -214,10 +214,10 @@ check_line_number(Last,Line,OrigLine) -> [$>|Rest] = lists:dropwhile(fun($>) -> false; (_) -> true end,Line), check_line_number(Last,Rest,OrigLine); _ -> - [N |_] = string:tokens(Line,":"), + [N |_] = string:lexemes(Line,":"), % erlang:display(N), Num = - try list_to_integer(string:strip(N)) + try list_to_integer(string:trim(N,both,"\s")) catch _:_ -> ct:fail({no_line_number_after,Last,OrigLine}) end, if Num == Last+1 -> diff --git a/lib/common_test/test/telnet_server.erl b/lib/common_test/test/telnet_server.erl index 65300b0bdf..cef7784333 100644 --- a/lib/common_test/test/telnet_server.erl +++ b/lib/common_test/test/telnet_server.erl @@ -249,7 +249,7 @@ do_handle_data("echo " ++ Data,State) -> send(Data++"\r\n> ",State), {ok,State}; do_handle_data("echo_sep " ++ Data,State) -> - Msgs = string:tokens(Data," "), + Msgs = string:lexemes(Data," "), lists:foreach(fun(Msg) -> send(Msg,State), timer:sleep(10) @@ -260,28 +260,28 @@ do_handle_data("echo_no_prompt " ++ Data,State) -> send(Data,State), {ok,State}; do_handle_data("echo_ml " ++ Data,State) -> - Lines = string:tokens(Data," "), - ReturnData = string:join(Lines,"\n"), + Lines = string:lexemes(Data," "), + ReturnData = lists:flatten(lists:join("\n",Lines)), send(ReturnData++"\r\n> ",State), {ok,State}; do_handle_data("echo_ml_no_prompt " ++ Data,State) -> - Lines = string:tokens(Data," "), - ReturnData = string:join(Lines,"\n"), + Lines = string:lexemes(Data," "), + ReturnData = lists:flatten(lists:join("\n",Lines)), send(ReturnData,State), {ok,State}; do_handle_data("echo_loop " ++ Data,State) -> - [TStr|Lines] = string:tokens(Data," "), - ReturnData = string:join(Lines,"\n"), + [TStr|Lines] = string:lexemes(Data," "), + ReturnData = lists:flatten(lists:join("\n",Lines)), send_loop(list_to_integer(TStr),ReturnData,State), {ok,State}; do_handle_data("echo_delayed_prompt "++Data,State) -> - [MsStr|EchoData] = string:tokens(Data, " "), - send(string:join(EchoData,"\n"),State), + [MsStr|EchoData] = string:lexemes(Data, " "), + send(lists:flatten(lists:join("\n",EchoData)),State), timer:sleep(list_to_integer(MsStr)), send("\r\n> ",State), {ok,State}; do_handle_data("disconnect_after " ++WaitStr,State) -> - Wait = list_to_integer(string:strip(WaitStr,right,$\n)), + Wait = list_to_integer(string:trim(WaitStr,trailing,"\n")), dbg("Server will close connection in ~w ms...", [Wait]), erlang:send_after(Wait,self(),disconnect), {ok,State}; diff --git a/lib/common_test/test/test_server_SUITE.erl b/lib/common_test/test/test_server_SUITE.erl index 50d8bdd1ac..edfaea1d08 100644 --- a/lib/common_test/test/test_server_SUITE.erl +++ b/lib/common_test/test/test_server_SUITE.erl @@ -71,7 +71,7 @@ init_per_testcase(_TestCase, Config) -> %% @spec end_per_testcase(TestCase, Config0) -> %% void() | {save_config,Config1} | {fail,Reason} end_per_testcase(test_server_unicode, _Config) -> - [_,Host] = string:tokens(atom_to_list(node()), "@"), + [_,Host] = string:lexemes(atom_to_list(node()), "@"), N1 = list_to_atom("test_server_tester_latin1" ++ "@" ++ Host), N2 = list_to_atom("test_server_tester_utf8" ++ "@" ++ Host), test_server:stop_node(N1), @@ -347,7 +347,7 @@ generate_and_run_unicode_test(Config0,Encoding) -> RunDir = get_latest_run_dir(LogDir), true = filelib:is_dir(RunDir), - LowerModStr = string:to_lower(ModStr), + LowerModStr = string:lowercase(ModStr), SuiteHtml = translate_filename(LowerModStr++".src.html",Encoding), true = filelib:is_regular(filename:join(RunDir,SuiteHtml)), @@ -362,7 +362,7 @@ generate_and_run_unicode_test(Config0,Encoding) -> %% remote file system on master - i.e. they will use same file name %% mode as the master. start_node(Config,Name,Args) -> - [_,Host] = string:tokens(atom_to_list(node()), "@"), + [_,Host] = string:lexemes(atom_to_list(node()), "@"), ct:log("Trying to start ~w@~s~n",[Name,Host]), case test_server:start_node(Name, peer, [{args,Args}]) of {error,Reason} -> diff --git a/lib/common_test/test/test_server_test_lib.erl b/lib/common_test/test/test_server_test_lib.erl index c18b89b178..e3d987a2ea 100644 --- a/lib/common_test/test/test_server_test_lib.erl +++ b/lib/common_test/test/test_server_test_lib.erl @@ -43,7 +43,7 @@ pre_init_per_testcase(_TC,Config,State) -> {start_slave(Config, 50),State}. start_slave(Config,_Level) -> - [_,Host] = string:tokens(atom_to_list(node()), "@"), + [_,Host] = string:lexemes(atom_to_list(node()), "@"), ct:log("Trying to start ~s~n", ["test_server_tester@"++Host]), diff --git a/lib/common_test/test_server/ts.erl b/lib/common_test/test_server/ts.erl index 5bfea9f4de..330652e73f 100644 --- a/lib/common_test/test_server/ts.erl +++ b/lib/common_test/test_server/ts.erl @@ -583,7 +583,7 @@ is_list_of_suites(List) -> S = if is_atom(Suite) -> atom_to_list(Suite); true -> Suite end, - try lists:last(string:tokens(S,"_")) of + try lists:last(string:lexemes(S,"_")) of "SUITE" -> true; "suite" -> true; _ -> false diff --git a/lib/common_test/test_server/ts_autoconf_win32.erl b/lib/common_test/test_server/ts_autoconf_win32.erl index 52e5ac8e69..6f6caaeb70 100644 --- a/lib/common_test/test_server/ts_autoconf_win32.erl +++ b/lib/common_test/test_server/ts_autoconf_win32.erl @@ -228,7 +228,7 @@ make(Vars) -> end. find_make(MakeCmd, Vars) -> - [Make|_] = string:tokens(MakeCmd, " \t"), + [Make|_] = string:lexemes(MakeCmd, " \t"), case os:find_executable(Make) of false -> {no, Vars}; @@ -248,9 +248,9 @@ javac(Vars) -> end. is_debug_build() -> - case catch string:str(erlang:system_info(system_version), "debug") of - Int when is_integer(Int), Int > 0 -> - true; - _ -> - false + case catch string:find(erlang:system_info(system_version), "debug") of + nomatch -> + false; + _Else -> + true end. diff --git a/lib/common_test/test_server/ts_erl_config.erl b/lib/common_test/test_server/ts_erl_config.erl index 032593bdda..c7fe4ccf83 100644 --- a/lib/common_test/test_server/ts_erl_config.erl +++ b/lib/common_test/test_server/ts_erl_config.erl @@ -311,7 +311,7 @@ lib_dir(Vars, Lib) -> end, CLibDir = filename:join(CLibDirList), Cmd = "ls -d " ++ CLibDir ++ "*", - XLibDir = lists:last(string:tokens(os:cmd(Cmd),"\n")), + XLibDir = lists:last(string:lexemes(os:cmd(Cmd),"\n")), case file:list_dir(XLibDir) of {error, enoent} -> []; @@ -361,15 +361,11 @@ emu_vars(Vars) -> {erl_name, atom_to_list(lib:progname())}|Vars]. is_source_build() -> - string:str(erlang:system_info(system_version), "[source]") > 0. + string:find(erlang:system_info(system_version), "source") =/= nomatch. is_debug_build() -> - case catch string:str(erlang:system_info(system_version), "debug") of - Int when is_integer(Int), Int > 0 -> - true; - _ -> - false - end. + string:find(erlang:system_info(system_version), "debug") =/= nomatch. + %% %% ssl_libdir %% diff --git a/lib/common_test/test_server/ts_install.erl b/lib/common_test/test_server/ts_install.erl index c5631fb9c3..048e5493d2 100644 --- a/lib/common_test/test_server/ts_install.erl +++ b/lib/common_test/test_server/ts_install.erl @@ -115,7 +115,7 @@ get_vars(_, _, _, _) -> config_flags() -> case os:getenv("CONFIG_FLAGS") of false -> []; - CF -> string:tokens(CF, " \t\n") + CF -> string:lexemes(CF, " \t\n") end. unix_autoconf(XConf) -> @@ -127,7 +127,7 @@ unix_autoconf(XConf) -> Threads = [" --enable-shlib-thread-safety" || erlang:system_info(threads) /= false], Debug = [" --enable-debug-mode" || - string:str(erlang:system_info(system_version),"debug") > 0], + string:find(erlang:system_info(system_version),"debug") =/= nomatch], MXX_Build = [Y || Y <- config_flags(), Y == "--enable-m64-build" orelse Y == "--enable-m32-build"], @@ -159,10 +159,8 @@ assign_vars([]) -> assign_vars([{VAR,FlagsStr} | VARs]) -> [{VAR,assign_vars(FlagsStr)} | assign_vars(VARs)]; assign_vars(FlagsStr) -> - Flags = [assign_all_vars(Str,[]) || Str <- string:tokens(FlagsStr, [$ ])], - string:strip(lists:flatten(lists:map(fun(Flag) -> - Flag ++ " " - end, Flags)), right). + Flags = [assign_all_vars(Str,[]) || Str <- string:lexemes(FlagsStr, [$\s])], + lists:flatten(lists:join(" ", Flags)). assign_all_vars([$$ | Rest], FlagSoFar) -> {VarName,Rest1} = get_var_name(Rest, []), @@ -292,7 +290,7 @@ add_vars(Vars0, Opts0) -> get_testcase_callback() -> case os:getenv("TS_TESTCASE_CALLBACK") of ModFunc when is_list(ModFunc), ModFunc /= "" -> - case string:tokens(ModFunc, " ") of + case string:lexemes(ModFunc, " ") of [_Mod,_Func] -> ModFunc; _ -> "" end; @@ -430,8 +428,8 @@ bind_type() -> debug() -> - case string:str(erlang:system_info(system_version), "debug") of - 0 -> ""; + case string:find(erlang:system_info(system_version), "debug") of + nomatch -> ""; _ -> "/Debug" end. diff --git a/lib/common_test/test_server/ts_lib.erl b/lib/common_test/test_server/ts_lib.erl index ea039a2c2b..da8d676b18 100644 --- a/lib/common_test/test_server/ts_lib.erl +++ b/lib/common_test/test_server/ts_lib.erl @@ -99,7 +99,7 @@ specialized_specs(Dir,PostFix) -> sort_tests([begin DirPart = filename:dirname(Name), AppTest = hd(lists:reverse(filename:split(DirPart))), - list_to_atom(string:substr(AppTest, 1, length(AppTest)-5)) + list_to_atom(string:slice(AppTest, 0, string:length(AppTest)-5)) end || Name <- Specs]). specs(Dir) -> @@ -111,9 +111,9 @@ specs(Dir) -> [Spec,TestDir|_] = lists:reverse(filename:split(FullName)), [_TestSuffix|TDParts] = - lists:reverse(string:tokens(TestDir,[$_,$.])), + lists:reverse(string:lexemes(TestDir,[$_,$.])), [_SpecSuffix|SParts] = - lists:reverse(string:tokens(Spec,[$_,$.])), + lists:reverse(string:lexemes(Spec,[$_,$.])), if TDParts == SParts -> [filename_to_atom(FullName)]; true -> @@ -273,7 +273,7 @@ do_test(Rest, Vars, Test) -> get_arg([$(|Rest], Vars, Stop, _) -> get_arg(Rest, Vars, Stop, []); get_arg([Stop|Rest], Vars, Stop, Acc) -> - Arg = string:strip(lists:reverse(Acc)), + Arg = string:trim(lists:reverse(Acc),both,[$\s]), Subst = subst(Arg, Vars), {Subst,Rest}; get_arg([C|Rest], Vars, Stop, Acc) -> diff --git a/lib/common_test/test_server/ts_run.erl b/lib/common_test/test_server/ts_run.erl index 2736010551..3f594236bc 100644 --- a/lib/common_test/test_server/ts_run.erl +++ b/lib/common_test/test_server/ts_run.erl @@ -464,4 +464,4 @@ split_one(Path) -> filename:split(Path). split_path(Path) -> - string:tokens(Path,";"). + string:lexemes(Path,";"). diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk index 9fc3f7f797..7b959ebfe3 100644 --- a/lib/common_test/vsn.mk +++ b/lib/common_test/vsn.mk @@ -1 +1 @@ -COMMON_TEST_VSN = 1.15.1 +COMMON_TEST_VSN = 1.15.2 diff --git a/lib/compiler/doc/src/compile.xml b/lib/compiler/doc/src/compile.xml index 10164890f2..b398871ddf 100644 --- a/lib/compiler/doc/src/compile.xml +++ b/lib/compiler/doc/src/compile.xml @@ -123,6 +123,17 @@ in the Efficiency Guide.</p> </item> + <tag><c>{compile_info, [{atom(), term()}]}</c></tag> + <item> + <p>Allows compilers built on top of <c>compile</c> to attach + extra compilation metadata to the <c>compile_info</c> chunk + in the generated beam file.</p> + + <p>It is advised for compilers to remove all non-deterministic + information if the <c>deterministic</c> option is supported and + it was supplied by the user.</p> + </item> + <tag><c>compressed</c></tag> <item> <p>The compiler will compress the generated object code, diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml index bc335a9eaa..9b32ec54c4 100644 --- a/lib/compiler/doc/src/notes.xml +++ b/lib/compiler/doc/src/notes.xml @@ -32,6 +32,61 @@ <p>This document describes the changes made to the Compiler application.</p> +<section><title>Compiler 7.1.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Fail labels on guard BIFs weren't taken into account + during an optimization pass, and a bug in the validation + pass sometimes prevented this from being noticed when a + fault occurred.</p> + <p> + Own Id: OTP-14522 Aux Id: ERIERL-48 </p> + </item> + <item> + <p> + When compiling from Core Erlang, an 'apply' with a nested + apply in the function position would be treated as an + invalid call. Corrected. (Thanks to Mikael Pettersson for + reporting this bug.)</p> + <p> + Own Id: OTP-14526</p> + </item> + <item> + <p>Fixed checking of binary matching in the + <c>beam_validator</c> module to ensure that potential + compiler bugs are found at compile-time instead as + emulator crash at run-time.</p> + <p> + Own Id: OTP-14591</p> + </item> + <item> + <p>There could be false warnings for + <c>erlang:get_stacktrace/0</c> being used outside of a + <c>try</c> block when using multiple <c>catch</c> + clauses.</p> + <p> + Own Id: OTP-14600 Aux Id: ERL-478 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> The Erlang code linter no longer checks that the + functions mentioned in <c>nowarn_deprecated_function</c> + options are declared in the module. </p> + <p> + Own Id: OTP-14378</p> + </item> + </list> + </section> + +</section> + <section><title>Compiler 7.1.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/compiler/src/beam_asm.erl b/lib/compiler/src/beam_asm.erl index c35efdfc9d..9ecbb7884c 100644 --- a/lib/compiler/src/beam_asm.erl +++ b/lib/compiler/src/beam_asm.erl @@ -21,7 +21,7 @@ -module(beam_asm). --export([module/5]). +-export([module/4]). -export([encode/2]). -export_type([fail/0,label/0,reg/0,src/0,module_code/0,function_name/0]). @@ -55,20 +55,20 @@ -type module_code() :: {module(),[_],[_],[asm_function()],pos_integer()}. --spec module(module_code(), [{binary(), binary()}], [_], [compile:option()], [compile:option()]) -> +-spec module(module_code(), [{binary(), binary()}], [{atom(),term()}], [compile:option()]) -> {'ok',binary()}. -module(Code, ExtraChunks, SourceFile, Opts, CompilerOpts) -> - {ok,assemble(Code, ExtraChunks, SourceFile, Opts, CompilerOpts)}. +module(Code, ExtraChunks, CompileInfo, CompilerOpts) -> + {ok,assemble(Code, ExtraChunks, CompileInfo, CompilerOpts)}. -assemble({Mod,Exp0,Attr0,Asm0,NumLabels}, ExtraChunks, SourceFile, Opts, CompilerOpts) -> +assemble({Mod,Exp0,Attr0,Asm0,NumLabels}, ExtraChunks, CompileInfo, CompilerOpts) -> {1,Dict0} = beam_dict:atom(Mod, beam_dict:new()), {0,Dict1} = beam_dict:fname(atom_to_list(Mod) ++ ".erl", Dict0), NumFuncs = length(Asm0), {Asm,Attr} = on_load(Asm0, Attr0), Exp = cerl_sets:from_list(Exp0), {Code,Dict2} = assemble_1(Asm, Exp, Dict1, []), - build_file(Code, Attr, Dict2, NumLabels, NumFuncs, ExtraChunks, SourceFile, Opts, CompilerOpts). + build_file(Code, Attr, Dict2, NumLabels, NumFuncs, ExtraChunks, CompileInfo, CompilerOpts). on_load(Fs0, Attr0) -> case proplists:get_value(on_load, Attr0) of @@ -111,7 +111,7 @@ assemble_function([H|T], Acc, Dict0) -> assemble_function([], Code, Dict) -> {Code, Dict}. -build_file(Code, Attr, Dict, NumLabels, NumFuncs, ExtraChunks, SourceFile, Opts, CompilerOpts) -> +build_file(Code, Attr, Dict, NumLabels, NumFuncs, ExtraChunks, CompileInfo, CompilerOpts) -> %% Create the code chunk. CodeChunk = chunk(<<"Code">>, @@ -182,7 +182,7 @@ build_file(Code, Attr, Dict, NumLabels, NumFuncs, ExtraChunks, SourceFile, Opts, Essentials1 = [iolist_to_binary(C) || C <- Essentials0], MD5 = module_md5(Essentials1), Essentials = finalize_fun_table(Essentials1, MD5), - {Attributes,Compile} = build_attributes(Opts, SourceFile, Attr, MD5), + {Attributes,Compile} = build_attributes(Attr, CompileInfo, MD5), AttrChunk = chunk(<<"Attr">>, Attributes), CompileChunk = chunk(<<"CInf">>, Compile), @@ -192,7 +192,7 @@ build_file(Code, Attr, Dict, NumLabels, NumFuncs, ExtraChunks, SourceFile, Opts, %% Create IFF chunk. - Chunks = case member(slim, Opts) of + Chunks = case member(slim, CompilerOpts) of true -> [Essentials,AttrChunk]; false -> @@ -264,22 +264,10 @@ flatten_exports(Exps) -> flatten_imports(Imps) -> list_to_binary(map(fun({M,F,A}) -> <<M:32,F:32,A:32>> end, Imps)). -build_attributes(Opts, SourceFile, Attr, MD5) -> - Misc0 = case SourceFile of - [] -> []; - [_|_] -> [{source,SourceFile}] - end, - Misc = case member(slim, Opts) of - false -> Misc0; - true -> [] - end, - Compile = case member(deterministic, Opts) of - false -> - [{options,Opts},{version,?COMPILER_VSN}|Misc]; - true -> - [{version,?COMPILER_VSN}] - end, - {term_to_binary(set_vsn_attribute(Attr, MD5)),term_to_binary(Compile)}. +build_attributes(Attr, Compile, MD5) -> + AttrBinary = term_to_binary(set_vsn_attribute(Attr, MD5)), + CompileBinary = term_to_binary([{version,?COMPILER_VSN}|Compile]), + {AttrBinary,CompileBinary}. build_line_table(Dict) -> {NumLineInstrs,NumFnames0,Fnames0,NumLines,Lines0} = diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index 00901077d3..be8908dd6b 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -1430,13 +1430,13 @@ merge_types(bool, {atom,A}) -> merge_bool(A); merge_types({atom,A}, bool) -> merge_bool(A); -merge_types(#ms{id=Id1,valid=B0,slots=Slots}, - #ms{id=Id2,valid=B1,slots=Slots}) -> +merge_types(#ms{id=Id1,valid=B1,slots=Slots1}, + #ms{id=Id2,valid=B2,slots=Slots2}) -> Id = if Id1 =:= Id2 -> Id1; true -> make_ref() end, - #ms{id=Id,valid=B0 band B1,slots=Slots}; + #ms{id=Id,valid=B1 band B2,slots=min(Slots1, Slots2)}; merge_types(T1, T2) when T1 =/= T2 -> %% Too different. All we know is that the type is a 'term'. term. diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl index ec7e7aed14..1b359d1e59 100644 --- a/lib/compiler/src/compile.erl +++ b/lib/compiler/src/compile.erl @@ -1448,15 +1448,33 @@ save_core_code(Code, St) -> beam_asm(Code0, #compile{ifile=File,extra_chunks=ExtraChunks,options=CompilerOpts}=St) -> case debug_info(St) of {ok,DebugInfo,Opts0} -> - Source = paranoid_absname(File), Opts1 = [O || O <- Opts0, effects_code_generation(O)], Chunks = [{<<"Dbgi">>, DebugInfo} | ExtraChunks], - {ok,Code} = beam_asm:module(Code0, Chunks, Source, Opts1, CompilerOpts), + CompileInfo = compile_info(File, Opts1), + {ok,Code} = beam_asm:module(Code0, Chunks, CompileInfo, CompilerOpts), {ok,Code,St#compile{abstract_code=[]}}; {error,Es} -> {error,St#compile{errors=St#compile.errors ++ [{File,Es}]}} end. +compile_info(File, Opts) -> + IsSlim = member(slim, Opts), + IsDeterministic = member(deterministic, Opts), + Info0 = proplists:get_value(compile_info, Opts, []), + Info1 = + case paranoid_absname(File) of + [_|_] = Source when not IsSlim, not IsDeterministic -> + [{source,Source} | Info0]; + _ -> + Info0 + end, + Info2 = + case IsDeterministic of + false -> [{options,proplists:delete(compile_info, Opts)} | Info1]; + true -> Info1 + end, + Info2. + paranoid_absname(""=File) -> File; paranoid_absname(File) -> diff --git a/lib/compiler/src/core_pp.erl b/lib/compiler/src/core_pp.erl index cff6c7098b..2516a9a1e1 100644 --- a/lib/compiler/src/core_pp.erl +++ b/lib/compiler/src/core_pp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2016. All Rights Reserved. +%% Copyright Ericsson AB 1999-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -464,7 +464,7 @@ indent(#ctxt{indent=N}) -> N =< 0 -> ""; true -> - string:chars($\t, N div ?TAB_WIDTH, spaces(N rem ?TAB_WIDTH)) + lists:duplicate(N div ?TAB_WIDTH, $\t) ++ spaces(N rem ?TAB_WIDTH) end. nl_indent(Ctxt) -> [$\n|indent(Ctxt)]. diff --git a/lib/compiler/src/core_scan.erl b/lib/compiler/src/core_scan.erl index 9f0676538f..a50a2ffa8d 100644 --- a/lib/compiler/src/core_scan.erl +++ b/lib/compiler/src/core_scan.erl @@ -200,8 +200,8 @@ pre_string(eof, Q, _, Sp, SoFar, Pos) -> pre_string_error(Q, Sp, SoFar, Pos). pre_string_error(Q, Sp, SoFar, Pos) -> - S = reverse(string:substr(SoFar, 1, string:chr(SoFar, Q)-1)), - pre_error({string,Q,string:substr(S, 1, 16)}, Sp, Pos). + [S,_] = string:split(SoFar, [Q]), + pre_error({string,Q,string:slice(string:reverse(S), 0, 16)}, Sp, Pos). pre_char([C|Cs], SoFar) -> pre_char(C, Cs, SoFar); pre_char([], _) -> more; diff --git a/lib/compiler/src/v3_kernel_pp.erl b/lib/compiler/src/v3_kernel_pp.erl index 53097d0d7d..ac91039ae0 100644 --- a/lib/compiler/src/v3_kernel_pp.erl +++ b/lib/compiler/src/v3_kernel_pp.erl @@ -491,7 +491,7 @@ indent(Ctxt) -> indent(Ctxt#ctxt.indent, Ctxt). indent(N, _Ctxt) when N =< 0 -> ""; indent(N, Ctxt) -> T = Ctxt#ctxt.tab_width, - string:chars($\t, N div T, string:chars($\s, N rem T)). + lists:duplicate(N div T, $\t) ++ lists:duplicate(N rem T, $\s). nl_indent(Ctxt) -> [$\n|indent(Ctxt)]. @@ -508,7 +508,7 @@ unindent([$\t|T], N, Ctxt, C) -> if N >= Tab -> unindent(T, N - Tab, Ctxt, C); true -> - unindent([string:chars($\s, Tab - N)|T], 0, Ctxt, C) + unindent([lists:duplicate(Tab - N, $\s)|T], 0, Ctxt, C) end; unindent([L|T], N, Ctxt, C) when is_list(L) -> unindent(L, N, Ctxt, [T|C]); diff --git a/lib/compiler/test/bs_match_SUITE.erl b/lib/compiler/test/bs_match_SUITE.erl index 1da7f68dab..ad48d4c0b7 100644 --- a/lib/compiler/test/bs_match_SUITE.erl +++ b/lib/compiler/test/bs_match_SUITE.erl @@ -39,7 +39,7 @@ match_string_opt/1,select_on_integer/1, map_and_binary/1,unsafe_branch_caching/1, bad_literals/1,good_literals/1,constant_propagation/1, - parse_xml/1,get_payload/1,escape/1]). + parse_xml/1,get_payload/1,escape/1,num_slots_different/1]). -export([coverage_id/1,coverage_external_ignore/2]). @@ -71,7 +71,7 @@ groups() -> match_string_opt,select_on_integer, map_and_binary,unsafe_branch_caching, bad_literals,good_literals,constant_propagation,parse_xml, - get_payload,escape]}]. + get_payload,escape,num_slots_different]}]. init_per_suite(Config) -> @@ -1539,6 +1539,40 @@ escape(<<Byte, Rest/bits>>, Pos) -> escape(<<_Rest/bits>>, Pos) -> Pos. +%% ERL-490 +num_slots_different(_Config) -> + Ts = [{<<"de">>, <<"default">>, <<"Remove">>, <<"a">>}, + {<<"de">>, <<"default">>, <<"Remove from list">>, <<"a">>}, + {<<"de">>, <<"default">>, <<"Remove from the list">>, <<"a">>}, + {<<"de">>, <<"default">>, <<"Results">>, <<"Ergebnisse">>}, + {<<"de">>, <<"default">>, <<"Reservatio">>, <<"a">>}, + {<<"de">>, <<"navigation">>, <<"Results">>, <<"Ergebnisse">>}, + {<<"de">>, <<"navigation">>, <<"Resources">>, <<"Ressourcen">>}], + _ = [{ok,Res} = lgettext(A, B, C) || {A,B,C,Res} <- Ts], + + {'EXIT',_} = (catch lgettext(<<"d">>, <<"default">>, <<"Remove">>)), + {'EXIT',_} = (catch lgettext("", <<"default">>, <<"Remove">>)), + {'EXIT',_} = (catch lgettext(<<"de">>, <<"def">>, <<"Remove">>)), + {'EXIT',_} = (catch lgettext(<<"de">>, <<"default">>, <<"Res">>)), + ok. + + +lgettext(<<"de">>, <<"default">>, <<"Remove">>) -> + {ok, <<"a">>}; +lgettext(<<"de">>, <<"default">>, <<"Remove from list">>) -> + {ok, <<"a">>}; +lgettext(<<"de">>, <<"default">>, <<"Remove from the list">>) -> + {ok, <<"a">>}; +lgettext(<<"de">>, <<"default">>, <<"Results">>) -> + {ok, <<"Ergebnisse">>}; +lgettext(<<"de">>, <<"default">>, <<"Reservatio">>) -> + {ok, <<"a">>}; +lgettext(<<"de">>, <<"navigation">>, <<"Results">>) -> + {ok, <<"Ergebnisse">>}; +lgettext(<<"de">>, <<"navigation">>, <<"Resources">>) -> + {ok, <<"Ressourcen">>}. + + check(F, R) -> R = F(). diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl index aaa2005e73..25983c6012 100644 --- a/lib/compiler/test/compile_SUITE.erl +++ b/lib/compiler/test/compile_SUITE.erl @@ -27,7 +27,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, app_test/1,appup_test/1, - debug_info/4, custom_debug_info/1, + debug_info/4, custom_debug_info/1, custom_compile_info/1, file_1/1, forms_2/1, module_mismatch/1, big_file/1, outdir/1, binary/1, makedep/1, cond_and_ifdef/1, listings/1, listings_big/1, other_output/1, kernel_listing/1, encrypted_abstr/1, @@ -53,7 +53,8 @@ all() -> strict_record, utf8_atoms, utf8_functions, extra_chunks, cover, env, core_pp, core_roundtrip, asm, optimized_guards, sys_pre_attributes, dialyzer, warnings, pre_load_check, - env_compiler_options, custom_debug_info, bc_options]. + env_compiler_options, custom_debug_info, bc_options, + custom_compile_info]. groups() -> []. @@ -649,6 +650,23 @@ custom_debug_info(Config) when is_list(Config) -> {ok,{simple,[{debug_info,{debug_info_v1,?MODULE,error}}]}} = beam_lib:chunks(ErrorBin, [debug_info]). +custom_compile_info(Config) when is_list(Config) -> + Anno = erl_anno:new(1), + Forms = [{attribute,Anno,module,custom_compile_info}], + Opts = [binary,{compile_info,[{another,version}]}], + + {ok,custom_compile_info,Bin} = compile:forms(Forms, Opts), + {ok,{custom_compile_info,[{compile_info,CompileInfo}]}} = + beam_lib:chunks(Bin, [compile_info]), + version = proplists:get_value(another, CompileInfo), + CompileOpts = proplists:get_value(options, CompileInfo), + undefined = proplists:get_value(compile_info, CompileOpts), + + {ok,custom_compile_info,DetBin} = compile:forms(Forms, [deterministic|Opts]), + {ok,{custom_compile_info,[{compile_info,DetInfo}]}} = + beam_lib:chunks(DetBin, [compile_info]), + version = proplists:get_value(another, DetInfo). + cover(Config) when is_list(Config) -> io:format("~p\n", [compile:options()]), ok. diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk index 27ee5a3fb7..43fe0c8f6d 100644 --- a/lib/compiler/vsn.mk +++ b/lib/compiler/vsn.mk @@ -1 +1 @@ -COMPILER_VSN = 7.1.1 +COMPILER_VSN = 7.1.2 diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml index 574353ce7a..9376e6f649 100644 --- a/lib/crypto/doc/src/notes.xml +++ b/lib/crypto/doc/src/notes.xml @@ -31,6 +31,52 @@ </header> <p>This document describes the changes made to the Crypto application.</p> +<section><title>Crypto 4.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>On macOS, <c>crypto</c> would crash if <c>observer</c> + had been started before <c>crypto</c>. On the beta for + macOS 10.13 (High Sierra), <c>crypto</c> would crash. + Both of those bugs have been fixed.</p> + <p> + Own Id: OTP-14499 Aux Id: ERL-251 ERL-439 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Extend crypto:sign, crypto:verify, public_key:sign and + public_key:verify with:</p> + <p> + * support for RSASSA-PS padding for signatures and for + saltlength setting<br/> * X9.31 RSA padding.<br/> * sha, + sha224, sha256, sha384, and sha512 for dss signatures as + mentioned in NIST SP 800-57 Part 1.<br/> * ripemd160 to + be used for rsa signatures.</p> + <p> + This is a manual merge of half of the pull request 838 by + potatosalad from Sept 2015.</p> + <p> + Own Id: OTP-13704 Aux Id: PR838 </p> + </item> + <item> + <p> + A new tuple in <c>crypto:supports/0</c> reports supported + MAC algorithms.</p> + <p> + Own Id: OTP-14504</p> + </item> + </list> + </section> + +</section> + <section><title>Crypto 4.0</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk index 796e3b6d84..1dceebb4e4 100644 --- a/lib/crypto/vsn.mk +++ b/lib/crypto/vsn.mk @@ -1 +1 @@ -CRYPTO_VSN = 4.0 +CRYPTO_VSN = 4.1 diff --git a/lib/debugger/doc/src/notes.xml b/lib/debugger/doc/src/notes.xml index fa85567a84..21fe7d449d 100644 --- a/lib/debugger/doc/src/notes.xml +++ b/lib/debugger/doc/src/notes.xml @@ -33,6 +33,21 @@ <p>This document describes the changes made to the Debugger application.</p> +<section><title>Debugger 4.2.3</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Tools are updated to show Unicode atoms correctly.</p> + <p> + Own Id: OTP-14464</p> + </item> + </list> + </section> + +</section> + <section><title>Debugger 4.2.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/debugger/src/debugger.app.src b/lib/debugger/src/debugger.app.src index 446f2b9882..37a41c1a56 100644 --- a/lib/debugger/src/debugger.app.src +++ b/lib/debugger/src/debugger.app.src @@ -48,5 +48,5 @@ ]}, {registered, [dbg_iserver, dbg_wx_mon, dbg_wx_winman]}, {applications, [kernel, stdlib]}, - {runtime_dependencies, ["wx-1.2","stdlib-2.5","kernel-3.0","erts-6.0", + {runtime_dependencies, ["wx-1.2","stdlib-3.4","kernel-5.3","erts-9.0", "compiler-5.0"]}]}. diff --git a/lib/debugger/src/i.erl b/lib/debugger/src/i.erl index 62ce8d0e20..853fa529a0 100644 --- a/lib/debugger/src/i.erl +++ b/lib/debugger/src/i.erl @@ -30,7 +30,7 @@ -import(lists, [sort/1,foreach/2]). iv() -> - Vsn = string:substr(filename:basename(code:lib_dir(debugger)), 10), + Vsn = string:slice(filename:basename(code:lib_dir(debugger)), 9), list_to_atom(Vsn). %% ------------------------------------------- diff --git a/lib/debugger/vsn.mk b/lib/debugger/vsn.mk index 3534570ef5..72cedb2240 100644 --- a/lib/debugger/vsn.mk +++ b/lib/debugger/vsn.mk @@ -1 +1 @@ -DEBUGGER_VSN = 4.2.2 +DEBUGGER_VSN = 4.2.3 diff --git a/lib/dialyzer/doc/src/notes.xml b/lib/dialyzer/doc/src/notes.xml index c26b7aab5e..6a6e65cb94 100644 --- a/lib/dialyzer/doc/src/notes.xml +++ b/lib/dialyzer/doc/src/notes.xml @@ -32,6 +32,40 @@ <p>This document describes the changes made to the Dialyzer application.</p> +<section><title>Dialyzer 3.2.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> Fix a bug regarding map types that caused Dialyzer to + go into an infinite loop. A consequence of the fix is + that compound map keys such as maps and tuples sometimes + are handled with less precision than before. </p> + <p> + Own Id: OTP-14572 Aux Id: seq13319 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + General Unicode improvements.</p> + <p> + Own Id: OTP-14462</p> + </item> + <item> + <p> The check for unknown remote types is improved. </p> + <p> + Own Id: OTP-14606 Aux Id: OTP-14218 </p> + </item> + </list> + </section> + +</section> + <section><title>Dialyzer 3.2.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/dialyzer/src/dialyzer.app.src b/lib/dialyzer/src/dialyzer.app.src index 5f803875b0..e3a0fc967d 100644 --- a/lib/dialyzer/src/dialyzer.app.src +++ b/lib/dialyzer/src/dialyzer.app.src @@ -48,6 +48,6 @@ {registered, []}, {applications, [compiler, hipe, kernel, stdlib, wx]}, {env, []}, - {runtime_dependencies, ["wx-1.2","syntax_tools-2.0","stdlib-3.0", - "kernel-5.0","hipe-3.15.4","erts-8.0", + {runtime_dependencies, ["wx-1.2","syntax_tools-2.0","stdlib-3.4", + "kernel-5.3","hipe-3.16.1","erts-9.0", "compiler-7.0"]}]}. diff --git a/lib/dialyzer/src/dialyzer_cl.erl b/lib/dialyzer/src/dialyzer_cl.erl index 0617be6435..1e06d6e974 100644 --- a/lib/dialyzer/src/dialyzer_cl.erl +++ b/lib/dialyzer/src/dialyzer_cl.erl @@ -672,7 +672,7 @@ failed_anal_msg(Reason, LogCache) -> %% format_log_cache(LogCache) -> Str = lists:append(lists:reverse(LogCache)), - string:join(string:tokens(Str, "\n"), "\n "). + lists:join("\n ", string:lexemes(Str, "\n")). -spec store_warnings(#cl_state{}, [raw_warning()]) -> #cl_state{}. diff --git a/lib/dialyzer/src/dialyzer_gui_wx.erl b/lib/dialyzer/src/dialyzer_gui_wx.erl index b4b1872c12..b8414b7d8b 100644 --- a/lib/dialyzer/src/dialyzer_gui_wx.erl +++ b/lib/dialyzer/src/dialyzer_gui_wx.erl @@ -475,7 +475,7 @@ gui_loop(#gui_state{backend_pid = BackendPid, doc_plt = DocPlt, gui_loop(State); {BackendPid, ext_types, ExtTypes} -> Map = fun({M,F,A}) -> io_lib:format("~tp:~tp/~p",[M,F,A]) end, - ExtTypeString = string:join(lists:map(Map, ExtTypes), "\n"), + ExtTypeString = lists:join("\n", lists:map(Map, ExtTypes)), Msg = io_lib:format("The following remote types are being used " "but information about them is not available.\n" "The analysis might get more precise by including " @@ -638,7 +638,7 @@ output_sms(#gui_state{frame = Frame}, Title, Message, Type) -> free_editor(#gui_state{gui = Wx, frame = Frame}, Title, Contents0) -> Contents = lists:flatten(Contents0), - Tokens = string:tokens(Contents, "\n"), + Tokens = string:lexemes(Contents, "\n"), NofLines = length(Tokens), LongestLine = lists:max([length(X) || X <- Tokens]), Height0 = NofLines * 25 + 80, diff --git a/lib/dialyzer/src/dialyzer_races.erl b/lib/dialyzer/src/dialyzer_races.erl index 7fe64c3e11..7602faa21d 100644 --- a/lib/dialyzer/src/dialyzer_races.erl +++ b/lib/dialyzer/src/dialyzer_races.erl @@ -1270,8 +1270,8 @@ filter_named_tables(NamesList) -> [] -> []; [Head|Tail] -> NewHead = - case string:rstr(Head, "()") of - 0 -> [Head]; + case string:find(Head, "()", trailing) of + nomatch -> [Head]; _Other -> [] end, NewHead ++ filter_named_tables(Tail) @@ -1558,8 +1558,8 @@ any_args(StrList) -> case StrList of [] -> false; [Head|Tail] -> - case string:rstr(Head, "()") of - 0 -> any_args(Tail); + case string:find(Head, "()", trailing) of + nomatch -> any_args(Tail); _Other -> true end end. @@ -1765,10 +1765,8 @@ ets_list_args(MaybeList) -> end. ets_list_argtypes(ListStr) -> - ListStr1 = string:strip(ListStr, left, $[), - ListStr2 = string:strip(ListStr1, right, $]), - ListStr3 = string:strip(ListStr2, right, $.), - string:strip(ListStr3, right, $,). + ListStr1 = string:trim(ListStr, leading, "$["), + string:trim(ListStr1, trailing, "$]$.$,"). ets_tuple_args(MaybeTuple) -> case is_tuple(MaybeTuple) of @@ -1810,7 +1808,7 @@ ets_tuple_argtypes2_helper(TupleStr, ElemStr, NestingLevel) -> {[H|ElemStr], NestingLevel, false} end, case Return of - true -> string:tokens(NewElemStr, " |"); + true -> string:lexemes(NewElemStr, " |"); false -> ets_tuple_argtypes2_helper(T, NewElemStr, NewNestingLevel) end @@ -1889,44 +1887,44 @@ format_args_2(StrArgList, Call) -> case Call of whereis -> lists_key_replace(2, StrArgList, - string:tokens(lists:nth(2, StrArgList), " |")); + string:lexemes(lists:nth(2, StrArgList), " |")); register -> lists_key_replace(2, StrArgList, - string:tokens(lists:nth(2, StrArgList), " |")); + string:lexemes(lists:nth(2, StrArgList), " |")); unregister -> lists_key_replace(2, StrArgList, - string:tokens(lists:nth(2, StrArgList), " |")); + string:lexemes(lists:nth(2, StrArgList), " |")); ets_new -> StrArgList1 = lists_key_replace(2, StrArgList, - string:tokens(lists:nth(2, StrArgList), " |")), + string:lexemes(lists:nth(2, StrArgList), " |")), lists_key_replace(4, StrArgList1, - string:tokens(ets_list_argtypes(lists:nth(4, StrArgList1)), " |")); + string:lexemes(ets_list_argtypes(lists:nth(4, StrArgList1)), " |")); ets_lookup -> StrArgList1 = lists_key_replace(2, StrArgList, - string:tokens(lists:nth(2, StrArgList), " |")), + string:lexemes(lists:nth(2, StrArgList), " |")), lists_key_replace(4, StrArgList1, - string:tokens(lists:nth(4, StrArgList1), " |")); + string:lexemes(lists:nth(4, StrArgList1), " |")); ets_insert -> StrArgList1 = lists_key_replace(2, StrArgList, - string:tokens(lists:nth(2, StrArgList), " |")), + string:lexemes(lists:nth(2, StrArgList), " |")), lists_key_replace(4, StrArgList1, ets_tuple_argtypes2( ets_tuple_argtypes1(lists:nth(4, StrArgList1), [], [], 0), [])); mnesia_dirty_read1 -> lists_key_replace(2, StrArgList, - [mnesia_tuple_argtypes(T) || T <- string:tokens( + [mnesia_tuple_argtypes(T) || T <- string:lexemes( lists:nth(2, StrArgList), " |")]); mnesia_dirty_read2 -> lists_key_replace(2, StrArgList, - string:tokens(lists:nth(2, StrArgList), " |")); + string:lexemes(lists:nth(2, StrArgList), " |")); mnesia_dirty_write1 -> lists_key_replace(2, StrArgList, - [mnesia_record_tab(R) || R <- string:tokens( + [mnesia_record_tab(R) || R <- string:lexemes( lists:nth(2, StrArgList), " |")]); mnesia_dirty_write2 -> lists_key_replace(2, StrArgList, - string:tokens(lists:nth(2, StrArgList), " |")); + string:lexemes(lists:nth(2, StrArgList), " |")); function_call -> StrArgList end. @@ -1943,18 +1941,16 @@ format_type(Type, State) -> erl_types:t_to_string(Type, R). mnesia_record_tab(RecordStr) -> - case string:str(RecordStr, "#") =:= 1 of - true -> - "'" ++ - string:sub_string(RecordStr, 2, string:str(RecordStr, "{") - 1) ++ - "'"; - false -> RecordStr + case erl_scan:string(RecordStr) of + {ok, [{'#', _}, {atom, _, Name}|_], _} -> + io_lib:write_string(atom_to_list(Name), $'); + _ -> RecordStr end. mnesia_tuple_argtypes(TupleStr) -> - TupleStr1 = string:strip(TupleStr, left, ${), - [TupleStr2|_T] = string:tokens(TupleStr1, " ,"), - lists:flatten(string:tokens(TupleStr2, " |")). + TupleStr1 = string:trim(TupleStr, leading, "${"), + [TupleStr2|_T] = string:lexemes(TupleStr1, " ,"), + lists:flatten(string:lexemes(TupleStr2, " |")). -spec race_var_map(var_to_map1(), var_to_map2(), dict:dict(), op()) -> dict:dict(). @@ -2237,7 +2233,7 @@ var_type_analysis(FunDefArgs, FunCallTypes, WarnVarArgs, RaceWarnTag, case lists_key_member_lists(Vars, FunVarArgs) of 0 -> [Vars, WVA2, WVA3, WVA4]; N when is_integer(N) -> - NewWVA2 = string:tokens(lists:nth(N + 1, FunVarArgs), " |"), + NewWVA2 = string:lexemes(lists:nth(N + 1, FunVarArgs), " |"), [Vars, NewWVA2, WVA3, WVA4] end; ?WARN_WHEREIS_UNREGISTER -> @@ -2246,7 +2242,7 @@ var_type_analysis(FunDefArgs, FunCallTypes, WarnVarArgs, RaceWarnTag, case lists_key_member_lists(Vars, FunVarArgs) of 0 -> [Vars, WVA2]; N when is_integer(N) -> - NewWVA2 = string:tokens(lists:nth(N + 1, FunVarArgs), " |"), + NewWVA2 = string:lexemes(lists:nth(N + 1, FunVarArgs), " |"), [Vars, NewWVA2] end; ?WARN_ETS_LOOKUP_INSERT -> @@ -2256,7 +2252,7 @@ var_type_analysis(FunDefArgs, FunCallTypes, WarnVarArgs, RaceWarnTag, case lists_key_member_lists(Vars1, FunVarArgs) of 0 -> [Vars1, WVA2]; N1 when is_integer(N1) -> - NewWVA2 = string:tokens(lists:nth(N1 + 1, FunVarArgs), " |"), + NewWVA2 = string:lexemes(lists:nth(N1 + 1, FunVarArgs), " |"), [Vars1, NewWVA2] end, Vars2 = @@ -2286,10 +2282,10 @@ var_type_analysis(FunDefArgs, FunCallTypes, WarnVarArgs, RaceWarnTag, NewWVA2 = case Arity of 1 -> - [mnesia_record_tab(R) || R <- string:tokens( + [mnesia_record_tab(R) || R <- string:lexemes( lists:nth(2, FunVarArgs), " |")]; 2 -> - string:tokens(lists:nth(N + 1, FunVarArgs), " |") + string:lexemes(lists:nth(N + 1, FunVarArgs), " |") end, [Vars, NewWVA2|T] end diff --git a/lib/dialyzer/test/dialyzer_common.erl b/lib/dialyzer/test/dialyzer_common.erl index 48083a2731..1a8403f486 100644 --- a/lib/dialyzer/test/dialyzer_common.erl +++ b/lib/dialyzer/test/dialyzer_common.erl @@ -221,13 +221,9 @@ get_suites(Dir) -> end. suffix(String, Suffix) -> - case string:rstr(String, Suffix) of - 0 -> no; - Index -> - case string:substr(String, Index) =:= Suffix of - true -> {yes, string:sub_string(String,1,Index-1)}; - false -> no - end + case string:split(String, Suffix, trailing) of + [Prefix,[]] -> {yes, Prefix}; + _ -> no end. -spec create_suite(string()) -> 'ok'. diff --git a/lib/dialyzer/test/map_SUITE_data/results/loop b/lib/dialyzer/test/map_SUITE_data/results/loop new file mode 100644 index 0000000000..2e956a5709 --- /dev/null +++ b/lib/dialyzer/test/map_SUITE_data/results/loop @@ -0,0 +1,4 @@ + +loop.erl:63: The call loop:start_timer(#loop{state::'idle' | 'waiting',queues::#{'category1'=>#queue{limit::non_neg_integer(),buffer::[any()]}, 'category2'=>#queue{limit::non_neg_integer(),buffer::[any()]}},counters::#{'counter1':=10, 2:=10}}) does not have a term of type #loop{state::'idle' | 'waiting',timer::timer:tref(),queues::#{'category1'=>#queue{limit::non_neg_integer(),buffer::[any()]}, 'category2'=>#queue{limit::non_neg_integer(),buffer::[any()]}},counters::#{'counter1'=>non_neg_integer(), 2=>non_neg_integer()}} (with opaque subterms) as 1st argument +loop.erl:67: Function wait/1 has no local return +loop.erl:85: Record construction #loop{state::'idle' | 'waiting',timer::{'error',_} | {'ok',timer:tref()},queues::#{'category1'=>#queue{limit::non_neg_integer(),buffer::[any()]}, 'category2'=>#queue{limit::non_neg_integer(),buffer::[any()]}},counters::#{'counter1'=>non_neg_integer(), 2=>non_neg_integer()}} violates the declared type of field timer::'undefined' | timer:tref() diff --git a/lib/dialyzer/test/map_SUITE_data/results/map_galore b/lib/dialyzer/test/map_SUITE_data/results/map_galore index c34ba5cf30..9a140de255 100644 --- a/lib/dialyzer/test/map_SUITE_data/results/map_galore +++ b/lib/dialyzer/test/map_SUITE_data/results/map_galore @@ -1,11 +1,11 @@ map_galore.erl:1000: A key of type 42 cannot exist in a map of type #{1:='a', 2:='b', 4:='d', 5:='e', float()=>'c' | 'v'} -map_galore.erl:1080: A key of type 'nonexisting' cannot exist in a map of type #{#{'map':='key', 'one':='small'}:=[32 | 49 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'second':='small'}:=[32 | 50 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'third':='small'}:=[32 | 51 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], 10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 16:='a6', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 26:='b6', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 36:=[54 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]} | #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], 'k16'=>'a6', 'k26'=>'b6', 'k36'=>[54 | 99,...], 16=>'a6', 26=>'b6', 36=>[54 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]}=>[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 100 | 101,...]}=>atom() | [1..255,...]} -map_galore.erl:1082: A key of type 42 cannot exist in a map of type #{#{'map':='key', 'one':='small'}:=[32 | 49 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'second':='small'}:=[32 | 50 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'third':='small'}:=[32 | 51 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], 10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 16:='a6', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 26:='b6', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 36:=[54 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]} | #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], 'k16'=>'a6', 'k26'=>'b6', 'k36'=>[54 | 99,...], 16=>'a6', 26=>'b6', 36=>[54 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]}=>[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 100 | 101,...]}=>atom() | [1..255,...]} -map_galore.erl:1140: The call map_galore:map_guard_sequence_1(#{'seq':=6, 'val':=[101,...]}) will never return since it differs in the 1st argument from the success typing arguments: (#{'seq':=1 | 2 | 3 | 4 | 5, 'val':=[97 | 98 | 99 | 100 | 101,...], #{'map':='key', 'one':='small'}=>[32 | 49 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'second':='small'}=>[32 | 50 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'third':='small'}=>[32 | 51 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[any(),...]} | #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 27:='b7', 28:='b8', 29:='b9', 30:=[any(),...], 31:=[any(),...], 32:=[any(),...], 33:=[any(),...], 34:=[any(),...], 35:=[any(),...], 37:=[any(),...], 38:=[any(),...], 39:=[any(),...], 'k16'=>'a6', 'k26'=>'b6', 'k36'=>[any(),...], 16=>'a6', 26=>'b6', 36=>[any(),...], <<_:16>> | [any(),...] | {_}=>[any(),...]}=>atom() | [1..255,...]}) -map_galore.erl:1141: The call map_galore:map_guard_sequence_2(#{'b':=5}) will never return since it differs in the 1st argument from the success typing arguments: (#{'a':='gg' | 'kk' | 'sc' | 3 | 4, 'b'=>'other' | 3 | 4 | 5, 'c'=>'sc2', #{'map':='key', 'one':='small'}=>[32 | 49 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'second':='small'}=>[32 | 50 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'third':='small'}=>[32 | 51 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[any(),...]} | #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 27:='b7', 28:='b8', 29:='b9', 30:=[any(),...], 31:=[any(),...], 32:=[any(),...], 33:=[any(),...], 34:=[any(),...], 35:=[any(),...], 37:=[any(),...], 38:=[any(),...], 39:=[any(),...], 'k16'=>'a6', 'k26'=>'b6', 'k36'=>[any(),...], 16=>'a6', 26=>'b6', 36=>[any(),...], <<_:16>> | [any(),...] | {_}=>[any(),...]}=>atom() | [1..255,...]}) -map_galore.erl:1209: The call map_galore:map_guard_sequence_1(#{'seq':=6, 'val':=[101,...], #{'map':='key', 'one':='small'}:=[32 | 49 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'second':='small'}:=[32 | 50 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'third':='small'}:=[32 | 51 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], 10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 16:='a6', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 26:='b6', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 36:=[54 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | 3,...]} | #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], 'k16'=>'a6', 'k26'=>'b6', 'k36'=>[54 | 99,...], 16=>'a6', 26=>'b6', 36=>[54 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]}=>[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 100 | 101,...]}=>atom() | [1..255,...]}) will never return since it differs in the 1st argument from the success typing arguments: (#{'seq':=1 | 2 | 3 | 4 | 5, 'val':=[97 | 98 | 99 | 100 | 101,...], #{'map':='key', 'one':='small'}=>[32 | 49 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'second':='small'}=>[32 | 50 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'third':='small'}=>[32 | 51 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[any(),...]} | #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 27:='b7', 28:='b8', 29:='b9', 30:=[any(),...], 31:=[any(),...], 32:=[any(),...], 33:=[any(),...], 34:=[any(),...], 35:=[any(),...], 37:=[any(),...], 38:=[any(),...], 39:=[any(),...], 'k16'=>'a6', 'k26'=>'b6', 'k36'=>[any(),...], 16=>'a6', 26=>'b6', 36=>[any(),...], <<_:16>> | [any(),...] | {_}=>[any(),...]}=>atom() | [1..255,...]}) -map_galore.erl:1210: The call map_galore:map_guard_sequence_2(#{'b':=5, #{'map':='key', 'one':='small'}:=[32 | 49 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'second':='small'}:=[32 | 50 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'third':='small'}:=[32 | 51 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], 10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 16:='a6', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 26:='b6', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 36:=[54 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | 3,...]} | #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], 'k16'=>'a6', 'k26'=>'b6', 'k36'=>[54 | 99,...], 16=>'a6', 26=>'b6', 36=>[54 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]}=>[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 100 | 101,...]}=>atom() | [1..255,...]}) will never return since it differs in the 1st argument from the success typing arguments: (#{'a':='gg' | 'kk' | 'sc' | 3 | 4, 'b'=>'other' | 3 | 4 | 5, 'c'=>'sc2', #{'map':='key', 'one':='small'}=>[32 | 49 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'second':='small'}=>[32 | 50 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], #{'map':='key', 'third':='small'}=>[32 | 51 | 97 | 101 | 107 | 108 | 109 | 112 | 115 | 121,...], 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[any(),...]} | #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 27:='b7', 28:='b8', 29:='b9', 30:=[any(),...], 31:=[any(),...], 32:=[any(),...], 33:=[any(),...], 34:=[any(),...], 35:=[any(),...], 37:=[any(),...], 38:=[any(),...], 39:=[any(),...], 'k16'=>'a6', 'k26'=>'b6', 'k36'=>[any(),...], 16=>'a6', 26=>'b6', 36=>[any(),...], <<_:16>> | [any(),...] | {_}=>[any(),...]}=>atom() | [1..255,...]}) +map_galore.erl:1080: A key of type 'nonexisting' cannot exist in a map of type #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 16:='a6', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 26:='b6', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 36:=[54 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]} | #{'k16'=>'a6', 'k26'=>'b6', 'k36'=>[54 | 99,...], 'map'=>'key', 'one'=>'small', 'second'=>'small', 'third'=>'small', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]}=>[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 100 | 101,...]}=>atom() | [1..255,...]} +map_galore.erl:1082: A key of type 42 cannot exist in a map of type #{10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 16:='a6', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 26:='b6', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 36:=[54 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]} | #{'k16'=>'a6', 'k26'=>'b6', 'k36'=>[54 | 99,...], 'map'=>'key', 'one'=>'small', 'second'=>'small', 'third'=>'small', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]}=>[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 100 | 101,...]}=>atom() | [1..255,...]} +map_galore.erl:1140: The call map_galore:map_guard_sequence_1(#{'seq':=6, 'val':=[101,...]}) will never return since it differs in the 1st argument from the success typing arguments: (#{'seq':=1 | 2 | 3 | 4 | 5, 'val':=[97 | 98 | 99 | 100 | 101,...], 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[any(),...]} | #{'k16'=>'a6', 'k26'=>'b6', 'k36'=>[any(),...], 'map'=>'key', 'one'=>'small', 'second'=>'small', 'third'=>'small', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[any(),...], 31=>[any(),...], 32=>[any(),...], 33=>[any(),...], 34=>[any(),...], 35=>[any(),...], 36=>[any(),...], 37=>[any(),...], 38=>[any(),...], 39=>[any(),...], <<_:16>> | [any(),...] | {_}=>[any(),...]}=>atom() | [1..255,...]}) +map_galore.erl:1141: The call map_galore:map_guard_sequence_2(#{'b':=5}) will never return since it differs in the 1st argument from the success typing arguments: (#{'a':='gg' | 'kk' | 'sc' | 3 | 4, 'b'=>'other' | 3 | 4 | 5, 'c'=>'sc2', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[any(),...]} | #{'k16'=>'a6', 'k26'=>'b6', 'k36'=>[any(),...], 'map'=>'key', 'one'=>'small', 'second'=>'small', 'third'=>'small', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[any(),...], 31=>[any(),...], 32=>[any(),...], 33=>[any(),...], 34=>[any(),...], 35=>[any(),...], 36=>[any(),...], 37=>[any(),...], 38=>[any(),...], 39=>[any(),...], <<_:16>> | [any(),...] | {_}=>[any(),...]}=>atom() | [1..255,...]}) +map_galore.erl:1209: The call map_galore:map_guard_sequence_1(#{'seq':=6, 'val':=[101,...], 10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 16:='a6', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 26:='b6', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 36:=[54 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | 3,...]} | #{'k16'=>'a6', 'k26'=>'b6', 'k36'=>[54 | 99,...], 'map'=>'key', 'one'=>'small', 'second'=>'small', 'third'=>'small', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]}=>[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 100 | 101,...]}=>atom() | [1..255,...]}) will never return since it differs in the 1st argument from the success typing arguments: (#{'seq':=1 | 2 | 3 | 4 | 5, 'val':=[97 | 98 | 99 | 100 | 101,...], 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[any(),...]} | #{'k16'=>'a6', 'k26'=>'b6', 'k36'=>[any(),...], 'map'=>'key', 'one'=>'small', 'second'=>'small', 'third'=>'small', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[any(),...], 31=>[any(),...], 32=>[any(),...], 33=>[any(),...], 34=>[any(),...], 35=>[any(),...], 36=>[any(),...], 37=>[any(),...], 38=>[any(),...], 39=>[any(),...], <<_:16>> | [any(),...] | {_}=>[any(),...]}=>atom() | [1..255,...]}) +map_galore.erl:1210: The call map_galore:map_guard_sequence_2(#{'b':=5, 10:='a0', 11:='a1', 12:='a2', 13:='a3', 14:='a4', 15:='a5', 16:='a6', 17:='a7', 18:='a8', 19:='a9', 20:='b0', 21:='b1', 22:='b2', 23:='b3', 24:='b4', 25:='b5', 26:='b6', 27:='b7', 28:='b8', 29:='b9', 30:=[48 | 99,...], 31:=[49 | 99,...], 32:=[50 | 99,...], 33:=[51 | 99,...], 34:=[52 | 99,...], 35:=[53 | 99,...], 36:=[54 | 99,...], 37:=[55 | 99,...], 38:=[56 | 99,...], 39:=[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | 3,...]} | #{'k16'=>'a6', 'k26'=>'b6', 'k36'=>[54 | 99,...], 'map'=>'key', 'one'=>'small', 'second'=>'small', 'third'=>'small', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | {[[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...],...]}=>[48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 100 | 101,...]}=>atom() | [1..255,...]}) will never return since it differs in the 1st argument from the success typing arguments: (#{'a':='gg' | 'kk' | 'sc' | 3 | 4, 'b'=>'other' | 3 | 4 | 5, 'c'=>'sc2', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[48 | 99,...], 31=>[49 | 99,...], 32=>[50 | 99,...], 33=>[51 | 99,...], 34=>[52 | 99,...], 35=>[53 | 99,...], 36=>[54 | 99,...], 37=>[55 | 99,...], 38=>[56 | 99,...], 39=>[57 | 99,...], <<_:16>> | [48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57,...] | float() | {[any(),...]} | #{'k16'=>'a6', 'k26'=>'b6', 'k36'=>[any(),...], 'map'=>'key', 'one'=>'small', 'second'=>'small', 'third'=>'small', 10=>'a0', 11=>'a1', 12=>'a2', 13=>'a3', 14=>'a4', 15=>'a5', 16=>'a6', 17=>'a7', 18=>'a8', 19=>'a9', 20=>'b0', 21=>'b1', 22=>'b2', 23=>'b3', 24=>'b4', 25=>'b5', 26=>'b6', 27=>'b7', 28=>'b8', 29=>'b9', 30=>[any(),...], 31=>[any(),...], 32=>[any(),...], 33=>[any(),...], 34=>[any(),...], 35=>[any(),...], 36=>[any(),...], 37=>[any(),...], 38=>[any(),...], 39=>[any(),...], <<_:16>> | [any(),...] | {_}=>[any(),...]}=>atom() | [1..255,...]}) map_galore.erl:1418: Fun application with arguments (#{'s':='none', 'v':='none'}) will never return since it differs in the 1st argument from the success typing arguments: (#{'s':='l' | 't' | 'v', 'v':='none' | <<_:16>> | [<<_:16>>,...] | {<<_:16>>,<<_:16>>}}) map_galore.erl:1491: The test #{} =:= #{'a':=1} can never evaluate to 'true' map_galore.erl:1492: The test #{'a':=1} =:= #{} can never evaluate to 'true' diff --git a/lib/dialyzer/test/map_SUITE_data/results/opaque_key b/lib/dialyzer/test/map_SUITE_data/results/opaque_key index 2ae0e0c5c6..8d6379b5e0 100644 --- a/lib/dialyzer/test/map_SUITE_data/results/opaque_key +++ b/lib/dialyzer/test/map_SUITE_data/results/opaque_key @@ -1,4 +1,5 @@ +opaque_key_adt.erl:35: Invalid type specification for function opaque_key_adt:s2/0. The success typing is () -> #{3:='a'} opaque_key_adt.erl:41: Invalid type specification for function opaque_key_adt:s4/0. The success typing is () -> #{1:='a'} opaque_key_adt.erl:44: Invalid type specification for function opaque_key_adt:s5/0. The success typing is () -> #{2:=3} opaque_key_adt.erl:56: Invalid type specification for function opaque_key_adt:smt1/0. The success typing is () -> #{3:='a'} diff --git a/lib/dialyzer/test/map_SUITE_data/src/loop.erl b/lib/dialyzer/test/map_SUITE_data/src/loop.erl new file mode 100644 index 0000000000..c861052d9f --- /dev/null +++ b/lib/dialyzer/test/map_SUITE_data/src/loop.erl @@ -0,0 +1,92 @@ +-module(loop). + +-export([timeout/2]). + +-export([idle/2, waiting/2]). + +-type request_category() :: category1 | category2. + +-type counter() :: counter1 | 2. + +-type counters() :: #{counter() => non_neg_integer()}. + +-record(queue, {limit = 0 :: non_neg_integer(), + buffer = [] :: list()}). + +-type request_queues() :: #{request_category() => #queue{}}. + +-record(?MODULE, + {state = idle :: idle | waiting, + timer = undefined :: undefined | timer:tref(), + queues = #{category1 => #queue{}, + category2 => #queue{}} :: request_queues(), + counters = new_counters() :: counters()}). +-spec timeout(Ref, Timer :: timer:tref()) -> {noreply, Ref}. +timeout(Ref, Timer) -> + handle_message(Ref, {timeout, Timer}). + +-type message() :: {reset, request_category()} + | {timeout, timer:tref()}. + +-spec handle_message(Ref, Message :: message()) -> + {reply, boolean(), Ref} | {noreply, Ref}. +handle_message(Ref, Msg) -> + MV = #?MODULE{state = State} = get(mv), + case apply(?MODULE, State, [Msg, MV]) of + {reply, Result, NewMV} -> + put(mv, NewMV), + {reply, Result, Ref}; + {noreply, NewMV} -> + put(mv, NewMV), + {noreply, Ref} + end. + +-spec idle(Message :: message(), #?MODULE{}) -> + {reply, boolean(), #?MODULE{}} | {noreply, #?MODULE{}}. +idle({reset, Category}, MV = #?MODULE{queues = Queues}) -> + case Queues of + #{Category := #queue{limit = 0}} -> + {reply, false, MV}; + _ -> + wait(MV) + end; +idle(_, MV) -> + {noreply, MV}. + +-spec waiting(Message :: message(), #?MODULE{}) -> + {reply, boolean(), #?MODULE{}} | {noreply, #?MODULE{}}. +waiting({reset, _Category}, MV = #?MODULE{}) -> + NewMV = stop_timer(MV), + {noreply, NewMV#?MODULE{state = idle}}; +waiting({timeout, Timer}, #?MODULE{timer = Timer} = MV) -> + %% The opaque warning is an effect of the call to timer:send_after(). + {noreply, start_timer(MV#?MODULE{timer = undefined, + counters = new_counters()})}. + +-spec wait(#?MODULE{}) -> {noreply, #?MODULE{}}. +wait(MV) -> + {noreply, start_timer(MV#?MODULE{state = waiting})}. + +-spec stop_timer(#?MODULE{}) -> #?MODULE{}. +stop_timer(MV) -> + case MV#?MODULE.timer of + undefined -> + MV; + Timer -> + timer:cancel(Timer), + MV#?MODULE{timer = undefined} + end. + +-spec start_timer(MV :: #?MODULE{}) -> #?MODULE{}. +start_timer(MV) -> + case MV#?MODULE.timer of + undefined -> + %% Note: timer:send_after() returns {ok, TRef} | {error, _}. + MV#?MODULE{timer = timer:send_after(1000, ?MODULE)}; + _Timer -> + start_timer(stop_timer(MV)) + end. + +-spec new_counters() -> counters(). +new_counters() -> + #{counter1 => 10, 2 => 10}. diff --git a/lib/dialyzer/test/map_SUITE_data/src/opaque_key/opaque_key_adt.erl b/lib/dialyzer/test/map_SUITE_data/src/opaque_key/opaque_key_adt.erl index b98c713c6b..9228cfa413 100644 --- a/lib/dialyzer/test/map_SUITE_data/src/opaque_key/opaque_key_adt.erl +++ b/lib/dialyzer/test/map_SUITE_data/src/opaque_key/opaque_key_adt.erl @@ -33,7 +33,7 @@ s0() -> #{}. s1() -> #{3 => a}. -spec s2() -> s(atom() | 3). -s2() -> #{3 => a}. %% Contract breakage (not found) +s2() -> #{3 => a}. %% Contract breakage -spec s3() -> s(atom() | 3). s3() -> #{3 => 5, a => 6, 7 => 8}. diff --git a/lib/dialyzer/vsn.mk b/lib/dialyzer/vsn.mk index 866a82ee3e..d130b14fec 100644 --- a/lib/dialyzer/vsn.mk +++ b/lib/dialyzer/vsn.mk @@ -1 +1 @@ -DIALYZER_VSN = 3.2.1 +DIALYZER_VSN = 3.2.2 diff --git a/lib/diameter/doc/src/diameter_sctp.xml b/lib/diameter/doc/src/diameter_sctp.xml index c9b74a9ec5..62e958870e 100644 --- a/lib/diameter/doc/src/diameter_sctp.xml +++ b/lib/diameter/doc/src/diameter_sctp.xml @@ -1,5 +1,7 @@ <?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd" [ + <!ENTITY man_tcp_sender + '<seealso marker="diameter_tcp#sender">diameter_tcp(3)</seealso>'> <!ENTITY gen_sctp '<seealso marker="kernel:gen_sctp">gen_sctp(3)</seealso>'> <!ENTITY gen_sctp_open1 '<seealso marker="kernel:gen_sctp#open-1">gen_sctp:open/1</seealso>'> @@ -78,7 +80,11 @@ and implements the behaviour documented in <v>Reason = term()</v> <v>OwnOpt = {raddr, &ip_address;} | {rport, integer()} - | {accept, Match}</v> + | {accept, Match} + | {unordered, boolean() | pos_integer()} + | {packet, boolean() | raw} + | {message_cb, &mod_eval;} + | {sender, boolean()}</v> <v>SctpOpt = term()</v> <v>Match = &ip_address; | string() | [Match]</v> </type> @@ -106,6 +112,41 @@ A string-valued <c>Match</c> that does not parse as an address is interpreted as a regular expression.</p> <p> +Option <c>unordered</c> specifies whether or not to use unordered +delivery, integer <c>N</c> being equivalent to <c>N =< OS</c>, +where <c>OS</c> is the number of outbound streams negotiated on the +association in question. +Regardless of configuration, sending is ordered on stream 0 +until reception of a second incoming message, to ensure that a peer +receives capabilities exchange messages before any other. +Defaults to <c>false</c>.</p> + +<p> +Option <c>packet</c> determines how/if an incoming message is +packaged into a diameter_packet record. +If <c>false</c> then messages are received as binary(). +If <c>true</c> then as a record with the binary() message in the +<c>bin</c> field and a <c>{stream, Id}</c> tuple in the +<c>transport_data</c> field, where <c>Id</c> is the identifier of the +inbound stream the message was received on. +If <c>raw</c> then as a record with the received ancillary +sctp_sndrcvinfo record in the <c>transport_data</c> field. +Defaults to <c>true</c>.</p> + +<p> +Options <c>message_cb</c> and <c>sender</c> have semantics identical +to those documented in &man_tcp_sender;, but with the message argument +to a <c>recv</c> callback being as directed by the <c>packet</c> +option.</p> + +<p> +An <c>{outstream, Id}</c> tuple in the <c>transport_data</c> field of +a outgoing diameter_packet record sets the outbound stream on which +the message is sent, modulo the negotiated number of outbound streams. +Any other value causes successive such sends to cycle though all +outbound streams.</p> + +<p> Remaining options are any accepted by &gen_sctp_open1;, with the exception of options <c>mode</c>, <c>binary</c>, <c>list</c>, <c>active</c> and <c>sctp_events</c>. @@ -121,29 +162,16 @@ connecting transport.</p> <warning> <p> -An insufficiently large receive buffer may result in a peer having to +An small receive buffer may result in a peer having to resend incoming messages: set the &inet; option <c>recbuf</c> to increase the buffer size.</p> <p> -An insufficiently large send buffer may result in outgoing messages +An small send buffer may result in outgoing messages being discarded: set the &inet; option <c>sndbuf</c> to increase the buffer size.</p> </warning> -<p> -The <c>transport_data</c> field of record <c>diameter_packet</c> -is used to communicate the stream on which an inbound message -has been received, or on which an outbound message should be sent. -The value will be of the form <c>{stream, Id}</c> for an inbound -message passed to a &app_handle_request; or &app_handle_answer; -callback. -For an outbound message, <c>{outstream, Id}</c> in the return value of -&app_handle_request; or &app_prepare_retransmit; sets the outbound -stream, the stream id being interpreted modulo the number of outbound -streams. -Any other value, or not setting a value, causes successive such sends -to cycle though all outbound streams.</p> </desc> </func> diff --git a/lib/diameter/doc/src/diameter_soc.xml b/lib/diameter/doc/src/diameter_soc.xml index ae404fcda4..28e01ff1be 100644 --- a/lib/diameter/doc/src/diameter_soc.xml +++ b/lib/diameter/doc/src/diameter_soc.xml @@ -1,15 +1,22 @@ <?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd" [ + <!ENTITY gen_sctp '<seealso marker="kernel:gen_sctp">gen_sctp(3)</seealso>'> + <!ENTITY gen_tcp '<seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso>'> + <!ENTITY service '<seealso marker="diameter#start_service-2">service</seealso>'> + <!ENTITY capabilities '<seealso marker="diameter#capability">capabilities</seealso>'> + <!ENTITY events '<seealso marker="diameter#service_event">events</seealso>'> + <!ENTITY NA '—'> + <!ENTITY BR '<br/> <br/>'> <!ENTITY % also SYSTEM "seealso.ent" > %also; ]> -<chapter xmlns:xi="http://www.w3.org/2001/XInclude"> +<chapter> <header> <copyright> <year>2011</year> -<year>2016</year> +<year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> @@ -41,63 +48,1285 @@ limitations under the License. </header> <p> -Known points of questionable or non-compliance.</p> +The table below summarizes the diameter application's compliance with +&the_rfc;. +Since the diameter application isn't a Diameter node on its own, +compliance is strictly the responsibility of the user in many cases, +diameter providing the means for the user to be compliant +rather than being compliant on its own.</p> -<!-- ===================================================================== --> - -<section> -<title>&the_rfc;</title> - -<list> - -<item> -<p> -There is no support for DTLS over SCTP.</p> -</item> - -<item> <p> -There is no explicit support for peer discovery (section 5.2). -It can possibly be implemented on top of diameter as is but this is -probably something that diameter should do.</p> -</item> +The Compliance column notes <em>C</em> (Compliant) if the required +functionality is implemented, <em>PC</em> (Partially Compliant) if +there are limitations, <em>NC</em> (Not Compliant) if functionality is +not implemented, or a dash if text is informational or only places +requirements that must be met by the user's implementation.</p> -<item> <p> -The peer state machine's election process (section 5.6.4) isn't -implemented as specified since it assumes knowledge of a -peer's Origin-Host before sending it a CER. (The identity becoming known -upon reception of CEA.) -The possibility of configuring -the peer's Origin-Host could be added, along with handling of the case -that it sends something else, but for many applications this will -just be unnecessary configuration of a value that it has no control over.</p> -</item> -<!-- Transport protocol plus address/port, which we do know when - sending and receiving CER, is enough to definitely identify - the peer. However, there's nothing stopping a peer from using - different identities on different transport protocols, even - if it's maybe a bit far-fetched. --> - -</list> - -<xi:include href="diameter_soc_rfc6733.xml"/> - -</section> +Capitalized <em>Diameter</em> refers to the protocol, lowercase +<em>diameter</em> to the Erlang application.</p> <!-- ===================================================================== --> <section> -<title>RFC 3539</title> +<title>&the_rfc; - Diameter Base Protocol</title> -<p> -RFC 3539 is more difficult to comply to since it discusses -problems as much as it requires functionality but all the MUST's are -covered, the watchdog state machine being the primary one. -Of the optional functionality, load balancing is left to the -diameter user (since it's the one deciding who to send to) and -there is no Congestion Manager.</p> +<table> +<row> + <cell><em>Section</em></cell> + <cell><em>Title</em></cell> + <cell><em>Compliance</em></cell> + <cell><em>Notes</em></cell> +</row> +<row> + <cell>1</cell> + <cell>Introduction</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>1.1</cell> + <cell>Diameter Protocol</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>1.1.1</cell> + <cell>Description of the Document Set</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>1.1.2</cell> + <cell>Conventions Used in This Document</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>1.1.3</cell> + <cell>Changes from RFC 3588</cell> + <cell>&NA;</cell> + <cell>It is possible to configure a 3588 dictionary in + order to get 3588 semantics, where the differ from 6733.</cell> +</row> +<row> + <cell>1.2</cell> + <cell>Terminology</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>1.3</cell> + <cell>Approach to Extensibility</cell> + <cell>&NA;</cell> + <cell>The dictionary interface documented in &man_dict; provides + extensibility, allowing the user to defined new AVPs, commands, and + applications. + Ready dictionaries are provided for the &the_rfc; common message, base + accounting, and relay applications, as well as for RFC 7683, + Diameter Overload Indicator Conveyance.</cell> +</row> +<row> + <cell>1.3.1</cell> + <cell>Defining New AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>1.3.2</cell> + <cell>Creating New AVPs</cell> + <cell>&NA;</cell> + <cell>New AVPs can be defined using the dictionary interface. + Both both RFC data formats and extensions are supported.</cell> +</row> +<row> + <cell>1.3.3</cell> + <cell>Creating New Commands</cell> + <cell>&NA;</cell> + <cell>New commands can be defined using the dictionary interface.</cell> +</row> +<row> + <cell>1.3.4</cell> + <cell>Creating New Diameter Applications</cell> + <cell>&NA;</cell> + <cell>New applications can be defined using the dictionary interface.</cell> +</row> +<row> + <cell>2</cell> + <cell>Protocol Overview</cell> + <cell>&NA;</cell> + <cell>Session state is the responsibility of the user.&BR; + The role of a Diameter node is determined by the user's + implementation.</cell> +</row> +<row> + <cell>2.1</cell> + <cell>Transport</cell> + <cell>PC</cell> + <cell>Ports are configured by the user: diameter places no + restrictions.&BR; + The transport interface documented in &man_transport; + allows the user to implement their own methods. + Ready support is provided for TCP, TCP/TLS, and SCTP, but not + DTLS/SCTP.&BR; + Multiple connections to the same peer is possible. + ICMP messages are not interpreted.</cell> +</row> +<row> + <cell>2.1.1</cell> + <cell>SCTP Guidelines</cell> + <cell>C</cell> + <cell>Unordered sending is configurable in &man_sctp;. + There is no special handling of DPR/DPA: since a user that cares + about pending answers should wait for them before initiating + DPR.&BR; + A PPID can be configured with a a gen_sctp sctp_default_send_param + option.</cell> +</row> +<row> + <cell>2.2</cell> + <cell>Securing Diameter Messages</cell> + <cell>PC</cell> + <cell>DTLS is not supported by &man_sctp;. See also + 2.1.</cell> +</row> +<row> + <cell>2.3</cell> + <cell>Diameter Application Compliance</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>2.4</cell> + <cell>Application Identifiers</cell> + <cell>C</cell> + <cell>The user configures diameter with the identifiers to send at + capabilities exchange, along with corresponding dictionaries + defining the messages of the applications.</cell> +</row> +<row> + <cell>2.5</cell> + <cell>Connections vs. Sessions</cell> + <cell>C</cell> + <cell>Connections are realized by configuring transport. Sessions + are the responsibility of the user.</cell> +</row> +<row> + <cell>2.6</cell> + <cell>Peer Table</cell> + <cell>PC</cell> + <cell>Routing is implemented by the user in callbacks documented in + &man_app;. + A peer table of the documented form is not exposed to the user.</cell> +</row> +<row> + <cell>2.7</cell> + <cell>Routing Table</cell> + <cell>PC</cell> + <cell>See 2.6. + A routing table of the documented form is not exposed to + the user.</cell> +</row> +<row> + <cell>2.8</cell> + <cell>Role of Diameter Agents</cell> + <cell>C</cell> + <cell>Most role-specific behaviour is implemented by the user. + How a node advertises itself at capabilities exchange is determined + by user configuration.</cell> +</row> +<row> + <cell>2.8.1</cell> + <cell>Relay Agents</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>2.8.2</cell> + <cell>Proxy Agents</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>2.8.3</cell> + <cell>Redirect Agents</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>2.8.4</cell> + <cell>Translation Agents</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>2.9</cell> + <cell>Diameter Path Authorization</cell> + <cell>&NA;</cell> + <cell>Authorization is the responsibility of the user.</cell> +</row> +<row> + <cell>3</cell> + <cell>Diameter Header</cell> + <cell>C</cell> + <cell>Hop-by-Hop and End-to-End Identifiers are set by diameter when + sending outgoing requests.</cell> +</row> +<row> + <cell>3.1</cell> + <cell>Command Codes</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>3.2</cell> + <cell>Command Code Format Specification</cell> + <cell>C</cell> + <cell>Commands are defined as CCF specifications in dictionary + files.</cell> +</row> +<row> + <cell>3.3</cell> + <cell>Diameter Command Naming Conventions</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>4</cell> + <cell>Diameter AVPs</cell> + <cell>C</cell> + <cell>Any required padding is added by diameter when encoding + outgoing messages.</cell> +</row> +<row> + <cell>4.1</cell> + <cell>AVP Header</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>4.1.1</cell> + <cell>Optional Header Elements</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>4.2</cell> + <cell>Basic AVP Data Formats</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>4.3</cell> + <cell>Derived AVP Data Formats</cell> + <cell>C</cell> + <cell>Arbitrary derived data formats are supported by the dictionary + interface.</cell> +</row> +<row> + <cell>4.3.1</cell> + <cell>Common Derived AVP Data Formats</cell> + <cell>C</cell> + <cell>Beware that RFC 6733 changed the DiameterURI transport/port + defaults specified in RFC3588. + Relying on the defaults can result in interoperability + problems.</cell> +</row> +<row> + <cell>4.4</cell> + <cell>Grouped AVP Values</cell> + <cell>C</cell> + <cell>The M-bit on a component AVP of a Grouped AVP that does not + set M is ignored: such AVPs are not regarded as erroneous at + decode.&BR; + Grouped AVPs are defined as CCF specifications in dictionary + files.</cell> +</row> +<row> + <cell>4.4.1</cell> + <cell>Example AVP with a Grouped Data Type</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>4.5</cell> + <cell>Diameter Base Protocol AVPs</cell> + <cell>C</cell> + <cell>The base AVPs are defined in the common dictionary provided by + diameter. + There are common dictionaries for both RFC 3588 and RFC 6733 since + the latter made changes to both syntax and semantics.</cell> +</row> +<row> + <cell>5</cell> + <cell>Diameter Peers</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>5.1</cell> + <cell>Peer Connections</cell> + <cell>PC</cell> + <cell>A peer's DiameterIdentity is not required when initiating a + connection: the identify is received at capabilities exchange, at + which time the connection can be rejected if the identity is + objectionable.&BR; + The number of connections established depends on the user's + configuration. Multiple connections per peer is possible.</cell> +</row> +<row> + <cell>5.2</cell> + <cell>Diameter Peer Discovery</cell> + <cell>NC</cell> + <cell>No form of peer discovery is implemented. + The user can implement this independently of diameter if + required.</cell> +</row> +<row> + <cell>5.3</cell> + <cell>Capabilities Exchange</cell> + <cell>C</cell> + <cell>All supported applications are sent in CEA. + The user can reject an incoming CER or CEA in a configured + callback.&BR; + Both transport security at connection establishment and + negotiated via an Inband-Security AVP are supported.</cell> +</row> +<row> + <cell>5.3.1</cell> + <cell>Capabilities-Exchange-Request</cell> + <cell>C</cell> + <cell>CER is sent and received by diameter.</cell> +</row> +<row> + <cell>5.3.2</cell> + <cell>Capabilities-Exchange-Answer</cell> + <cell>C</cell> + <cell>CEA is sent and received by diameter.</cell> +</row> +<row> + <cell>5.3.3</cell> + <cell>Vendor-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.3.4</cell> + <cell>Firmware-Revision AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.3.5</cell> + <cell>Host-IP-Address AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.3.6</cell> + <cell>Supported-Vendor-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.3.7</cell> + <cell>Product-Name AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.4</cell> + <cell>Disconnecting Peer Connections</cell> + <cell>C</cell> + <cell>DPA will not be answered with error: a peer that wants to a + avoid a race can wait for pending answers before sending + DPR.</cell> +</row> +<row> + <cell>5.4.1</cell> + <cell>Disconnect-Peer-Request</cell> + <cell>C</cell> + <cell>DPR is sent by diameter in response to configuration + changes requiring a connection to be broken. + The user can also send DPR.</cell> +</row> +<row> + <cell>5.4.2</cell> + <cell>Disconnect-Peer-Answer</cell> + <cell>C</cell> + <cell>DPR is answered by diameter.</cell> +</row> +<row> + <cell>5.4.3</cell> + <cell>Disconnect-Cause AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.5</cell> + <cell>Transport Failure Detection</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>5.5.1</cell> + <cell>Device-Watchdog-Request</cell> + <cell>C</cell> + <cell>DWR is sent and received by diameter. + Callbacks notify the user of transitions into and out of the OKAY + state.</cell> +</row> +<row> + <cell>5.5.2</cell> + <cell>Device-Watchdog-Answer</cell> + <cell>C</cell> + <cell>DWA is sent and received by diameter.</cell> +</row> +<row> + <cell>5.5.3</cell> + <cell>Transport Failure Algorithm</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.5.4</cell> + <cell>Failover and Failback Procedures</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.6</cell> + <cell>Peer State Machine</cell> + <cell>PC</cell> + <cell>The election process is modified as described in 5.6.4.</cell> +</row> +<row> + <cell>5.6.1</cell> + <cell>Incoming Connections</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>5.6.2</cell> + <cell>Events</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>5.6.3</cell> + <cell>Actions</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>5.6.4</cell> + <cell>The Election Process</cell> + <cell>PC</cell> + <cell>As documented, the election assumes knowledge of a peer's + DiameterIdentity when initiating a connection, which diameter + doesn't require. Connections will be accepted if configuration + allows multiple connections per peer to be established or there is + no existing connection. Note that the election process is only + applicable when multiple connections per peer is + disallowed.</cell> +</row> +<row> + <cell>6</cell> + <cell>Diameter Message Processing</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>6.1</cell> + <cell>Diameter Request Routing Overview</cell> + <cell>&NA;</cell> + <cell>Routing is performed by the user. + A callback from diameter provides a list of available suitable peer + connections.</cell> +</row> +<row> + <cell>6.1.1</cell> + <cell>Originating a Request</cell> + <cell>C</cell> + <cell>Requests are constructed by the user; diameter sets header + fields as defined in the relevant dictionary.</cell> +</row> +<row> + <cell>6.1.2</cell> + <cell>Sending a Request</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.1.3</cell> + <cell>Receiving Requests</cell> + <cell>C</cell> + <cell>Loops are detected by diameter when the return value of a + request callback asks that a request be forwarded. + Loop detection in other cases is the responsibility of the + user.</cell> +</row> +<row> + <cell>6.1.4</cell> + <cell>Processing Local Requests</cell> + <cell>C</cell> + <cell>The user decides whether or not to process a request locally + in the request callback from diameter.</cell> +</row> +<row> + <cell>6.1.5</cell> + <cell>Request Forwarding</cell> + <cell>PC</cell> + <cell>See 2.6.</cell> +</row> +<row> + <cell>6.1.6</cell> + <cell>Request Routing</cell> + <cell>PC</cell> + <cell>See 2.7.</cell> +</row> +<row> + <cell>6.1.7</cell> + <cell>Predictive Loop Avoidance</cell> + <cell>C</cell> + <cell>See 6.1.3.</cell> +</row> +<row> + <cell>6.1.8</cell> + <cell>Redirecting Requests</cell> + <cell>PC</cell> + <cell>See 2.6.</cell> +</row> +<row> + <cell>6.1.9</cell> + <cell>Relaying and Proxying Requests</cell> + <cell>C</cell> + <cell>A Route-Record AVP is appended by diameter when the return + value of a request callback asks that a request be forwarded. + Appending the AVP in other cases is the responsibility of the + user.</cell> +</row> +<row> + <cell>6.2</cell> + <cell>Diameter Answer Processing</cell> + <cell>C</cell> + <cell>Answer message are constructed by the user, except in the case + of some protocol errors, in which case the procedures are + followed.</cell> +</row> +<row> + <cell>6.2.1</cell> + <cell>Processing Received Answers</cell> + <cell>C</cell> + <cell>Answers with an unknown Hop-by-Hop Identifier are + discarded.</cell> +</row> +<row> + <cell>6.2.2</cell> + <cell>Relaying and Proxying Answers</cell> + <cell>&NA;</cell> + <cell>Modifying answers is the responsibility of the user in + callbacks from diameter.</cell> +</row> +<row> + <cell>6.3</cell> + <cell>Origin-Host AVP</cell> + <cell>C</cell> + <cell>The order of AVPs in an encoded message is determined by + the CCF of the message in question.&BR; + AVPs defined in the RFC are defined in dictionaries provided by + diameter. + Their proper use in application messages is the responsibility of + the user.</cell> +</row> +<row> + <cell>6.4</cell> + <cell>Origin-Realm AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.5</cell> + <cell>Destination-Host AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.6</cell> + <cell>Destination-Realm AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.7</cell> + <cell>Routing AVPs</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>6.7.1</cell> + <cell>Route-Record AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.7.2</cell> + <cell>Proxy-Info AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.7.3</cell> + <cell>Proxy-Host AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.7.4</cell> + <cell>Proxy-State AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.8</cell> + <cell>Auth-Application-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.9</cell> + <cell>Acct-Application-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.10</cell> + <cell>Inband-Security-Id AVP</cell> + <cell>C</cell> + <cell>See 2.1.</cell> +</row> +<row> + <cell>6.11</cell> + <cell>Vendor-Specific-Application-Id AVP</cell> + <cell>C</cell> + <cell>Note that the CCF of this AVP is not the same as in RFC + 3588.</cell> +</row> +<row> + <cell>6.12</cell> + <cell>Redirect-Host AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.13</cell> + <cell>Redirect-Host-Usage AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>6.14</cell> + <cell>Redirect-Max-Cache-Time AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>7</cell> + <cell>Error Handling</cell> + <cell>C</cell> + <cell>Answers are formulated by the user in most cases. + Answers setting the E-bit can be sent by diameter itself in response + to a request that cannot be handled by the user.</cell> +</row> +<row> + <cell>7.1</cell> + <cell>Result-Code AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>7.1.1</cell> + <cell>Informational</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>7.1.2</cell> + <cell>Success</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>7.1.3</cell> + <cell>Protocol Errors</cell> + <cell>C</cell> + <cell>Result codes 3001, 3002, 3005, and 3007 can be sent in answers + formulated by diameter, if configured to do so.</cell> +</row> +<row> + <cell>7.1.4</cell> + <cell>Transient Failures</cell> + <cell>C</cell> + <cell>Result code 4003 is sent in CEA if there is an existing + connection to the peer in question and configuration does not allow + more than one.</cell> +</row> +<row> + <cell>7.1.5</cell> + <cell>Permanent Failures</cell> + <cell>C</cell> + <cell>Message reception detects 5001, 5004, + 5005, 5008, 5009, 5010, 5011, 5014, 5015, and 5017 errors. + It ignores 5013 errors at the admonition of sections 3 and 4.1.&BR; + Note that RFC 3588 did not allow 5xxx result codes in + answers setting the E-bit, while RFC 6733 does. + This is a potential interoperability problem since the Diameter + protocol version has not changed.</cell> +</row> +<row> + <cell>7.2</cell> + <cell>Error Bit</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>7.3</cell> + <cell>Error-Message AVP</cell> + <cell>C</cell> + <cell>The user can include this AVP as required.</cell> +</row> +<row> + <cell>7.4</cell> + <cell>Error-Reporting-Host AVP</cell> + <cell>C</cell> + <cell>The user can include this AVP as required.</cell> +</row> +<row> + <cell>7.5</cell> + <cell>Failed-AVP AVP</cell> + <cell>C</cell> + <cell>The user constructs application-specific messages, but + diameter provides failed AVPs in message callbacks. Failed component AVPs + are grouped within the relevant Grouped AVPs.</cell> +</row> +<row> + <cell>7.6</cell> + <cell>Experimental-Result AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>7.7</cell> + <cell>Experimental-Result-Code AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8</cell> + <cell>Diameter User Sessions</cell> + <cell>&NA;</cell> + <cell>Authorization and accounting AVPs are defined in provided + dictionaries. Their proper use is the responsibility of the + user.</cell> +</row> +<row> + <cell>8.1</cell> + <cell>Authorization Session State Machine</cell> + <cell>&NA;</cell> + <cell>Authorization is the responsibility of the user: diameter does + not implement this state machine.</cell> +</row> +<row> + <cell>8.2</cell> + <cell>Accounting Session State Machine</cell> + <cell>&NA;</cell> + <cell>Accounting is the responsibility of the user: diameter does + not implement this state machine.</cell> +</row> +<row> + <cell>8.3</cell> + <cell>Server-Initiated Re-Auth</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>8.3.1</cell> + <cell>Re-Auth-Request</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.3.2</cell> + <cell>Re-Auth-Answer</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.4</cell> + <cell>Session Termination</cell> + <cell>&NA;</cell> + <cell>Session-related messages and AVPs are defined in provided + dictionaries. Their proper use is the user's responsibility.</cell> +</row> +<row> + <cell>8.4.1</cell> + <cell>Session-Termination-Request</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.4.2</cell> + <cell>Session-Termination-Answer</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.5</cell> + <cell>Aborting a Session</cell> + <cell>&NA;</cell> + <cell>Session-related messages and AVPs are defined in provided + dictionaries. Their proper use is the user's responsibility.</cell> +</row> +<row> + <cell>8.5.1</cell> + <cell>Abort-Session-Request</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.5.2</cell> + <cell>Abort-Session-Answer</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.6</cell> + <cell>Inferring Session Termination from Origin-State-Id</cell> + <cell>&NA;</cell> + <cell>Session-related messages and AVPs are defined in provided + dictionaries. Their proper use is the user's responsibility.</cell> +</row> +<row> + <cell>8.7</cell> + <cell>Auth-Request-Type AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.8</cell> + <cell>Session-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.9</cell> + <cell>Authorization-Lifetime AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.10</cell> + <cell>Auth-Grace-Period AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.11</cell> + <cell>Auth-Session-State AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.12</cell> + <cell>Re-Auth-Request-Type AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.13</cell> + <cell>Session-Timeout AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.14</cell> + <cell>User-Name AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.15</cell> + <cell>Termination-Cause AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.16</cell> + <cell>Origin-State-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.17</cell> + <cell>Session-Binding AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.18</cell> + <cell>Session-Server-Failover AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.19</cell> + <cell>Multi-Round-Time-Out AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.20</cell> + <cell>Class AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>8.21</cell> + <cell>Event-Timestamp AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9</cell> + <cell>Accounting</cell> + <cell>&NA;</cell> + <cell>Accounting-related messages and AVPs are defined in provided + dictionaries. Their proper use is the user's responsibility.</cell> +</row> +<row> + <cell>9.1</cell> + <cell>Server Directed Model</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>9.2</cell> + <cell>Protocol Messages</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>9.3</cell> + <cell>Accounting Application Extension and Requirements</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>9.4</cell> + <cell>Fault Resilience</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>9.5</cell> + <cell>Accounting Records</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>9.6</cell> + <cell>Correlation of Accounting Records</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>9.7</cell> + <cell>Accounting Command Codes</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>9.7.1</cell> + <cell>Accounting-Request</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9.7.2</cell> + <cell>Accounting-Answer</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9.8</cell> + <cell>Accounting AVPs</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>9.8.1</cell> + <cell>Accounting-Record-Type AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9.8.2</cell> + <cell>Acct-Interim-Interval AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9.8.3</cell> + <cell>Accounting-Record-Number AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9.8.4</cell> + <cell>Acct-Session-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9.8.5</cell> + <cell>Acct-Multi-Session-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9.8.6</cell> + <cell>Accounting-Sub-Session-Id AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>9.8.7</cell> + <cell>Accounting-Realtime-Required AVP</cell> + <cell>C</cell> + <cell></cell> +</row> +<row> + <cell>10</cell> + <cell>AVP Occurrence Tables</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>10.1</cell> + <cell>Base Protocol Command AVP Table</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>10.2</cell> + <cell>Accounting AVP Table</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11</cell> + <cell>IANA Considerations</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.1</cell> + <cell>AVP Header</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.1.1</cell> + <cell>AVP Codes</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.1.2</cell> + <cell>AVP Flags</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.2</cell> + <cell>Diameter Header</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.2.1</cell> + <cell>Command Codes</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.2.2</cell> + <cell>Command Flags</cell> + <cell></cell> + <cell></cell> +</row> +<row> + <cell>11.3</cell> + <cell>AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.1</cell> + <cell>Experimental-Result-Code AVP</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.2</cell> + <cell>Result-Code AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.3</cell> + <cell>Accounting-Record-Type AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.4</cell> + <cell>Termination-Cause AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.5</cell> + <cell>Redirect-Host-Usage AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.6</cell> + <cell>Session-Server-Failover AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.7</cell> + <cell>Session-Binding AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.8</cell> + <cell>Disconnect-Cause AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.9</cell> + <cell>Auth-Request-Type AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.10</cell> + <cell>Auth-Session-State AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.11</cell> + <cell>Re-Auth-Request-Type AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.12</cell> + <cell>Accounting-Realtime-Required AVP Values</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.3.13</cell> + <cell>Inband-Security-Id AVP (code 299)</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.4</cell> + <cell>_diameters Service Name and Port Number Registration</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.5</cell> + <cell>SCTP Payload Protocol Identifiers</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>11.6</cell> + <cell>S-NAPTR Parameters</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>12</cell> + <cell>Diameter Protocol-Related Configurable Parameters</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>13</cell> + <cell>Security Considerations</cell> + <cell>PC</cell> + <cell>See 2.1.&BR; + IPsec is transparent to diameter.</cell> +</row> +<row> + <cell>13.1</cell> + <cell>TLS/TCP and DTLS/SCTP Usage</cell> + <cell>PC</cell> + <cell>See 2.1.</cell> +</row> +<row> + <cell>13.2</cell> + <cell>Peer-to-Peer Considerations</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>13.3</cell> + <cell>AVP Considerations</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>14</cell> + <cell>References</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>14.1</cell> + <cell>Normative References</cell> + <cell>&NA;</cell> + <cell></cell> +</row> +<row> + <cell>14.2</cell> + <cell>Informative References</cell> + <cell>&NA;</cell> + <cell></cell> +</row> + +<tcaption>RFC 6733 Compliance</tcaption> +</table> </section> </chapter> + +<!-- LocalWords: AVP AVPs CCF DiameterIdentity CEA CER Inband IP +--> +<!-- LocalWords: DPA DPR DWR DWA Failover Failback Proxying Auth +--> +<!-- LocalWords: interoperability Multi Timestamp Realtime +--> diff --git a/lib/diameter/doc/src/diameter_soc_rfc6733.xml b/lib/diameter/doc/src/diameter_soc_rfc6733.xml deleted file mode 100644 index 2098965706..0000000000 --- a/lib/diameter/doc/src/diameter_soc_rfc6733.xml +++ /dev/null @@ -1,8693 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> - -<!-- - -<copyright> -<year>2013</year><year>2016</year> -<holder>Ericsson AB. All Rights Reserved.</holder> -</copyright> - -<legalnotice> -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -</legalnotice> - ---> - -<!DOCTYPE section SYSTEM "chapter.dtd" [ - <!ENTITY gen_sctp '<seealso marker="kernel:gen_sctp">gen_sctp(3)</seealso>'> - <!ENTITY gen_tcp '<seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso>'> - <!ENTITY service '<seealso marker="diameter#start_service-2">service</seealso>'> - <!ENTITY capabilities '<seealso marker="diameter#capability">capabilities</seealso>'> - <!ENTITY events '<seealso marker="diameter#service_event">events</seealso>'> - <!ENTITY nada '<p>No comment.</p>'> - <!ENTITY % also SYSTEM "seealso.ent" > - %also; -]> - -<section> -<title>Commentary</title> - -<p> -A more detailed commentary on &the_rfc; follows. -Its purpose is to (hopefully) clarify not only what is supported but -how, given that semantics and features discussed in the RFC are not -solely the responsibility of the diameter application: -in many cases much depends on the configuration a user passes to -diameter, the implementation of &man_app; callback modules in -particular.</p> - -<p> -Comments apply to all text following the preceding comment. -Be sure to distinguish between capitalized <em>Diameter</em>, the -protocol defined by the RFC, and lowercase <em>diameter</em>, the -Erlang application to which the commentary applies.</p> - -<warning> -<p> -The commentary is not yet complete. -Comments currently stop at chapter 4.</p> -</warning> - -<pre> -Fajardo, et al. Standards Track [Page 6] - -RFC 6733 Diameter Base Protocol October 2012 - - -1. Introduction - - Authentication, Authorization, and Accounting (AAA) protocols such as - TACACS [RFC1492] and RADIUS [RFC2865] were initially deployed to - provide dial-up PPP [RFC1661] and terminal server access. Over time, - AAA support was needed on many new access technologies, the scale and - complexity of AAA networks grew, and AAA was also used on new - applications (such as voice over IP). This led to new demands on AAA - protocols. -</pre> - -<p> -Note that diameter implements the Diameter protocol as defined in -&the_rfc;. -It also supported the previous version of the protocol, as defined in -RFC 3588, when there are differences. -(Which will be noted below.) -It does not support RADIUS.</p> - -<pre> - - Network access requirements for AAA protocols are summarized in - Aboba, et al. [RFC2989]. These include: - - Failover - - [RFC2865] does not define failover mechanisms and, as a result, - failover behavior differs between implementations. In order to - provide well-defined failover behavior, Diameter supports - application-layer acknowledgements and defines failover algorithms - and the associated state machine. -</pre> - -&nada; - -<pre> - - Transmission-level security - - RADIUS [RFC2865] defines an application-layer authentication and - integrity scheme that is required only for use with response - packets. While [RFC2869] defines an additional authentication and - integrity mechanism, use is only required during Extensible - Authentication Protocol (EAP) [RFC3748] sessions. While attribute - hiding is supported, [RFC2865] does not provide support for per- - packet confidentiality. In accounting, [RFC2866] assumes that - replay protection is provided by the backend billing server rather - than within the protocol itself. - - While [RFC3162] defines the use of IPsec with RADIUS, support for - IPsec is not required. In order to provide universal support for - transmission-level security, and enable both intra- and inter- - domain AAA deployments, Diameter provides support for TLS/TCP and - DTLS/SCTP. Security is discussed in Section 13. -</pre> - -<p> -Whether or not IPsec is used is transparent to diameter.</p> - -<p> -The transport protocol used on a given peer connection is also -transparent to diameter in that transport to diameter is simply a -module that implements the transport protocol documented in -&man_transport;. -A diameter user configures this module as the &mod_transport_opt; -<c>transport_module</c>.</p> - -<p> -While a user can implement their own transport modules, diameter -includes implementations for TCP and SCTP: -&man_tcp; based on &gen_tcp; and &man_sctp; based on &gen_sctp;. -The former supports TLS but the latter does not currently support -DTLS.</p> - -<pre> - - Reliable transport - - RADIUS runs over UDP, and does not define retransmission behavior; - as a result, reliability varies between implementations. As - described in [RFC2975], this is a major issue in accounting, where - packet loss may translate directly into revenue loss. In order to - - - - - - -Fajardo, et al. Standards Track [Page 7] - -RFC 6733 Diameter Base Protocol October 2012 - - - provide well-defined transport behavior, Diameter runs over - reliable transport mechanisms (TCP, Stream Control Transmission - Protocol (SCTP)) as defined in [RFC3539]. - - Agent support - - RADIUS does not provide for explicit support for agents, including - proxies, redirects, and relays. Since the expected behavior is - not defined, it varies between implementations. Diameter defines - agent behavior explicitly; this is described in Section 2.8. -</pre> - -&nada; - -<pre> - - Server-initiated messages - - While server-initiated messages are defined in RADIUS [RFC5176], - support is optional. This makes it difficult to implement - features such as unsolicited disconnect or re-authentication/ - re-authorization on demand across a heterogeneous deployment. To - address this issue, support for server-initiated messages is - mandatory in Diameter. -</pre> - -<p> -A diameter user can both send and receive messages.</p> - -<pre> - - Transition support - - While Diameter does not share a common protocol data unit (PDU) - with RADIUS, considerable effort has been expended in enabling - backward compatibility with RADIUS so that the two protocols may - be deployed in the same network. Initially, it is expected that - Diameter will be deployed within new network devices, as well as - within gateways enabling communication between legacy RADIUS - devices and Diameter agents. This capability enables Diameter - support to be added to legacy networks, by addition of a gateway - or server speaking both RADIUS and Diameter. -</pre> - -<p> -RADIUS Attributes can be redefined as Diameter AVP's using diameter's -&man_dict; interface but diameter provides no such definitions.</p> - -<pre> - - In addition to addressing the above requirements, Diameter also - provides support for the following: - - Capability negotiation - - RADIUS does not support error messages, capability negotiation, or - a mandatory/non-mandatory flag for attributes. Since RADIUS - clients and servers are not aware of each other's capabilities, - they may not be able to successfully negotiate a mutually - acceptable service or, in some cases, even be aware of what - service has been implemented. Diameter includes support for error - handling (Section 7), capability negotiation (Section 5.3), and - mandatory/non-mandatory Attribute-Value Pairs (AVPs) - (Section 4.1). - - - - - -Fajardo, et al. Standards Track [Page 8] - -RFC 6733 Diameter Base Protocol October 2012 - - - Peer discovery and configuration - - RADIUS implementations typically require that the name or address - of servers or clients be manually configured, along with the - corresponding shared secrets. This results in a large - administrative burden and creates the temptation to reuse the - RADIUS shared secret, which can result in major security - vulnerabilities if the Request Authenticator is not globally and - temporally unique as required in [RFC2865]. Through DNS, Diameter - enables dynamic discovery of peers (see Section 5.2). Derivation - of dynamic session keys is enabled via transmission-level - security. - - Over time, the capabilities of Network Access Server (NAS) devices - have increased substantially. As a result, while Diameter is a - considerably more sophisticated protocol than RADIUS, it remains - feasible to implement it within embedded devices. -</pre> - -&nada; - -<pre> - -1.1. Diameter Protocol - - The Diameter base protocol provides the following facilities: - - o Ability to exchange messages and deliver AVPs -</pre> - -<p> -There are two interfaces directly involved in message exchange when -using diameter: the function &mod_call; for sending outgoing requests, -and the application callback interface, documented in &man_app; for -receiving incoming request and answers.</p> - -<pre> - - o Capabilities negotiation -</pre> - -<p> -Capabilities negotiation is the responsibility of diameter: -a user configures a diameter service and/or transport with -&capabilities; to provide AVP values for CER and CEA messages but it -is diameter itself that sends these messages. -A user receives notification of a successful capabilities exchange by -way of &app_peer_up; callbacks.</p> - -<pre> - - o Error notification -</pre> - -<p> -A user can subscribe to &events;, using &mod_subscribe;, in order to -receive notification of various failures. -Errors in Diameter messaging are communicated via the application -callbacks &app_handle_request;, &app_handle_answer; and -&app_handle_error;.</p> - - -<pre> - - o Extensibility, required in [RFC2989], through addition of new - applications, commands, and AVPs -</pre> - -<p> -Support for applications, commands and AVP's is extensible using -diameter's dictionary interface, as documented in &man_dict;. -Dictionaries are compiled to Erlang encode/decode modules using -&man_compile; or &man_make;.</p> - -<pre> - - o Basic services necessary for applications, such as the handling of - user sessions or accounting -</pre> - -<p> -Compiled dictionaries are provided for the RFC 3588 and RFC 6733 -Diameter applications: common, base accounting and relay. -Dictionaries for a number of standardized -applications are provided in uncompiled form below the <c>examples</c> -subdirectory of the diameter application directory.</p> - -<pre> - - All data delivered by the protocol is in the form of AVPs. Some of - these AVP values are used by the Diameter protocol itself, while - others deliver data associated with particular applications that - employ Diameter. AVPs may be arbitrarily added to Diameter messages, - the only restriction being that the Command Code Format (CCF) - specification (Section 3.2) be satisfied. AVPs are used by the base - Diameter protocol to support the following required features: - - o Transporting of user authentication information, for the purposes - of enabling the Diameter server to authenticate the user - - o Transporting of service-specific authorization information, - between client and servers, allowing the peers to decide whether a - user's access request should be granted - - - -Fajardo, et al. Standards Track [Page 9] - -RFC 6733 Diameter Base Protocol October 2012 - - - o Exchanging resource usage information, which may be used for - accounting purposes, capacity planning, etc. - - o Routing, relaying, proxying, and redirecting of Diameter messages - through a server hierarchy - - The Diameter base protocol satisfies the minimum requirements for a - AAA protocol, as specified by [RFC2989]. The base protocol may be - used by itself for accounting purposes only, or it may be used with a - Diameter application, such as Mobile IPv4 [RFC4004], or network - access [RFC4005]. It is also possible for the base protocol to be - extended for use in new applications, via the addition of new - commands or AVPs. The initial focus of Diameter was network access - and accounting applications. A truly generic AAA protocol used by - many applications might provide functionality not provided by - Diameter. Therefore, it is imperative that the designers of new - applications understand their requirements before using Diameter. - See Section 1.3.4 for more information on Diameter applications. - - Any node can initiate a request. In that sense, Diameter is a peer- - to-peer protocol. In this document, a Diameter client is a device at - the edge of the network that performs access control, such as a - Network Access Server (NAS) or a Foreign Agent (FA). A Diameter - client generates Diameter messages to request authentication, - authorization, and accounting services for the user. A Diameter - agent is a node that does not provide local user authentication or - authorization services; agents include proxies, redirects, and relay - agents. A Diameter server performs authentication and/or - authorization of the user. A Diameter node may act as an agent for - certain requests while acting as a server for others. - - The Diameter protocol also supports server-initiated messages, such - as a request to abort service to a particular user. -</pre> - -&nada; - -<pre> - -1.1.1. Description of the Document Set - - The Diameter specification consists of an updated version of the base - protocol specification (this document) and the Transport Profile - [RFC3539]. This document obsoletes both RFC 3588 and RFC 5719. A - summary of the base protocol updates included in this document can be - found in Section 1.1.3. - - This document defines the base protocol specification for AAA, which - includes support for accounting. There are also a myriad of - applications documents describing applications that use this base - specification for Authentication, Authorization, and Accounting. - These application documents specify how to use the Diameter protocol - within the context of their application. - - - -Fajardo, et al. Standards Track [Page 10] - -RFC 6733 Diameter Base Protocol October 2012 - - - The Transport Profile document [RFC3539] discusses transport layer - issues that arise with AAA protocols and recommendations on how to - overcome these issues. This document also defines the Diameter - failover algorithm and state machine. - - "Clarifications on the Routing of Diameter Request Based on the - Username and the Realm" [RFC5729] defines specific behavior on how to - route requests based on the content of the User-Name AVP (Attribute - Value Pair). - -1.1.2. Conventions Used in This Document - - The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", - "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this - document are to be interpreted as described in [RFC2119]. -</pre> - -&nada; - -<pre> - -1.1.3. Changes from RFC 3588 - - This document obsoletes RFC 3588 but is fully backward compatible - with that document. The changes introduced in this document focus on - fixing issues that have surfaced during the implementation of - Diameter (RFC 3588). An overview of some the major changes are given - below. -</pre> - -<p> -RFC 6733 is not fully backwards compatible with RFC 3588. -(For example, in what values of Result-Code values are permissible with -the E-bit.) -The implications of incompatibilities for diameter are noted where -appropriate.</p> - -<pre> - - o Deprecated the use of the Inband-Security AVP for negotiating - Transport Layer Security (TLS) [RFC5246]. It has been generally - considered that bootstrapping of TLS via Inband-Security AVP - creates certain security risks because it does not completely - protect the information carried in the CER/CEA (Capabilities- - Exchange-Request/Capabilities-Exchange-Answer). This version of - Diameter adopts the common approach of defining a well-known - secured port that peers should use when communicating via TLS/TCP - and DTLS/SCTP. This new approach augments the existing in-band - security negotiation, but it does not completely replace it. The - old method is kept for backward compatibility reasons. -</pre> - -<p> -&man_tcp; supports both methods of negotiating TLS: -bootstrapping via Inband-Security and directly following connection -establishment.</p> - -<pre> - - o Deprecated the exchange of CER/CEA messages in the open state. - This feature was implied in the peer state machine table of RFC - 3588, but it was not clearly defined anywhere else in that - document. As work on this document progressed, it became clear - that the multiplicity of meaning and use of Application-Id AVPs in - the CER/CEA messages (and the messages themselves) is seen as an - abuse of the Diameter extensibility rules and thus required - simplification. Capabilities exchange in the open state has been - re-introduced in a separate specification [RFC6737], which clearly - defines new commands for this feature. -</pre> - -<p> -Capabilities exchange in the open state is not supported: an incoming -CER in the open state will cause diameter to ask the relevant -transport process to terminate, which implies the loss of the peer -connection in the case of &man_tcp; and &man_sctp;.</p> - -<p> -Capabilities update, as defined by RFC 6737, is not yet supported. -Support will require diameter to handle CUR/CUA in the same way that -it handles CER/CEA.</p> - -<pre> - - - - - -Fajardo, et al. Standards Track [Page 11] - -RFC 6733 Diameter Base Protocol October 2012 - - - o Simplified security requirements. The use of a secured transport - for exchanging Diameter messages remains mandatory. However, TLS/ - TCP and DTLS/SCTP have become the primary methods of securing - Diameter with IPsec as a secondary alternative. See Section 13 - for details. The support for the End-to-End security framework - (E2E-Sequence AVP and 'P'-bit in the AVP header) has also been - deprecated. -</pre> - -<p> -The End-to-End security framework is not supported since it's use is -largely unspecified: diameter will set the P-bit in outgoing AVP's as -directed by the relevant dictionary and/or &app_prepare_request; or -&app_handle_request; callbacks, but whether or not the P-bit is set on -incoming AVP's has no consequence.</p> - -<p> -As noted above, DTLS is not currently supported and whether or not -IPsec is used is transparent to diameter.</p> - -<pre> - - o Changed Diameter extensibility. This includes fixes to the - Diameter extensibility description (Section 1.3 and others) to - better aid Diameter application designers; in addition, the new - specification relaxes the policy with respect to the allocation of - Command Codes for vendor-specific uses. - - o Clarified Application Id usage. Clarify the proper use of - Application Id information, which can be found in multiple places - within a Diameter message. This includes correlating Application - Ids found in the message headers and AVPs. These changes also - clearly specify the proper Application Id value to use for - specific base protocol messages (ASR/ASA, STR/STA) as well as - clarify the content and use of Vendor-Specific-Application-Id. - - o Clarified routing fixes. This document more clearly specifies - what information (AVPs and Application Ids) can be used for making - general routing decisions. A rule for the prioritization of - redirect routing criteria when multiple route entries are found - via redirects has also been added (see Section 6.13). - - o Simplified Diameter peer discovery. The Diameter discovery - process now supports only widely used discovery schemes; the rest - have been deprecated (see Section 5.2 for details). -</pre> - -<p> -Peer discover is not currently supported: peers to which a node should -connect must be configured. -Connection requests are accepted from arbitrary peers but a -&mod_transport_opt; <c>capabilities_cb</c> can be used to reject a -peer based on an incoming CER or CEA.</p> - -<pre> - - There are many other miscellaneous fixes that have been introduced in - this document that may not be considered significant, but they have - value nonetheless. Examples are removal of obsolete types, fixes to - the state machine, clarification of the election process, message - validation, fixes to Failed-AVP and Result-Code AVP values, etc. All - of the errata filed against RFC 3588 prior to the publication of this - document have been addressed. A comprehensive list of changes is not - shown here for practical reasons. - -1.2. Terminology - - AAA - - Authentication, Authorization, and Accounting. - - - - - -Fajardo, et al. Standards Track [Page 12] - -RFC 6733 Diameter Base Protocol October 2012 - - - ABNF - - Augmented Backus-Naur Form [RFC5234]. A metalanguage with its own - formal syntax and rules. It is based on the Backus-Naur Form and - is used to define message exchanges in a bi-directional - communications protocol. - - Accounting - - The act of collecting information on resource usage for the - purpose of capacity planning, auditing, billing, or cost - allocation. - - Accounting Record - - An accounting record represents a summary of the resource - consumption of a user over the entire session. Accounting servers - creating the accounting record may do so by processing interim - accounting events or accounting events from several devices - serving the same user. - - Authentication - - The act of verifying the identity of an entity (subject). - - Authorization - - The act of determining whether a requesting entity (subject) will - be allowed access to a resource (object). - - Attribute-Value Pair (AVP) - - The Diameter protocol consists of a header followed by one or more - Attribute-Value-Pairs (AVPs). An AVP includes a header and is - used to encapsulate protocol-specific data (e.g., routing - information) as well as authentication, authorization, or - accounting information. -</pre> - -&nada; - -<pre> - - Command Code Format (CCF) - - A modified form of ABNF used to define Diameter commands (see - Section 3.2). -</pre> - -<p> -The <c>@messages</c> section of the &man_dict; format has the CCF as -content.</p> - -<pre> - - Diameter Agent - - A Diameter Agent is a Diameter node that provides relay, proxy, - redirect, or translation services. - - - - -Fajardo, et al. Standards Track [Page 13] - -RFC 6733 Diameter Base Protocol October 2012 - - - Diameter Client - - A Diameter client is a Diameter node that supports Diameter client - applications as well as the base protocol. Diameter clients are - often implemented in devices situated at the edge of a network and - provide access control services for that network. Typical - examples of Diameter clients include the Network Access Server - (NAS) and the Mobile IP Foreign Agent (FA). - - Diameter Node - - A Diameter node is a host process that implements the Diameter - protocol and acts as either a client, an agent, or a server. - - Diameter Peer - - Two Diameter nodes sharing a direct TCP or SCTP transport - connection are called Diameter peers. - - Diameter Server - - A Diameter server is a Diameter node that handles authentication, - authorization, and accounting requests for a particular realm. By - its very nature, a Diameter server must support Diameter server - applications in addition to the base protocol. -</pre> - -<p> -A Diameter Node is implemented by configuring a service -using &mod_start_service; and one or more transports using -&mod_add_transport;. -The service typically represents a Diameter Node but since -capabilities can be configured on individual transports it's more -accurate to say that the node is a collection of transports -advertising the same Origin-Host.</p> - -<p> -The role of a node (agent, client or server) is not something that's -configured explicitly. -Transports are either connecting or listening, depending on whether -diameter should establish a peer connection and send CER or accept -connections and receive CER, but the role a node implements depends -largely on dictionary configuration and &man_app; callback -implementation.</p> - -<pre> - - Downstream - - Downstream is used to identify the direction of a particular - Diameter message from the home server towards the Diameter client. - - Home Realm - - A Home Realm is the administrative domain with which the user - maintains an account relationship. - - Home Server - - A Diameter server that serves the Home Realm. - - Interim Accounting - - An interim accounting message provides a snapshot of usage during - a user's session. Typically, it is implemented in order to - provide for partial accounting of a user's session in case a - device reboot or other network problem prevents the delivery of a - session summary message or session record. - - - - -Fajardo, et al. Standards Track [Page 14] - -RFC 6733 Diameter Base Protocol October 2012 - - - Local Realm - - A local realm is the administrative domain providing services to a - user. An administrative domain may act as a local realm for - certain users while being a home realm for others. - - Multi-session - - A multi-session represents a logical linking of several sessions. - Multi-sessions are tracked by using the Acct-Multi-Session-Id. An - example of a multi-session would be a Multi-link PPP bundle. Each - leg of the bundle would be a session while the entire bundle would - be a multi-session. - - Network Access Identifier - - The Network Access Identifier, or NAI [RFC4282], is used in the - Diameter protocol to extract a user's identity and realm. The - identity is used to identify the user during authentication and/or - authorization while the realm is used for message routing - purposes. - - Proxy Agent or Proxy - - In addition to forwarding requests and responses, proxies make - policy decisions relating to resource usage and provisioning. - Typically, this is accomplished by tracking the state of NAS - devices. While proxies usually do not respond to client requests - prior to receiving a response from the server, they may originate - Reject messages in cases where policies are violated. As a - result, proxies need to understand the semantics of the messages - passing through them, and they may not support all Diameter - applications. - - Realm - - The string in the NAI that immediately follows the '@' character. - NAI realm names are required to be unique and are piggybacked on - the administration of the DNS namespace. Diameter makes use of - the realm, also loosely referred to as domain, to determine - whether messages can be satisfied locally or whether they must be - routed or redirected. In RADIUS, realm names are not necessarily - piggybacked on the DNS namespace but may be independent of it. - - - - - - - - -Fajardo, et al. Standards Track [Page 15] - -RFC 6733 Diameter Base Protocol October 2012 - - - Real-Time Accounting - - Real-time accounting involves the processing of information on - resource usage within a defined time window. Typically, time - constraints are imposed in order to limit financial risk. The - Diameter Credit-Control Application [RFC4006] is an example of an - application that defines real-time accounting functionality. - - Relay Agent or Relay - - Relays forward requests and responses based on routing-related - AVPs and routing table entries. Since relays do not make policy - decisions, they do not examine or alter non-routing AVPs. As a - result, relays never originate messages, do not need to understand - the semantics of messages or non-routing AVPs, and are capable of - handling any Diameter application or message type. Since relays - make decisions based on information in routing AVPs and realm - forwarding tables, they do not keep state on NAS resource usage or - sessions in progress. - - Redirect Agent - - Rather than forwarding requests and responses between clients and - servers, redirect agents refer clients to servers and allow them - to communicate directly. Since redirect agents do not sit in the - forwarding path, they do not alter any AVPs transiting between - client and server. Redirect agents do not originate messages and - are capable of handling any message type, although they may be - configured only to redirect messages of certain types, while - acting as relay or proxy agents for other types. As with relay - agents, redirect agents do not keep state with respect to sessions - or NAS resources. -</pre> - -&nada; - -<pre> - - Session - - A session is a related progression of events devoted to a - particular activity. Diameter application documents provide - guidelines as to when a session begins and ends. All Diameter - packets with the same Session-Id are considered to be part of the - same session. -</pre> - -<p> -Sessions are not something that diameter is aware of. -The function &mod_session_id; can be used to construct appropriate -values for Session-Id AVP's but logic connecting events in the same -session is the responsibility of the diameter user.</p> - -<pre> - - Stateful Agent - - A stateful agent is one that maintains session state information, - by keeping track of all authorized active sessions. Each - authorized session is bound to a particular service, and its state - is considered active either until it is notified otherwise or - until expiration. - - - -Fajardo, et al. Standards Track [Page 16] - -RFC 6733 Diameter Base Protocol October 2012 - - - Sub-session - - A sub-session represents a distinct service (e.g., QoS or data - characteristics) provided to a given session. These services may - happen concurrently (e.g., simultaneous voice and data transfer - during the same session) or serially. These changes in sessions - are tracked with the Accounting-Sub-Session-Id. - - Transaction State - - The Diameter protocol requires that agents maintain transaction - state, which is used for failover purposes. Transaction state - implies that upon forwarding a request, the Hop-by-Hop Identifier - is saved; the field is replaced with a locally unique identifier, - which is restored to its original value when the corresponding - answer is received. The request's state is released upon receipt - of the answer. A stateless agent is one that only maintains - transaction state. - - Translation Agent - - A translation agent (TLA in Figure 4) is a stateful Diameter node - that performs protocol translation between Diameter and another - AAA protocol, such as RADIUS. - - Upstream - - Upstream is used to identify the direction of a particular - Diameter message from the Diameter client towards the home server. - - User - - The entity or device requesting or using some resource, in support - of which a Diameter client has generated a request. -</pre> - -&nada; - -<pre> - -1.3. Approach to Extensibility - - The Diameter protocol is designed to be extensible, using several - mechanisms, including: - - o Defining new AVP values - - o Creating new AVPs - - o Creating new commands - - o Creating new applications - - - - -Fajardo, et al. Standards Track [Page 17] - -RFC 6733 Diameter Base Protocol October 2012 - - - From the point of view of extensibility, Diameter authentication, - authorization, and accounting applications are treated in the same - way. -</pre> - -<p> -Extensibility in diameter is by way of the dictionary interface -documented in &man_dict;: a diameter user creates applications, -commands and AVP's by implementing a new dictionary, -compiling the dictionary to a codec module using &man_compile; or -&man_make;, and configuring the resulting dictionary module on a -service. -The dictionary modules provided with diameter are all implemented in -this manner.</p> - -<pre> - Note: Protocol designers should try to reuse existing functionality, - namely AVP values, AVPs, commands, and Diameter applications. Reuse - simplifies standardization and implementation. To avoid potential - interoperability issues, it is important to ensure that the semantics - of the reused features are well understood. Given that Diameter can - also carry RADIUS attributes as Diameter AVPs, such reuse - considerations also apply to existing RADIUS attributes that may be - useful in a Diameter application. -</pre> - -<p> -Reuse in dictionary files is achieved by way of the <c>@inherits</c> -section. -AVP's are inherited, commands are not.</p> - -<pre> - -1.3.1. Defining New AVP Values - - In order to allocate a new AVP value for AVPs defined in the Diameter - base protocol, the IETF needs to approve a new RFC that describes the - AVP value. IANA considerations for these AVP values are discussed in - Section 11.3. - - The allocation of AVP values for other AVPs is guided by the IANA - considerations of the document that defines those AVPs. Typically, - allocation of new values for an AVP defined in an RFC would require - IETF Review [RFC5226], whereas values for vendor-specific AVPs can be - allocated by the vendor. - -1.3.2. Creating New AVPs - - A new AVP being defined MUST use one of the data types listed in - Sections 4.2 or 4.3. If an appropriate derived data type is already - defined, it SHOULD be used instead of a base data type to encourage - reusability and good design practice. - - In the event that a logical grouping of AVPs is necessary, and - multiple "groups" are possible in a given command, it is recommended - that a Grouped AVP be used (see Section 4.4). - - The creation of new AVPs can happen in various ways. The recommended - approach is to define a new general-purpose AVP in a Standards Track - RFC approved by the IETF. However, as described in Section 11.1.1, - there are other mechanisms. -</pre> - -<p> -Creating new AVP's is an issue for the dictionary designer, not -diameter.</p> - -<pre> - -1.3.3. Creating New Commands - - A new Command Code MUST be allocated when required AVPs (those - indicated as {AVP} in the CCF definition) are added to, deleted from, - or redefined in (for example, by changing a required AVP into an - optional one) an existing command. - - - -Fajardo, et al. Standards Track [Page 18] - -RFC 6733 Diameter Base Protocol October 2012 - - - Furthermore, if the transport characteristics of a command are - changed (for example, with respect to the number of round trips - required), a new Command Code MUST be registered. - - A change to the CCF of a command, such as described above, MUST - result in the definition of a new Command Code. This subsequently - leads to the need to define a new Diameter application for any - application that will use that new command. - - The IANA considerations for Command Codes are discussed in - Section 3.1. -</pre> - -<p> -Creating new commands is an issue for the dictionary designer, not -diameter.</p> - -<pre> - -1.3.4. Creating New Diameter Applications - - Every Diameter application specification MUST have an IANA-assigned - Application Id (see Section 2.4). The managed Application ID space - is flat, and there is no relationship between different Diameter - applications with respect to their Application Ids. As such, there - is no versioning support provided by these Application Ids - themselves; every Diameter application is a standalone application. - If the application has a relationship with other Diameter - applications, such a relationship is not known to Diameter. -</pre> - -<p> -Creating new applications is an issue for the dictionary designer, -not diameter.</p> - -<p> -An application's Application Id is specified in the <c>@id</c> section -of a dictionary file.</p> - -<pre> - - Before describing the rules for creating new Diameter applications, - it is important to discuss the semantics of the AVP occurrences as - stated in the CCF and the M-bit flag (Section 4.1) for an AVP. There - is no relationship imposed between the two; they are set - independently. - - o The CCF indicates what AVPs are placed into a Diameter command by - the sender of that command. Often, since there are multiple modes - of protocol interactions, many of the AVPs are indicated as - optional. - - o The M-bit allows the sender to indicate to the receiver whether or - not understanding the semantics of an AVP and its content is - mandatory. If the M-bit is set by the sender and the receiver - does not understand the AVP or the values carried within that AVP, - then a failure is generated (see Section 7). -</pre> - -<p> -The M-bit is set on outgoing AVP's as directed by the relevant -dictionary. -For incoming AVP's, an M-bit set on an AVP that isn't -explicitly included in the definition of the command in question is -interpreted as a 5001 error, DIAMETER_AVP_UNSUPPORTED, the -consequences of which depend on the value of the &mod_application_opt; -<c>answer_errors</c> or <c>request_errors</c>.</p> - -<pre> - - It is the decision of the protocol designer when to develop a new - Diameter application rather than extending Diameter in other ways. - However, a new Diameter application MUST be created when one or more - of the following criteria are met: - - - - - - - -Fajardo, et al. Standards Track [Page 19] - -RFC 6733 Diameter Base Protocol October 2012 - - - M-bit Setting - - An AVP with the M-bit in the MUST column of the AVP flag table is - added to an existing Command/Application. An AVP with the M-bit - in the MAY column of the AVP flag table is added to an existing - Command/Application. - - Note: The M-bit setting for a given AVP is relevant to an - Application and each command within that application that includes - the AVP. That is, if an AVP appears in two commands for - application Foo and the M-bit settings are different in each - command, then there should be two AVP flag tables describing when - to set the M-bit. - - Commands - - A new command is used within the existing application because - either an additional command is added, an existing command has - been modified so that a new Command Code had to be registered, or - a command has been deleted. - - AVP Flag bits - - If an existing application changes the meaning/semantics of its - AVP Flags or adds new flag bits, then a new Diameter application - MUST be created. - - If the CCF definition of a command allows it, an implementation may - add arbitrary optional AVPs with the M-bit cleared (including vendor- - specific AVPs) to that command without needing to define a new - application. Please refer to Section 11.1.1 for details. -</pre> - -&nada; - -<pre> - -2. Protocol Overview - - The base Diameter protocol concerns itself with establishing - connections to peers, capabilities negotiation, how messages are sent - and routed through peers, and how the connections are eventually torn - down. The base protocol also defines certain rules that apply to all - message exchanges between Diameter nodes. - - Communication between Diameter peers begins with one peer sending a - message to another Diameter peer. The set of AVPs included in the - message is determined by a particular Diameter application. One AVP - that is included to reference a user's session is the Session-Id. - - The initial request for authentication and/or authorization of a user - would include the Session-Id AVP. The Session-Id is then used in all - subsequent messages to identify the user's session (see Section 8 for - - - -Fajardo, et al. Standards Track [Page 20] - -RFC 6733 Diameter Base Protocol October 2012 - - - more information). The communicating party may accept the request or - reject it by returning an answer message with the Result-Code AVP set - to indicate that an error occurred. The specific behavior of the - Diameter server or client receiving a request depends on the Diameter - application employed. - - Session state (associated with a Session-Id) MUST be freed upon - receipt of the Session-Termination-Request, Session-Termination- - Answer, expiration of authorized service time in the Session-Timeout - AVP, and according to rules established in a particular Diameter - application. -</pre> - -<p> -Like Session-Id, session state is maintained by the diameter user: -diameter has no session state of its own and does not interpret -STR/STA in any way.</p> - -<pre> - - The base Diameter protocol may be used by itself for accounting - applications. For authentication and authorization, it is always - extended for a particular application. - - Diameter clients MUST support the base protocol, which includes - accounting. In addition, they MUST fully support each Diameter - application that is needed to implement the client's service, e.g., - Network Access Server Requirements (NASREQ) [RFC2881] and/or Mobile - IPv4. A Diameter client MUST be referred to as "Diameter X Client" - where X is the application that it supports and not a "Diameter - Client". - - Diameter servers MUST support the base protocol, which includes - accounting. In addition, they MUST fully support each Diameter - application that is needed to implement the intended service, e.g., - NASREQ and/or Mobile IPv4. A Diameter server MUST be referred to as - "Diameter X Server" where X is the application that it supports, and - not a "Diameter Server". - - Diameter relays and redirect agents are transparent to the Diameter - applications, but they MUST support the Diameter base protocol, which - includes accounting, and all Diameter applications. - - Diameter proxies MUST support the base protocol, which includes - accounting. In addition, they MUST fully support each Diameter - application that is needed to implement proxied services, e.g., - NASREQ and/or Mobile IPv4. A Diameter proxy MUST be referred to as - "Diameter X Proxy" where X is the application which it supports, and - not a "Diameter Proxy". - -</pre> - -&nada; - -<pre> - - - - - - - - - -Fajardo, et al. Standards Track [Page 21] - -RFC 6733 Diameter Base Protocol October 2012 - - -2.1. Transport - - The Diameter Transport profile is defined in [RFC3539]. - - The base Diameter protocol is run on port 3868 for both TCP [RFC0793] - and SCTP [RFC4960]. For TLS [RFC5246] and Datagram Transport Layer - Security (DTLS) [RFC6347], a Diameter node that initiates a - connection prior to any message exchanges MUST run on port 5658. It - is assumed that TLS is run on top of TCP when it is used, and DTLS is - run on top of SCTP when it is used. -</pre> - -<p> -Which port a transport connects to or listens on is a matter of -configuration. -Both &man_tcp; and &man_sctp; will default to 3868 if no other value -is specified.</p> - -<pre> - - If the Diameter peer does not support receiving TLS/TCP and DTLS/SCTP - connections on port 5658 (i.e., the peer complies only with RFC - 3588), then the initiator MAY revert to using TCP or SCTP on port - 3868. Note that this scheme is kept only for the purpose of backward - compatibility and that there are inherent security vulnerabilities - when the initial CER/CEA messages are sent unprotected (see - Section 5.6). - - Diameter clients MUST support either TCP or SCTP; agents and servers - SHOULD support both. - - A Diameter node MAY initiate connections from a source port other - than the one that it declares it accepts incoming connections on, and - it MUST always be prepared to receive connections on port 3868 for - TCP or SCTP and port 5658 for TLS/TCP and DTLS/SCTP connections. - When DNS-based peer discovery (Section 5.2) is used, the port numbers - received from SRV records take precedence over the default ports - (3868 and 5658). - - A given Diameter instance of the peer state machine MUST NOT use more - than one transport connection to communicate with a given peer, - unless multiple instances exist on the peer, in which, case a - separate connection per process is allowed. -</pre> - -<p> -The &mod_service_opt; <c>restrict_connection</c> controls to what -extent a diameter service allows multiple connections to the same -peer. -(As identified by the value of Origin-Host received from it -during capabilities exchange.)</p> - -<pre> - - When no transport connection exists with a peer, an attempt to - connect SHOULD be made periodically. This behavior is handled via - the Tc timer (see Section 12 for details), whose recommended value is - 30 seconds. There are certain exceptions to this rule, such as when - a peer has terminated the transport connection stating that it does - not wish to communicate. - -</pre> - -<p> -The frequency of reconnection attempts is configured with the -&mod_transport_opt; <c>connect_timer</c> and -<c>watchdog_timer</c>.</p> - -<pre> - - When connecting to a peer and either zero or more transports are - specified, TLS SHOULD be tried first, followed by DTLS, then by TCP, - and finally by SCTP. See Section 5.2 for more information on peer - discovery. -</pre> - -<p> -The order in which different transports are attempted depends on the -order of &mod_transport_opt; <c>transport_module</c> and -<c>transport_config</c> tuples in transport configuration.</p> - -<pre> - - - -Fajardo, et al. Standards Track [Page 22] - -RFC 6733 Diameter Base Protocol October 2012 - - - Diameter implementations SHOULD be able to interpret ICMP protocol - port unreachable messages as explicit indications that the server is - not reachable, subject to security policy on trusting such messages. - Further guidance regarding the treatment of ICMP errors can be found - in [RFC5927] and [RFC5461]. Diameter implementations SHOULD also be - able to interpret a reset from the transport and timed-out connection - attempts. If Diameter receives data from the lower layer that cannot - be parsed or identified as a Diameter error made by the peer, the - stream is compromised and cannot be recovered. The transport - connection MUST be closed using a RESET call (send a TCP RST bit) or - an SCTP ABORT message (graceful closure is compromised). -</pre> - -<p> -ICMP messages and other transport-level errors aren't directly -visible to diameter but transport implementations like &man_tcp; and -&man_sctp; propagate these as terminating transport processes.</p> - -<pre> - -2.1.1. SCTP Guidelines - - Diameter messages SHOULD be mapped into SCTP streams in a way that - avoids head-of-the-line (HOL) blocking. Among different ways of - performing the mapping that fulfill this requirement it is - RECOMMENDED that a Diameter node send every Diameter message (request - or response) over stream zero with the unordered flag set. However, - Diameter nodes MAY select and implement other design alternatives for - avoiding HOL blocking such as using multiple streams with the - unordered flag cleared (as originally instructed in RFC 3588). On - the receiving side, a Diameter entity MUST be ready to receive - Diameter messages over any stream, and it is free to return responses - over a different stream. This way, both sides manage the available - streams in the sending direction, independently of the streams chosen - by the other side to send a particular Diameter message. These - messages can be out-of-order and belong to different Diameter - sessions. -</pre> - -<p> -&man_sctp; allows the sender to specify a stream number explicitly. -The stream on which an incoming message is received it passed to -&app_handle_request; and &app_handle_answer; callbacks as -<c>transport_data</c> in a <c>#diameter_packet{}</c>.</p> - -<p> -Ordered or unordered delivery can be configured per transport.</p> - -<pre> - - Out-of-order delivery has special concerns during a connection - establishment and termination. When a connection is established, the - responder side sends a CEA message and moves to R-Open state as - specified in Section 5.6. If an application message is sent shortly - after the CEA and delivered out-of-order, the initiator side, still - in Wait-I-CEA state, will discard the application message and close - the connection. In order to avoid this race condition, the receiver - side SHOULD NOT use out-of-order delivery methods until the first - message has been received from the initiator, proving that it has - moved to I-Open state. To trigger such a message, the receiver side - could send a DWR immediately after sending a CEA. Upon reception of - the corresponding DWA, the receiver side should start using out-of- - order delivery methods to counter the HOL blocking. -</pre> - -<p> -&man_sctp; does not currently allow the user to switch between ordered -and unordered delivery, or to specify the manner of sending per -message: one or the other must be configured, the defaults being -ordered.</p> - -<pre> - - Another race condition may occur when DPR and DPA messages are used. - Both DPR and DPA are small in size; thus, they may be delivered to - the peer faster than application messages when an out-of-order - delivery mechanism is used. Therefore, it is possible that a DPR/DPA - - - -Fajardo, et al. Standards Track [Page 23] - -RFC 6733 Diameter Base Protocol October 2012 - - - exchange completes while application messages are still in transit, - resulting in a loss of these messages. An implementation could - mitigate this race condition, for example, using timers, and wait for - a short period of time for pending application level messages to - arrive before proceeding to disconnect the transport connection. - Eventually, lost messages are handled by the retransmission mechanism - described in Section 5.5.4. - - A Diameter agent SHOULD use dedicated payload protocol identifiers - (PPIDs) for clear text and encrypted SCTP DATA chunks instead of only - using the unspecified payload protocol identifier (value 0). For - this purpose, two PPID values are allocated: the PPID value 46 is for - Diameter messages in clear text SCTP DATA chunks, and the PPID value - 47 is for Diameter messages in protected DTLS/SCTP DATA chunks. -</pre> - -&nada; - -<pre> - -2.2. Securing Diameter Messages - - Connections between Diameter peers SHOULD be protected by TLS/TCP and - DTLS/SCTP. All Diameter base protocol implementations MUST support - the use of TLS/TCP and DTLS/SCTP. If desired, alternative security - mechanisms that are independent of Diameter, such as IPsec [RFC4301], - can be deployed to secure connections between peers. The Diameter - protocol MUST NOT be used without one of TLS, DTLS, or IPsec. -</pre> - -<p> -As noted above, DTLS is not currently supported and IPsec usage is -transparent to diameter. -Security is not enforced by diameter.</p> - -<pre> - -2.3. Diameter Application Compliance - - Application Ids are advertised during the capabilities exchange phase - (see Section 5.3). Advertising support of an application implies - that the sender supports the functionality specified in the - respective Diameter application specification. - - Implementations MAY add arbitrary optional AVPs with the M-bit - cleared (including vendor-specific AVPs) to a command defined in an - application, but only if the command's CCF syntax specification - allows for it. Please refer to Section 11.1.1 for details. -</pre> - -&nada; - -<pre> - -2.4. Application Identifiers - - Each Diameter application MUST have an IANA-assigned Application ID. - The base protocol does not require an Application Id since its - support is mandatory. During the capabilities exchange, Diameter - nodes inform their peers of locally supported applications. - Furthermore, all Diameter messages contain an Application Id, which - is used in the message forwarding process. - - - - - - - -Fajardo, et al. Standards Track [Page 24] - -RFC 6733 Diameter Base Protocol October 2012 - - - The following Application Id values are defined: - - Diameter common message 0 - Diameter base accounting 3 - Relay 0xffffffff -</pre> - -<p> -These applications are implemented in the dictionary modules -<c>diameter_gen_base_rfc6733</c>, <c>diameter_gen_acct_rfc6733</c> and -<c>diameter_relay</c> respectively. -There are also RFC 3588 versions or the common and accounting -dictionaries: <c>diameter_gen_base_rfc3588</c> and -<c>diameter_base_accounting</c>. -(The inconsistent naming is historical.) -Dictionary modules are configured using the &mod_application_opt; -<c>dictionary</c>.</p> - -<pre> - Relay and redirect agents MUST advertise the Relay Application ID, - while all other Diameter nodes MUST advertise locally supported - applications. The receiver of a Capabilities Exchange message - advertising relay service MUST assume that the sender supports all - current and future applications. - - Diameter relay and proxy agents are responsible for finding an - upstream server that supports the application of a particular - message. If none can be found, an error message is returned with the - Result-Code AVP set to DIAMETER_UNABLE_TO_DELIVER. -</pre> - -&nada; - -<pre> - -2.5. Connections vs. Sessions - - This section attempts to provide the reader with an understanding of - the difference between "connection" and "session", which are terms - used extensively throughout this document. - - A connection refers to a transport-level connection between two peers - that is used to send and receive Diameter messages. A session is a - logical concept at the application layer that exists between the - Diameter client and the Diameter server; it is identified via the - Session-Id AVP. - - +--------+ +-------+ +--------+ - | Client | | Relay | | Server | - +--------+ +-------+ +--------+ - <----------> <----------> - peer connection A peer connection B - - <-----------------------------> - User session x - - Figure 1: Diameter Connections and Sessions - - In the example provided in Figure 1, peer connection A is established - between the client and the relay. Peer connection B is established - between the relay and the server. User session X spans from the - client via the relay to the server. Each "user" of a service causes - an auth request to be sent, with a unique session identifier. Once - accepted by the server, both the client and the server are aware of - the session. - - - - -Fajardo, et al. Standards Track [Page 25] - -RFC 6733 Diameter Base Protocol October 2012 - - - It is important to note that there is no relationship between a - connection and a session, and that Diameter messages for multiple - sessions are all multiplexed through a single connection. Also, note - that Diameter messages pertaining to the session, both application- - specific and those that are defined in this document such as ASR/ASA, - RAR/RAA, and STR/STA, MUST carry the Application Id of the - application. Diameter messages pertaining to peer connection - establishment and maintenance such as CER/CEA, DWR/DWA, and DPR/DPA - MUST carry an Application Id of zero (0). -</pre> - -<p> -As noted above, diameter is not involved in session management. -This is the responsibility of the diameter user.</p> - -<pre> - -2.6. Peer Table - - The Diameter peer table is used in message forwarding and is - referenced by the routing table. A peer table entry contains the - following fields: - - Host Identity - - Following the conventions described for the DiameterIdentity- - derived AVP data format in Section 4.3.1, this field contains the - contents of the Origin-Host (Section 6.3) AVP found in the CER or - CEA message. - - StatusT - - This is the state of the peer entry, and it MUST match one of the - values listed in Section 5.6. - - Static or Dynamic - - Specifies whether a peer entry was statically configured or - dynamically discovered. - - Expiration Time - - Specifies the time at which dynamically discovered peer table - entries are to be either refreshed or expired. If public key - certificates are used for Diameter security (e.g., with TLS), this - value MUST NOT be greater than the expiry times in the relevant - certificates. - - TLS/TCP and DTLS/SCTP Enabled - - Specifies whether TLS/TCP and DTLS/SCTP is to be used when - communicating with the peer. - - Additional security information, when needed (e.g., keys, - certificates). -</pre> - -<p> -The Peer Table is not directly accessible to the diameter user. -Information about connected peers can be retrieved using -&mod_service_info;.</p> - -<pre> - - - -Fajardo, et al. Standards Track [Page 26] - -RFC 6733 Diameter Base Protocol October 2012 - - -2.7. Routing Table - - All Realm-Based routing lookups are performed against what is - commonly known as the routing table (see Section 12). Each routing - table entry contains the following fields: - - Realm Name - - This is the field that MUST be used as a primary key in the - routing table lookups. Note that some implementations perform - their lookups based on longest-match-from-the-right on the realm - rather than requiring an exact match. - - Application Identifier - - An application is identified by an Application Id. A route entry - can have a different destination based on the Application Id in - the message header. This field MUST be used as a secondary key - field in routing table lookups. - - Local Action - - The Local Action field is used to identify how a message should be - treated. The following actions are supported: - - 1. LOCAL - Diameter messages that can be satisfied locally and do - not need to be routed to another Diameter entity. - - 2. RELAY - All Diameter messages that fall within this category - MUST be routed to a next-hop Diameter entity that is indicated - by the identifier described below. Routing is done without - modifying any non-routing AVPs. See Section 6.1.9 for - relaying guidelines. - - 3. PROXY - All Diameter messages that fall within this category - MUST be routed to a next Diameter entity that is indicated by - the identifier described below. The local server MAY apply - its local policies to the message by including new AVPs to the - message prior to routing. See Section 6.1.9 for proxying - guidelines. - - 4. REDIRECT - Diameter messages that fall within this category - MUST have the identity of the home Diameter server(s) - appended, and returned to the sender of the message. See - Section 6.1.8 for redirection guidelines. - - - - - - -Fajardo, et al. Standards Track [Page 27] - -RFC 6733 Diameter Base Protocol October 2012 - - - Server Identifier - - The identity of one or more servers to which the message is to be - routed. This identity MUST also be present in the Host Identity - field of the peer table (Section 2.6). When the Local Action is - set to RELAY or PROXY, this field contains the identity of the - server(s) to which the message MUST be routed. When the Local - Action field is set to REDIRECT, this field contains the identity - of one or more servers to which the message MUST be redirected. - - Static or Dynamic - - Specifies whether a route entry was statically configured or - dynamically discovered. - - Expiration Time - - Specifies the time at which a dynamically discovered route table - entry expires. If public key certificates are used for Diameter - security (e.g., with TLS), this value MUST NOT be greater than the - expiry time in the relevant certificates. - - It is important to note that Diameter agents MUST support at least - one of the LOCAL, RELAY, PROXY, or REDIRECT modes of operation. - Agents do not need to support all modes of operation in order to - conform with the protocol specification, but they MUST follow the - protocol compliance guidelines in Section 2. Relay agents and - proxies MUST NOT reorder AVPs. - - The routing table MAY include a default entry that MUST be used for - any requests not matching any of the other entries. The routing - table MAY consist of only such an entry. - - When a request is routed, the target server MUST have advertised the - Application Id (see Section 2.4) for the given message or have - advertised itself as a relay or proxy agent. Otherwise, an error is - returned with the Result-Code AVP set to DIAMETER_UNABLE_TO_DELIVER. -</pre> - -<p> -Routing does not need specific support in diameter: a user can -maintain their own routing table if desired and implement any desired -routing in &man_app; callbacks. -However, it may be convenient to add more specific routing support to -diameter in the future.</p> - -<pre> - -2.8. Role of Diameter Agents - - In addition to clients and servers, the Diameter protocol introduces - relay, proxy, redirect, and translation agents, each of which is - defined in Section 1.2. Diameter agents are useful for several - reasons: -</pre> - -<p> -An noted above, the role a node plays is largely a question of -configuration and &man_app; callback implementation.</p> - -<pre> - - o They can distribute administration of systems to a configurable - grouping, including the maintenance of security associations. - - - - -Fajardo, et al. Standards Track [Page 28] - -RFC 6733 Diameter Base Protocol October 2012 - - - o They can be used for concentration of requests from a number of - co-located or distributed NAS equipment sets to a set of like user - groups. - - o They can do value-added processing to the requests or responses. - - o They can be used for load balancing. - - o A complex network will have multiple authentication sources, they - can sort requests and forward towards the correct target. - - The Diameter protocol requires that agents maintain transaction - state, which is used for failover purposes. Transaction state - implies that upon forwarding a request, its Hop-by-Hop Identifier is - saved; the field is replaced with a locally unique identifier, which - is restored to its original value when the corresponding answer is - received. The request's state is released upon receipt of the - answer. A stateless agent is one that only maintains transaction - state. - - The Proxy-Info AVP allows stateless agents to add local state to a - Diameter request, with the guarantee that the same state will be - present in the answer. However, the protocol's failover procedures - require that agents maintain a copy of pending requests. - - A stateful agent is one that maintains session state information by - keeping track of all authorized active sessions. Each authorized - session is bound to a particular service, and its state is considered - active until either the agent is notified otherwise or the session - expires. Each authorized session has an expiration, which is - communicated by Diameter servers via the Session-Timeout AVP. - - Maintaining session state may be useful in certain applications, such - as: - - o Protocol translation (e.g., RADIUS <-> Diameter) - - o Limiting resources authorized to a particular user - - o Per-user or per-transaction auditing - - A Diameter agent MAY act in a stateful manner for some requests and - be stateless for others. A Diameter implementation MAY act as one - type of agent for some requests and as another type of agent for - others. -</pre> - -&nada; - -<pre> - - - - - - -Fajardo, et al. Standards Track [Page 29] - -RFC 6733 Diameter Base Protocol October 2012 - - -2.8.1. Relay Agents - - Relay agents are Diameter agents that accept requests and route - messages to other Diameter nodes based on information found in the - messages (e.g., the value of the Destination-Realm AVP Section 6.6). - This routing decision is performed using a list of supported realms - and known peers. This is known as the routing table, as is defined - further in Section 2.7. - - Relays may, for example, be used to aggregate requests from multiple - Network Access Servers (NASes) within a common geographical area - (Point of Presence, POP). The use of relays is advantageous since it - eliminates the need for NASes to be configured with the necessary - security information they would otherwise require to communicate with - Diameter servers in other realms. Likewise, this reduces the - configuration load on Diameter servers that would otherwise be - necessary when NASes are added, changed, or deleted. - - Relays modify Diameter messages by inserting and removing routing - information, but they do not modify any other portion of a message. - Relays SHOULD NOT maintain session state but MUST maintain - transaction state. - - +------+ ---------> +------+ ---------> +------+ - | | 1. Request | | 2. Request | | - | NAS | | DRL | | HMS | - | | 4. Answer | | 3. Answer | | - +------+ <--------- +------+ <--------- +------+ - example.net example.net example.com - - Figure 2: Relaying of Diameter messages - - The example provided in Figure 2 depicts a request issued from a NAS, - which is an access device, for the user [email protected]. Prior to - issuing the request, the NAS performs a Diameter route lookup, using - "example.com" as the key, and determines that the message is to be - relayed to a DRL, which is a Diameter relay. The DRL performs the - same route lookup as the NAS, and relays the message to the HMS, - which is example.com's home server. The HMS identifies that the - request can be locally supported (via the realm), processes the - authentication and/or authorization request, and replies with an - answer, which is routed back to the NAS using saved transaction - state. - - Since relays do not perform any application-level processing, they - provide relaying services for all Diameter applications; therefore, - they MUST advertise the Relay Application Id. -</pre> - -<p> -Requests are relayed by returning a <c>relay</c> tuple from a -&app_handle_request; callback.</p> - -<pre> - - - -Fajardo, et al. Standards Track [Page 30] - -RFC 6733 Diameter Base Protocol October 2012 - - -2.8.2. Proxy Agents - - Similar to relays, proxy agents route Diameter messages using the - Diameter routing table. However, they differ since they modify - messages to implement policy enforcement. This requires that proxies - maintain the state of their downstream peers (e.g., access devices) - to enforce resource usage, provide admission control, and provide - provisioning. - - Proxies may, for example, be used in call control centers or access - ISPs that provide outsourced connections; they can monitor the number - and type of ports in use and make allocation and admission decisions - according to their configuration. - - Since enforcing policies requires an understanding of the service - being provided, proxies MUST only advertise the Diameter applications - they support. -</pre> - -&nada; - -<pre> - -2.8.3. Redirect Agents - - Redirect agents are useful in scenarios where the Diameter routing - configuration needs to be centralized. An example is a redirect - agent that provides services to all members of a consortium, but does - not wish to be burdened with relaying all messages between realms. - This scenario is advantageous since it does not require that the - consortium provide routing updates to its members when changes are - made to a member's infrastructure. - - Since redirect agents do not relay messages, and only return an - answer with the information necessary for Diameter agents to - communicate directly, they do not modify messages. Since redirect - agents do not receive answer messages, they cannot maintain session - state. - - The example provided in Figure 3 depicts a request issued from the - access device, NAS, for the user [email protected]. The message is - forwarded by the NAS to its relay, DRL, which does not have a routing - entry in its Diameter routing table for example.com. The DRL has a - default route configured to DRD, which is a redirect agent that - returns a redirect notification to DRL, as well as the HMS' contact - information. Upon receipt of the redirect notification, the DRL - establishes a transport connection with the HMS, if one doesn't - already exist, and forwards the request to it. - - - - - - - - -Fajardo, et al. Standards Track [Page 31] - -RFC 6733 Diameter Base Protocol October 2012 - - - +------+ - | | - | DRD | - | | - +------+ - ^ | - 2. Request | | 3. Redirection - | | Notification - | v - +------+ ---------> +------+ ---------> +------+ - | | 1. Request | | 4. Request | | - | NAS | | DRL | | HMS | - | | 6. Answer | | 5. Answer | | - +------+ <--------- +------+ <--------- +------+ - example.net example.net example.com - - Figure 3: Redirecting a Diameter Message - - Since redirect agents do not perform any application-level - processing, they provide relaying services for all Diameter - applications; therefore, they MUST advertise the Relay Application - ID. -</pre> - -&nada; - -<pre> - -2.8.4. Translation Agents - - A translation agent is a device that provides translation between two - protocols (e.g., RADIUS<->Diameter, TACACS+<->Diameter). Translation - agents are likely to be used as aggregation servers to communicate - with a Diameter infrastructure, while allowing for the embedded - systems to be migrated at a slower pace. - - Given that the Diameter protocol introduces the concept of long-lived - authorized sessions, translation agents MUST be session stateful and - MUST maintain transaction state. - - Translation of messages can only occur if the agent recognizes the - application of a particular request; therefore, translation agents - MUST only advertise their locally supported applications. - - +------+ ---------> +------+ ---------> +------+ - | | RADIUS Request | | Diameter Request | | - | NAS | | TLA | | HMS | - | | RADIUS Answer | | Diameter Answer | | - +------+ <--------- +------+ <--------- +------+ - example.net example.net example.com - - Figure 4: Translation of RADIUS to Diameter -</pre> - -&nada; - -<pre> - - - - -Fajardo, et al. Standards Track [Page 32] - -RFC 6733 Diameter Base Protocol October 2012 - - -2.9. Diameter Path Authorization - - As noted in Section 2.2, Diameter provides transmission-level - security for each connection using TLS/TCP and DTLS/SCTP. Therefore, - each connection can be authenticated and can be replay and integrity - protected. - - In addition to authenticating each connection, the entire session - MUST also be authorized. Before initiating a connection, a Diameter - peer MUST check that its peers are authorized to act in their roles. - For example, a Diameter peer may be authentic, but that does not mean - that it is authorized to act as a Diameter server advertising a set - of Diameter applications. - - Prior to bringing up a connection, authorization checks are performed - at each connection along the path. Diameter capabilities negotiation - (CER/CEA) also MUST be carried out, in order to determine what - Diameter applications are supported by each peer. Diameter sessions - MUST be routed only through authorized nodes that have advertised - support for the Diameter application required by the session. - - As noted in Section 6.1.9, a relay or proxy agent MUST append a - Route-Record AVP to all requests forwarded. The AVP contains the - identity of the peer from which the request was received. - - The home Diameter server, prior to authorizing a session, MUST check - the Route-Record AVPs to make sure that the route traversed by the - request is acceptable. For example, administrators within the home - realm may not wish to honor requests that have been routed through an - untrusted realm. By authorizing a request, the home Diameter server - is implicitly indicating its willingness to engage in the business - transaction as specified by any contractual relationship between the - server and the previous hop. A DIAMETER_AUTHORIZATION_REJECTED error - message (see Section 7.1.5) is sent if the route traversed by the - request is unacceptable. - - A home realm may also wish to check that each accounting request - message corresponds to a Diameter response authorizing the session. - Accounting requests without corresponding authorization responses - SHOULD be subjected to further scrutiny, as should accounting - requests indicating a difference between the requested and provided - service. - - Forwarding of an authorization response is considered evidence of a - willingness to take on financial risk relative to the session. A - local realm may wish to limit this exposure, for example, by - establishing credit limits for intermediate realms and refusing to - accept responses that would violate those limits. By issuing an - - - -Fajardo, et al. Standards Track [Page 33] - -RFC 6733 Diameter Base Protocol October 2012 - - - accounting request corresponding to the authorization response, the - local realm implicitly indicates its agreement to provide the service - indicated in the authorization response. If the service cannot be - provided by the local realm, then a DIAMETER_UNABLE_TO_COMPLY error - message MUST be sent within the accounting request; a Diameter client - receiving an authorization response for a service that it cannot - perform MUST NOT substitute an alternate service and then send - accounting requests for the alternate service instead. -</pre> - -&nada; - -<pre> - -3. Diameter Header - - A summary of the Diameter header format is shown below. The fields - are transmitted in network byte order. - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Version | Message Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Command Flags | Command Code | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Application-ID | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Hop-by-Hop Identifier | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | End-to-End Identifier | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | AVPs ... - +-+-+-+-+-+-+-+-+-+-+-+-+- -</pre> - -<p> -The Diameter Header is represented by the <c>diameter_header</c> -record defined in <c>diameter.hrl</c>. -The <c>diameter_packet</c> record contains a <c>header</c> field whose -value will be a decoded <c>#diameter_header{}</c> for incoming -messages passed to &app_handle_request; and &app_handle_answer; -callbacks. -In the case of outgoing messages, diameter and the relevant -dictionary populate the Diameter Header appropriately, although -&app_prepare_request; and &app_handle_request; callbacks can modify -header values. -(Which can be useful in test.)</p> - -<pre> - - Version - - This Version field MUST be set to 1 to indicate Diameter Version - 1. - - Message Length - - The Message Length field is three octets and indicates the length - of the Diameter message including the header fields and the padded - AVPs. Thus, the Message Length field is always a multiple of 4. - - Command Flags - - The Command Flags field is eight bits. The following bits are - assigned: - - - - - - -Fajardo, et al. Standards Track [Page 34] - -RFC 6733 Diameter Base Protocol October 2012 - - - 0 1 2 3 4 5 6 7 - +-+-+-+-+-+-+-+-+ - |R P E T r r r r| - +-+-+-+-+-+-+-+-+ - - R(equest) - - If set, the message is a request. If cleared, the message is - an answer. - - P(roxiable) - - If set, the message MAY be proxied, relayed, or redirected. If - cleared, the message MUST be locally processed. - - E(rror) - - If set, the message contains a protocol error, and the message - will not conform to the CCF described for this command. - Messages with the 'E' bit set are commonly referred to as error - messages. This bit MUST NOT be set in request messages (see - Section 7.2). - - T(Potentially retransmitted message) - - This flag is set after a link failover procedure, to aid the - removal of duplicate requests. It is set when resending - requests not yet acknowledged, as an indication of a possible - duplicate due to a link failure. This bit MUST be cleared when - sending a request for the first time; otherwise, the sender - MUST set this flag. Diameter agents only need to be concerned - about the number of requests they send based on a single - received request; retransmissions by other entities need not be - tracked. Diameter agents that receive a request with the T - flag set, MUST keep the T flag set in the forwarded request. - This flag MUST NOT be set if an error answer message (e.g., a - protocol error) has been received for the earlier message. It - can be set only in cases where no answer has been received from - the server for a request, and the request has been sent again. - This flag MUST NOT be set in answer messages. - - r(eserved) - - These flag bits are reserved for future use; they MUST be set - to zero and ignored by the receiver. -</pre> - -<p> -Reserved bits are set to 0 in outgoing messages.</p> - -<pre> - - - - - - -Fajardo, et al. Standards Track [Page 35] - -RFC 6733 Diameter Base Protocol October 2012 - - - Command Code - - The Command Code field is three octets and is used in order to - communicate the command associated with the message. The 24-bit - address space is managed by IANA (see Section 3.1). Command Code - values 16,777,214 and 16,777,215 (hexadecimal values FFFFFE- - FFFFFF) are reserved for experimental use (see Section 11.2). - - Application-ID - - Application-ID is four octets and is used to identify for which - application the message is applicable. The application can be an - authentication application, an accounting application, or a - vendor-specific application. - - The value of the Application-ID field in the header MUST be the - same as any relevant Application-Id AVPs contained in the message. - - Hop-by-Hop Identifier - - The Hop-by-Hop Identifier is an unsigned 32-bit integer field (in - network byte order) that aids in matching requests and replies. - The sender MUST ensure that the Hop-by-Hop Identifier in a request - is unique on a given connection at any given time, and it MAY - attempt to ensure that the number is unique across reboots. The - sender of an answer message MUST ensure that the Hop-by-Hop - Identifier field contains the same value that was found in the - corresponding request. The Hop-by-Hop Identifier is normally a - monotonically increasing number, whose start value was randomly - generated. An answer message that is received with an unknown - Hop-by-Hop Identifier MUST be discarded. - - End-to-End Identifier - - The End-to-End Identifier is an unsigned 32-bit integer field (in - network byte order) that is used to detect duplicate messages. - Upon reboot, implementations MAY set the high order 12 bits to - contain the low order 12 bits of current time, and the low order - 20 bits to a random value. Senders of request messages MUST - insert a unique identifier on each message. The identifier MUST - remain locally unique for a period of at least 4 minutes, even - across reboots. The originator of an answer message MUST ensure - that the End-to-End Identifier field contains the same value that - was found in the corresponding request. The End-to-End Identifier - MUST NOT be modified by Diameter agents of any kind. The - combination of the Origin-Host AVP (Section 6.3) and this field is - used to detect duplicates. Duplicate requests SHOULD cause the - same answer to be transmitted (modulo the Hop-by-Hop Identifier - - - -Fajardo, et al. Standards Track [Page 36] - -RFC 6733 Diameter Base Protocol October 2012 - - - field and any routing AVPs that may be present), and they MUST NOT - affect any state that was set when the original request was - processed. Duplicate answer messages that are to be locally - consumed (see Section 6.2) SHOULD be silently discarded. - - AVPs - - AVPs are a method of encapsulating information relevant to the - Diameter message. See Section 4 for more information on AVPs. -</pre> - -&nada; - -<pre> - -3.1. Command Codes - - Each command Request/Answer pair is assigned a Command Code, and the - sub-type (i.e., request or answer) is identified via the 'R' bit in - the Command Flags field of the Diameter header. - - Every Diameter message MUST contain a Command Code in its header's - Command Code field, which is used to determine the action that is to - be taken for a particular message. The following Command Codes are - defined in the Diameter base protocol: - - Section - Command Name Abbrev. Code Reference - -------------------------------------------------------- - Abort-Session-Request ASR 274 8.5.1 - Abort-Session-Answer ASA 274 8.5.2 - Accounting-Request ACR 271 9.7.1 - Accounting-Answer ACA 271 9.7.2 - Capabilities-Exchange- CER 257 5.3.1 - Request - Capabilities-Exchange- CEA 257 5.3.2 - Answer - Device-Watchdog-Request DWR 280 5.5.1 - Device-Watchdog-Answer DWA 280 5.5.2 - Disconnect-Peer-Request DPR 282 5.4.1 - Disconnect-Peer-Answer DPA 282 5.4.2 - Re-Auth-Request RAR 258 8.3.1 - Re-Auth-Answer RAA 258 8.3.2 - Session-Termination- STR 275 8.4.1 - Request - Session-Termination- STA 275 8.4.2 - Answer -</pre> - -<p> -These messages are all defined in diameter's implementation of the -common dictionary in modules <c>diameter_gen_base_rfc6733</c> and -<c>diameter_gen_base_rfc3588</c>. -Corresponding record definitions are found in -<c>diameter_gen_base_rfc6733.hrl</c> and -<c>diameter_gen_base_rfc3588.hrl</c>.</p> - -<pre> - - - - - - - - - -Fajardo, et al. Standards Track [Page 37] - -RFC 6733 Diameter Base Protocol October 2012 - - -3.2. Command Code Format Specification - - Every Command Code defined MUST include a corresponding Command Code - Format (CCF) specification, which is used to define the AVPs that - MUST or MAY be present when sending the message. The following ABNF - specifies the CCF used in the definition: -</pre> - -<p> -The CCF is what is specified in the <c>@messages</c> section of the -&man_dict; format, except as noted below.</p> - -<pre> - - command-def = "<" command-name ">" "::=" diameter-message -</pre> - -<p> -Angle brackets are currently not allowed here. -This was a change between RFC 3588 and RFC 6733: the former disallowed -them in the grammar but included them in its own command definitions.</p> - -<pre> - - command-name = diameter-name - - diameter-name = ALPHA *(ALPHA / DIGIT / "-") - - diameter-message = header *fixed *required *optional - - header = "<Diameter-Header:" command-id - [r-bit] [p-bit] [e-bit] [application-id]">" - - application-id = 1*DIGIT - - command-id = 1*DIGIT - ; The Command Code assigned to the command. - - r-bit = ", REQ" - ; If present, the 'R' bit in the Command - ; Flags is set, indicating that the message - ; is a request as opposed to an answer. - - p-bit = ", PXY" - ; If present, the 'P' bit in the Command - ; Flags is set, indicating that the message - ; is proxiable. - - e-bit = ", ERR" - ; If present, the 'E' bit in the Command - ; Flags is set, indicating that the answer - ; message contains a Result-Code AVP in - ; the "protocol error" class. - - fixed = [qual] "<" avp-spec ">" - ; Defines the fixed position of an AVP. - - required = [qual] "{" avp-spec "}" - ; The AVP MUST be present and can appear - ; anywhere in the message. - - - - - - -Fajardo, et al. Standards Track [Page 38] - -RFC 6733 Diameter Base Protocol October 2012 - - - optional = [qual] "[" avp-name "]" - ; The avp-name in the 'optional' rule cannot - ; evaluate to any AVP Name that is included - ; in a fixed or required rule. The AVP can - ; appear anywhere in the message. - ; - ; NOTE: "[" and "]" have a slightly different - ; meaning than in ABNF. These braces - ; cannot be used to express optional fixed rules - ; (such as an optional ICV at the end). To do - ; this, the convention is '0*1fixed'. - - qual = [min] "*" [max] - ; See ABNF conventions, RFC 5234, Section 4. - ; The absence of any qualifier depends on - ; whether it precedes a fixed, required, or - ; optional rule. If a fixed or required rule has - ; no qualifier, then exactly one such AVP MUST - ; be present. If an optional rule has no - ; qualifier, then 0 or 1 such AVP may be - ; present. If an optional rule has a qualifier, - ; then the value of min MUST be 0 if present. - - min = 1*DIGIT - ; The minimum number of times the element may - ; be present. If absent, the default value is 0 - ; for fixed and optional rules and 1 for - ; required rules. The value MUST be at least 1 - ; for required rules. - - max = 1*DIGIT - ; The maximum number of times the element may - ; be present. If absent, the default value is - ; infinity. A value of 0 implies the AVP MUST - ; NOT be present. - - avp-spec = diameter-name - ; The avp-spec has to be an AVP Name, defined - ; in the base or extended Diameter - ; specifications. - - avp-name = avp-spec / "AVP" - ; The string "AVP" stands for *any* arbitrary AVP - ; Name, not otherwise listed in that Command Code - ; definition. The inclusion of this string - ; is recommended for all CCFs to allow for - ; extensibility. - - - - -Fajardo, et al. Standards Track [Page 39] - -RFC 6733 Diameter Base Protocol October 2012 - - - The following is a definition of a fictitious Command Code: - - Example-Request ::= < Diameter Header: 9999999, REQ, PXY > - { User-Name } - 1* { Origin-Host } - * [ AVP ] -</pre> - -&nada; - -<pre> - -3.3. Diameter Command Naming Conventions - - Diameter command names typically includes one or more English words - followed by the verb "Request" or "Answer". Each English word is - delimited by a hyphen. A three-letter acronym for both the request - and answer is also normally provided. - - An example is a message set used to terminate a session. The command - name is Session-Terminate-Request and Session-Terminate-Answer, while - the acronyms are STR and STA, respectively. - - Both the request and the answer for a given command share the same - Command Code. The request is identified by the R(equest) bit in the - Diameter header set to one (1), to ask that a particular action be - performed, such as authorizing a user or terminating a session. Once - the receiver has completed the request, it issues the corresponding - answer, which includes a result code that communicates one of the - following: - - o The request was successful - - o The request failed - - o An additional request has to be sent to provide information the - peer requires prior to returning a successful or failed answer. - - o The receiver could not process the request, but provides - information about a Diameter peer that is able to satisfy the - request, known as redirect. - - Additional information, encoded within AVPs, may also be included in - answer messages. -</pre> - -<p> -The &man_dict; format places no requirement on the naming of commands.</p> - -<pre> - -4. Diameter AVPs - - Diameter AVPs carry specific authentication, accounting, - authorization, and routing information as well as configuration - details for the request and reply. - - - - - - -Fajardo, et al. Standards Track [Page 40] - -RFC 6733 Diameter Base Protocol October 2012 - - - Each AVP of type OctetString MUST be padded to align on a 32-bit - boundary, while other AVP types align naturally. A number of zero- - valued bytes are added to the end of the AVP Data field until a word - boundary is reached. The length of the padding is not reflected in - the AVP Length field. - -4.1. AVP Header - - The fields in the AVP header MUST be sent in network byte order. The - format of the header is: - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | AVP Code | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |V M P r r r r r| AVP Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Vendor-ID (opt) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Data ... - +-+-+-+-+-+-+-+-+ - - AVP Code - - The AVP Code, combined with the Vendor-Id field, identifies the - attribute uniquely. AVP numbers 1 through 255 are reserved for - reuse of RADIUS attributes, without setting the Vendor-Id field. - AVP numbers 256 and above are used for Diameter, which are - allocated by IANA (see Section 11.1.1). - - AVP Flags - - The AVP Flags field informs the receiver how each attribute must - be handled. New Diameter applications SHOULD NOT define - additional AVP Flag bits. However, note that new Diameter - applications MAY define additional bits within the AVP header, and - an unrecognized bit SHOULD be considered an error. The sender of - the AVP MUST set 'R' (reserved) bits to 0 and the receiver SHOULD - ignore all 'R' (reserved) bits. The 'P' bit has been reserved for - future usage of end-to-end security. At the time of writing, - there are no end-to-end security mechanisms specified; therefore, - the 'P' bit SHOULD be set to 0. - - The 'M' bit, known as the Mandatory bit, indicates whether the - receiver of the AVP MUST parse and understand the semantics of the - AVP including its content. The receiving entity MUST return an - appropriate error message if it receives an AVP that has the M-bit - - - -Fajardo, et al. Standards Track [Page 41] - -RFC 6733 Diameter Base Protocol October 2012 - - - set but does not understand it. An exception applies when the AVP - is embedded within a Grouped AVP. See Section 4.4 for details. - Diameter relay and redirect agents MUST NOT reject messages with - unrecognized AVPs. - - The 'M' bit MUST be set according to the rules defined in the - application specification that introduces or reuses this AVP. - Within a given application, the M-bit setting for an AVP is - defined either for all command types or for each command type. - - AVPs with the 'M' bit cleared are informational only; a receiver - that receives a message with such an AVP that is not supported, or - whose value is not supported, MAY simply ignore the AVP. - - The 'V' bit, known as the Vendor-Specific bit, indicates whether - the optional Vendor-ID field is present in the AVP header. When - set, the AVP Code belongs to the specific vendor code address - space. - - AVP Length - - The AVP Length field is three octets, and indicates the number of - octets in this AVP including the AVP Code field, AVP Length field, - AVP Flags field, Vendor-ID field (if present), and the AVP Data - field. If a message is received with an invalid attribute length, - the message MUST be rejected. - -4.1.1. Optional Header Elements - - The AVP header contains one optional field. This field is only - present if the respective bit-flag is enabled. - - Vendor-ID - - The Vendor-ID field is present if the 'V' bit is set in the AVP - Flags field. The optional four-octet Vendor-ID field contains the - IANA-assigned "SMI Network Management Private Enterprise Codes" - [ENTERPRISE] value, encoded in network byte order. Any vendors or - standardization organizations that are also treated like vendors - in the IANA-managed "SMI Network Management Private Enterprise - Codes" space wishing to implement a vendor-specific Diameter AVP - MUST use their own Vendor-ID along with their privately managed - AVP address space, guaranteeing that they will not collide with - any other vendor's vendor-specific AVP(s) or with future IETF - AVPs. - - - - - - -Fajardo, et al. Standards Track [Page 42] - -RFC 6733 Diameter Base Protocol October 2012 - - - A Vendor-ID value of zero (0) corresponds to the IETF-adopted AVP - values, as managed by IANA. Since the absence of the Vendor-ID - field implies that the AVP in question is not vendor specific, - implementations MUST NOT use the value of zero (0) for the - Vendor-ID field. - -4.2. Basic AVP Data Formats - - The Data field is zero or more octets and contains information - specific to the Attribute. The format and length of the Data field - is determined by the AVP Code and AVP Length fields. The format of - the Data field MUST be one of the following base data types or a data - type derived from the base data types. In the event that a new Basic - AVP Data Format is needed, a new version of this RFC MUST be created. - - OctetString - - The data contains arbitrary data of variable length. Unless - otherwise noted, the AVP Length field MUST be set to at least 8 - (12 if the 'V' bit is enabled). AVP values of this type that are - not a multiple of 4 octets in length are followed by the necessary - padding so that the next AVP (if any) will start on a 32-bit - boundary. - - Integer32 - - 32-bit signed value, in network byte order. The AVP Length field - MUST be set to 12 (16 if the 'V' bit is enabled). - - Integer64 - - 64-bit signed value, in network byte order. The AVP Length field - MUST be set to 16 (20 if the 'V' bit is enabled). - - Unsigned32 - - 32-bit unsigned value, in network byte order. The AVP Length - field MUST be set to 12 (16 if the 'V' bit is enabled). - - Unsigned64 - - 64-bit unsigned value, in network byte order. The AVP Length - field MUST be set to 16 (20 if the 'V' bit is enabled). - - - - - - - - -Fajardo, et al. Standards Track [Page 43] - -RFC 6733 Diameter Base Protocol October 2012 - - - Float32 - - This represents floating point values of single precision as - described by [FLOATPOINT]. The 32-bit value is transmitted in - network byte order. The AVP Length field MUST be set to 12 (16 if - the 'V' bit is enabled). - - Float64 - - This represents floating point values of double precision as - described by [FLOATPOINT]. The 64-bit value is transmitted in - network byte order. The AVP Length field MUST be set to 16 (20 if - the 'V' bit is enabled). - - Grouped - - The Data field is specified as a sequence of AVPs. These AVPs are - concatenated -- including their headers and padding -- in the - order in which they are specified and the result encapsulated in - the Data field. The AVP Length field is set to 8 (12 if the 'V' - bit is enabled) plus the total length of all included AVPs, - including their headers and padding. Thus, the AVP Length field - of an AVP of type Grouped is always a multiple of 4. - -4.3. Derived AVP Data Formats - - In addition to using the Basic AVP Data Formats, applications may - define data formats derived from the Basic AVP Data Formats. An - application that defines new Derived AVP Data Formats MUST include - them in a section titled "Derived AVP Data Formats", using the same - format as the definitions below. Each new definition MUST be either - defined or listed with a reference to the RFC that defines the - format. - -4.3.1. Common Derived AVP Data Formats - - The following are commonly used Derived AVP Data Formats. - - Address - - The Address format is derived from the OctetString Basic AVP - Format. It is a discriminated union representing, for example, a - 32-bit (IPv4) [RFC0791] or 128-bit (IPv6) [RFC4291] address, most - significant octet first. The first two octets of the Address AVP - represent the AddressType, which contains an Address Family, - defined in [IANAADFAM]. The AddressType is used to discriminate - the content and format of the remaining octets. - - - - -Fajardo, et al. Standards Track [Page 44] - -RFC 6733 Diameter Base Protocol October 2012 - - - Time - - The Time format is derived from the OctetString Basic AVP Format. - The string MUST contain four octets, in the same format as the - first four bytes are in the NTP timestamp format. The NTP - timestamp format is defined in Section 3 of [RFC5905]. - - This represents the number of seconds since 0h on 1 January 1900 - with respect to the Coordinated Universal Time (UTC). - - On 6h 28m 16s UTC, 7 February 2036, the time value will overflow. - Simple Network Time Protocol (SNTP) [RFC5905] describes a - procedure to extend the time to 2104. This procedure MUST be - supported by all Diameter nodes. - - UTF8String - - The UTF8String format is derived from the OctetString Basic AVP - Format. This is a human-readable string represented using the - ISO/IEC IS 10646-1 character set, encoded as an OctetString using - the UTF-8 transformation format [RFC3629]. - - Since additional code points are added by amendments to the 10646 - standard from time to time, implementations MUST be prepared to - encounter any code point from 0x00000001 to 0x7fffffff. Byte - sequences that do not correspond to the valid encoding of a code - point into UTF-8 charset or are outside this range are prohibited. - - The use of control codes SHOULD be avoided. When it is necessary - to represent a new line, the control code sequence CR LF SHOULD be - used. - - The use of leading or trailing white space SHOULD be avoided. - - For code points not directly supported by user interface hardware - or software, an alternative means of entry and display, such as - hexadecimal, MAY be provided. - - For information encoded in 7-bit US-ASCII, the UTF-8 charset is - identical to the US-ASCII charset. - - UTF-8 may require multiple bytes to represent a single character / - code point; thus, the length of a UTF8String in octets may be - different from the number of characters encoded. - - Note that the AVP Length field of an UTF8String is measured in - octets not characters. - - - - -Fajardo, et al. Standards Track [Page 45] - -RFC 6733 Diameter Base Protocol October 2012 - - - DiameterIdentity - - The DiameterIdentity format is derived from the OctetString Basic - AVP Format. - - DiameterIdentity = FQDN/Realm - - The DiameterIdentity value is used to uniquely identify either: - - * A Diameter node for purposes of duplicate connection and - routing loop detection. - - * A Realm to determine whether messages can be satisfied locally - or whether they must be routed or redirected. - - When a DiameterIdentity value is used to identify a Diameter node, - the contents of the string MUST be the Fully Qualified Domain Name - (FQDN) of the Diameter node. If multiple Diameter nodes run on - the same host, each Diameter node MUST be assigned a unique - DiameterIdentity. If a Diameter node can be identified by several - FQDNs, a single FQDN should be picked at startup and used as the - only DiameterIdentity for that node, whatever the connection on - which it is sent. In this document, note that DiameterIdentity is - in ASCII form in order to be compatible with existing DNS - infrastructure. See Appendix D for interactions between the - Diameter protocol and Internationalized Domain Names (IDNs). - - DiameterURI - - The DiameterURI MUST follow the Uniform Resource Identifiers (RFC - 3986) syntax [RFC3986] rules specified below: - - "aaa://" FQDN [ port ] [ transport ] [ protocol ] - - ; No transport security - - "aaas://" FQDN [ port ] [ transport ] [ protocol ] - - ; Transport security used - - FQDN = < Fully Qualified Domain Name > - - - - - - - - - - -Fajardo, et al. Standards Track [Page 46] - -RFC 6733 Diameter Base Protocol October 2012 - - - port = ":" 1*DIGIT - - ; One of the ports used to listen for - ; incoming connections. - ; If absent, the default Diameter port - ; (3868) is assumed if no transport - ; security is used and port 5658 when - ; transport security (TLS/TCP and DTLS/SCTP) - ; is used. - - transport = ";transport=" transport-protocol - - ; One of the transports used to listen - ; for incoming connections. If absent, - ; the default protocol is assumed to be TCP. - ; UDP MUST NOT be used when the aaa-protocol - ; field is set to diameter. - - transport-protocol = ( "tcp" / "sctp" / "udp" ) - - protocol = ";protocol=" aaa-protocol - - ; If absent, the default AAA protocol - ; is Diameter. - - aaa-protocol = ( "diameter" / "radius" / "tacacs+" ) - - The following are examples of valid Diameter host identities: - - aaa://host.example.com;transport=tcp - aaa://host.example.com:6666;transport=tcp - aaa://host.example.com;protocol=diameter - aaa://host.example.com:6666;protocol=diameter - aaa://host.example.com:6666;transport=tcp;protocol=diameter - aaa://host.example.com:1813;transport=udp;protocol=radius - - Enumerated - - The Enumerated format is derived from the Integer32 Basic AVP - Format. The definition contains a list of valid values and their - interpretation and is described in the Diameter application - introducing the AVP. - - - - - - - - - -Fajardo, et al. Standards Track [Page 47] - -RFC 6733 Diameter Base Protocol October 2012 - - - IPFilterRule - - The IPFilterRule format is derived from the OctetString Basic AVP - Format and uses the ASCII charset. The rule syntax is a modified - subset of ipfw(8) from FreeBSD. Packets may be filtered based on - the following information that is associated with it: - - Direction (in or out) - Source and destination IP address (possibly masked) - Protocol - Source and destination port (lists or ranges) - TCP flags - IP fragment flag - IP options - ICMP types - - Rules for the appropriate direction are evaluated in order, with the - first matched rule terminating the evaluation. Each packet is - evaluated once. If no rule matches, the packet is dropped if the - last rule evaluated was a permit, and passed if the last rule was a - deny. - - IPFilterRule filters MUST follow the format: - - action dir proto from src to dst [options] - - action permit - Allow packets that match the rule. - deny - Drop packets that match the rule. - - dir "in" is from the terminal, "out" is to the - terminal. - - proto An IP protocol specified by number. The "ip" - keyword means any protocol will match. - - src and dst <address/mask> [ports] - - The <address/mask> may be specified as: - ipno An IPv4 or IPv6 number in dotted- - quad or canonical IPv6 form. Only - this exact IP number will match the - rule. - - - - - - - - - -Fajardo, et al. Standards Track [Page 48] - -RFC 6733 Diameter Base Protocol October 2012 - - - ipno/bits An IP number as above with a mask - width of the form 192.0.2.10/24. In - this case, all IP numbers from - 192.0.2.0 to 192.0.2.255 will match. - The bit width MUST be valid for the - IP version, and the IP number MUST - NOT have bits set beyond the mask. - For a match to occur, the same IP - version must be present in the - packet that was used in describing - the IP address. To test for a - particular IP version, the bits part - can be set to zero. The keyword - "any" is 0.0.0.0/0 or the IPv6 - equivalent. The keyword "assigned" - is the address or set of addresses - assigned to the terminal. For IPv4, - a typical first rule is often "deny - in ip! assigned". - - The sense of the match can be inverted by - preceding an address with the not modifier (!), - causing all other addresses to be matched - instead. This does not affect the selection of - port numbers. - - With the TCP, UDP, and SCTP protocols, optional - ports may be specified as: - - {port/port-port}[,ports[,...]] - - The '-' notation specifies a range of ports - (including boundaries). - - Fragmented packets that have a non-zero offset - (i.e., not the first fragment) will never match - a rule that has one or more port - specifications. See the frag option for - details on matching fragmented packets. - - options: - frag Match if the packet is a fragment and this is not - the first fragment of the datagram. frag may not - be used in conjunction with either tcpflags or - TCP/UDP port specifications. - - - - - - -Fajardo, et al. Standards Track [Page 49] - -RFC 6733 Diameter Base Protocol October 2012 - - - ipoptions spec - Match if the IP header contains the comma-separated - list of options specified in spec. The - supported IP options are: - - ssrr (strict source route), lsrr (loose source - route), rr (record packet route), and ts - (timestamp). The absence of a particular option - may be denoted with a '!'. - - tcpoptions spec - Match if the TCP header contains the comma-separated - list of options specified in spec. The - supported TCP options are: - - mss (maximum segment size), window (tcp window - advertisement), sack (selective ack), ts (rfc1323 - timestamp), and cc (rfc1644 t/tcp connection - count). The absence of a particular option may - be denoted with a '!'. - - established - TCP packets only. Match packets that have the RST - or ACK bits set. - - setup TCP packets only. Match packets that have the SYN - bit set but no ACK bit. - - - tcpflags spec - TCP packets only. Match if the TCP header - contains the comma-separated list of flags - specified in spec. The supported TCP flags are: - - fin, syn, rst, psh, ack, and urg. The absence of a - particular flag may be denoted with a '!'. A rule - that contains a tcpflags specification can never - match a fragmented packet that has a non-zero - offset. See the frag option for details on - matching fragmented packets. - - icmptypes types - ICMP packets only. Match if the ICMP type is in - the list types. The list may be specified as any - combination of ranges or individual types - separated by commas. Both the numeric values and - the symbolic values listed below can be used. The - supported ICMP types are: - - - -Fajardo, et al. Standards Track [Page 50] - -RFC 6733 Diameter Base Protocol October 2012 - - - echo reply (0), destination unreachable (3), - source quench (4), redirect (5), echo request - (8), router advertisement (9), router - solicitation (10), time-to-live exceeded (11), IP - header bad (12), timestamp request (13), - timestamp reply (14), information request (15), - information reply (16), address mask request (17), - and address mask reply (18). - - There is one kind of packet that the access device MUST always - discard, that is an IP fragment with a fragment offset of one. This - is a valid packet, but it only has one use, to try to circumvent - firewalls. - - An access device that is unable to interpret or apply a deny rule - MUST terminate the session. An access device that is unable to - interpret or apply a permit rule MAY apply a more restrictive rule. - An access device MAY apply deny rules of its own before the supplied - rules, for example to protect the access device owner's - infrastructure. - -4.4. Grouped AVP Values - - The Diameter protocol allows AVP values of type 'Grouped'. This - implies that the Data field is actually a sequence of AVPs. It is - possible to include an AVP with a Grouped type within a Grouped type, - that is, to nest them. AVPs within an AVP of type Grouped have the - same padding requirements as non-Grouped AVPs, as defined in - Section 4.4. - - The AVP Code numbering space of all AVPs included in a Grouped AVP is - the same as for non-Grouped AVPs. Receivers of a Grouped AVP that - does not have the 'M' (mandatory) bit set and one or more of the - encapsulated AVPs within the group has the 'M' (mandatory) bit set - MAY simply be ignored if the Grouped AVP itself is unrecognized. The - rule applies even if the encapsulated AVP with its 'M' (mandatory) - bit set is further encapsulated within other sub-groups, i.e., other - Grouped AVPs embedded within the Grouped AVP. - - Every Grouped AVP definition MUST include a corresponding grammar, - using ABNF [RFC5234] (with modifications), as defined below. - - grouped-avp-def = "<" name ">" "::=" avp - - name-fmt = ALPHA *(ALPHA / DIGIT / "-") - - - - - - -Fajardo, et al. Standards Track [Page 51] - -RFC 6733 Diameter Base Protocol October 2012 - - - name = name-fmt - ; The name has to be the name of an AVP, - ; defined in the base or extended Diameter - ; specifications. - - avp = header *fixed *required *optional - - header = "<" "AVP-Header:" avpcode [vendor] ">" - - avpcode = 1*DIGIT - ; The AVP Code assigned to the Grouped AVP. - - vendor = 1*DIGIT - ; The Vendor-ID assigned to the Grouped AVP. - ; If absent, the default value of zero is - ; used. - -4.4.1. Example AVP with a Grouped Data Type - - The Example-AVP (AVP Code 999999) is of type Grouped and is used to - clarify how Grouped AVP values work. The Grouped Data field has the - following CCF grammar: - - Example-AVP ::= < AVP Header: 999999 > - { Origin-Host } - 1*{ Session-Id } - *[ AVP ] - - An Example-AVP with Grouped Data follows. - - The Origin-Host AVP (Section 6.3) is required. In this case: - - Origin-Host = "example.com". - - One or more Session-Ids must follow. Here there are two: - - Session-Id = - "grump.example.com:33041;23432;893;0AF3B81" - - Session-Id = - "grump.example.com:33054;23561;2358;0AF3B82" - - - - - - - - - - -Fajardo, et al. Standards Track [Page 52] - -RFC 6733 Diameter Base Protocol October 2012 - - - optional AVPs included are - - Recovery-Policy = <binary> - 2163bc1d0ad82371f6bc09484133c3f09ad74a0dd5346d54195a7cf0b35 - 2cabc881839a4fdcfbc1769e2677a4c1fb499284c5f70b48f58503a45c5 - c2d6943f82d5930f2b7c1da640f476f0e9c9572a50db8ea6e51e1c2c7bd - f8bb43dc995144b8dbe297ac739493946803e1cee3e15d9b765008a1b2a - cf4ac777c80041d72c01e691cf751dbf86e85f509f3988e5875dc905119 - 26841f00f0e29a6d1ddc1a842289d440268681e052b30fb638045f7779c - 1d873c784f054f688f5001559ecff64865ef975f3e60d2fd7966b8c7f92 - - Futuristic-Acct-Record = <binary> - fe19da5802acd98b07a5b86cb4d5d03f0314ab9ef1ad0b67111ff3b90a0 - 57fe29620bf3585fd2dd9fcc38ce62f6cc208c6163c008f4258d1bc88b8 - 17694a74ccad3ec69269461b14b2e7a4c111fb239e33714da207983f58c - 41d018d56fe938f3cbf089aac12a912a2f0d1923a9390e5f789cb2e5067 - d3427475e49968f841 - - The data for the optional AVPs is represented in hexadecimal form - since the format of these AVPs is not known at the time of definition - of the Example-AVP group nor (likely) at the time when the example - instance of this AVP is interpreted -- except by Diameter - implementations that support the same set of AVPs. The encoding - example illustrates how padding is used and how length fields are - calculated. Also, note that AVPs may be present in the Grouped AVP - value that the receiver cannot interpret (here, the Recover-Policy - and Futuristic-Acct-Record AVPs). The length of the Example-AVP is - the sum of all the length of the member AVPs, including their - padding, plus the Example-AVP header size. - - - - - - - - - - - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 53] - -RFC 6733 Diameter Base Protocol October 2012 - - - This AVP would be encoded as follows: - - 0 1 2 3 4 5 6 7 - +-------+-------+-------+-------+-------+-------+-------+-------+ - 0 | Example AVP Header (AVP Code = 999999), Length = 496 | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 8 | Origin-Host AVP Header (AVP Code = 264), Length = 19 | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 16 | 'e' | 'x' | 'a' | 'm' | 'p' | 'l' | 'e' | '.' | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 24 | 'c' | 'o' | 'm' |Padding| Session-Id AVP Header | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 32 | (AVP Code = 263), Length = 49 | 'g' | 'r' | 'u' | 'm' | - +-------+-------+-------+-------+-------+-------+-------+-------+ - . . . - +-------+-------+-------+-------+-------+-------+-------+-------+ - 72 | 'F' | '3' | 'B' | '8' | '1' |Padding|Padding|Padding| - +-------+-------+-------+-------+-------+-------+-------+-------+ - 80 | Session-Id AVP Header (AVP Code = 263), Length = 50 | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 88 | 'g' | 'r' | 'u' | 'm' | 'p' | '.' | 'e' | 'x' | - +-------+-------+-------+-------+-------+-------+-------+-------+ - . . . - +-------+-------+-------+-------+-------+-------+-------+-------+ - 120| '5' | '8' | ';' | '0' | 'A' | 'F' | '3' | 'B' | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 128| '8' | '2' |Padding|Padding| Recovery-Policy Header (AVP | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 136| Code = 8341), Length = 223 | 0x21 | 0x63 | 0xbc | 0x1d | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 144| 0x0a | 0xd8 | 0x23 | 0x71 | 0xf6 | 0xbc | 0x09 | 0x48 | - +-------+-------+-------+-------+-------+-------+-------+-------+ - . . . - +-------+-------+-------+-------+-------+-------+-------+-------+ - 352| 0x8c | 0x7f | 0x92 |Padding| Futuristic-Acct-Record Header | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 328|(AVP Code = 15930),Length = 137| 0xfe | 0x19 | 0xda | 0x58 | - +-------+-------+-------+-------+-------+-------+-------+-------+ - 336| 0x02 | 0xac | 0xd9 | 0x8b | 0x07 | 0xa5 | 0xb8 | 0xc6 | - +-------+-------+-------+-------+-------+-------+-------+-------+ - . . . - +-------+-------+-------+-------+-------+-------+-------+-------+ - 488| 0xe4 | 0x99 | 0x68 | 0xf8 | 0x41 |Padding|Padding|Padding| - +-------+-------+-------+-------+-------+-------+-------+-------+ - - - - - - - -Fajardo, et al. Standards Track [Page 54] - -RFC 6733 Diameter Base Protocol October 2012 - - -4.5. Diameter Base Protocol AVPs - - The following table describes the Diameter AVPs defined in the base - protocol, their AVP Code values, types, and possible flag values. - - Due to space constraints, the short form DiamIdent is used to - represent DiameterIdentity. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 55] - -RFC 6733 Diameter Base Protocol October 2012 - - - +----------+ - | AVP Flag | - | rules | - |----+-----| - AVP Section | |MUST | - Attribute Name Code Defined Data Type |MUST| NOT | - -----------------------------------------|----+-----| - Acct- 85 9.8.2 Unsigned32 | M | V | - Interim-Interval | | | - Accounting- 483 9.8.7 Enumerated | M | V | - Realtime-Required | | | - Acct- 50 9.8.5 UTF8String | M | V | - Multi-Session-Id | | | - Accounting- 485 9.8.3 Unsigned32 | M | V | - Record-Number | | | - Accounting- 480 9.8.1 Enumerated | M | V | - Record-Type | | | - Acct- 44 9.8.4 OctetString| M | V | - Session-Id | | | - Accounting- 287 9.8.6 Unsigned64 | M | V | - Sub-Session-Id | | | - Acct- 259 6.9 Unsigned32 | M | V | - Application-Id | | | - Auth- 258 6.8 Unsigned32 | M | V | - Application-Id | | | - Auth-Request- 274 8.7 Enumerated | M | V | - Type | | | - Authorization- 291 8.9 Unsigned32 | M | V | - Lifetime | | | - Auth-Grace- 276 8.10 Unsigned32 | M | V | - Period | | | - Auth-Session- 277 8.11 Enumerated | M | V | - State | | | - Re-Auth-Request- 285 8.12 Enumerated | M | V | - Type | | | - Class 25 8.20 OctetString| M | V | - Destination-Host 293 6.5 DiamIdent | M | V | - Destination- 283 6.6 DiamIdent | M | V | - Realm | | | - Disconnect-Cause 273 5.4.3 Enumerated | M | V | - Error-Message 281 7.3 UTF8String | | V,M | - Error-Reporting- 294 7.4 DiamIdent | | V,M | - Host | | | - Event-Timestamp 55 8.21 Time | M | V | - Experimental- 297 7.6 Grouped | M | V | - Result | | | - -----------------------------------------|----+-----| - - - - -Fajardo, et al. Standards Track [Page 56] - -RFC 6733 Diameter Base Protocol October 2012 - - - +----------+ - | AVP Flag | - | rules | - |----+-----| - AVP Section | |MUST | - Attribute Name Code Defined Data Type |MUST| NOT | - -----------------------------------------|----+-----| - Experimental- 298 7.7 Unsigned32 | M | V | - Result-Code | | | - Failed-AVP 279 7.5 Grouped | M | V | - Firmware- 267 5.3.4 Unsigned32 | | V,M | - Revision | | | - Host-IP-Address 257 5.3.5 Address | M | V | - Inband-Security | M | V | - -Id 299 6.10 Unsigned32 | | | - Multi-Round- 272 8.19 Unsigned32 | M | V | - Time-Out | | | - Origin-Host 264 6.3 DiamIdent | M | V | - Origin-Realm 296 6.4 DiamIdent | M | V | - Origin-State-Id 278 8.16 Unsigned32 | M | V | - Product-Name 269 5.3.7 UTF8String | | V,M | - Proxy-Host 280 6.7.3 DiamIdent | M | V | - Proxy-Info 284 6.7.2 Grouped | M | V | - Proxy-State 33 6.7.4 OctetString| M | V | - Redirect-Host 292 6.12 DiamURI | M | V | - Redirect-Host- 261 6.13 Enumerated | M | V | - Usage | | | - Redirect-Max- 262 6.14 Unsigned32 | M | V | - Cache-Time | | | - Result-Code 268 7.1 Unsigned32 | M | V | - Route-Record 282 6.7.1 DiamIdent | M | V | - Session-Id 263 8.8 UTF8String | M | V | - Session-Timeout 27 8.13 Unsigned32 | M | V | - Session-Binding 270 8.17 Unsigned32 | M | V | - Session-Server- 271 8.18 Enumerated | M | V | - Failover | | | - Supported- 265 5.3.6 Unsigned32 | M | V | - Vendor-Id | | | - Termination- 295 8.15 Enumerated | M | V | - Cause | | | - User-Name 1 8.14 UTF8String | M | V | - Vendor-Id 266 5.3.3 Unsigned32 | M | V | - Vendor-Specific- 260 6.11 Grouped | M | V | - Application-Id | | | - -----------------------------------------|----+-----| - - - - - - -Fajardo, et al. Standards Track [Page 57] - -RFC 6733 Diameter Base Protocol October 2012 - - -5. Diameter Peers - - This section describes how Diameter nodes establish connections and - communicate with peers. - -5.1. Peer Connections - - Connections between diameter peers are established using their valid - DiameterIdentity. A Diameter node initiating a connection to a peer - MUST know the peer's DiameterIdentity. Methods for discovering a - Diameter peer can be found in Section 5.2. - - Although a Diameter node may have many possible peers with which it - is able to communicate, it may not be economical to have an - established connection to all of them. At a minimum, a Diameter node - SHOULD have an established connection with two peers per realm, known - as the primary and secondary peers. Of course, a node MAY have - additional connections, if it is deemed necessary. Typically, all - messages for a realm are sent to the primary peer but, in the event - that failover procedures are invoked, any pending requests are sent - to the secondary peer. However, implementations are free to load - balance requests between a set of peers. - - Note that a given peer MAY act as a primary for a given realm while - acting as a secondary for another realm. - - When a peer is deemed suspect, which could occur for various reasons, - including not receiving a DWA within an allotted time frame, no new - requests should be forwarded to the peer, but failover procedures are - invoked. When an active peer is moved to this mode, additional - connections SHOULD be established to ensure that the necessary number - of active connections exists. - - There are two ways that a peer is removed from the suspect peer list: - - 1. The peer is no longer reachable, causing the transport connection - to be shut down. The peer is moved to the closed state. - - 2. Three watchdog messages are exchanged with accepted round-trip - times, and the connection to the peer is considered stabilized. - - In the event the peer being removed is either the primary or - secondary, an alternate peer SHOULD replace the deleted peer and - assume the role of either primary or secondary. - - - - - - - -Fajardo, et al. Standards Track [Page 58] - -RFC 6733 Diameter Base Protocol October 2012 - - -5.2. Diameter Peer Discovery - - Allowing for dynamic Diameter agent discovery makes possible simpler - and more robust deployment of Diameter services. In order to promote - interoperable implementations of Diameter peer discovery, the - following mechanisms (manual configuration and DNS) are described. - These are based on existing IETF standards. Both mechanisms MUST be - supported by all Diameter implementations; either MAY be used. - - There are two cases where Diameter peer discovery may be performed. - The first is when a Diameter client needs to discover a first-hop - Diameter agent. The second case is when a Diameter agent needs to - discover another agent for further handling of a Diameter operation. - In both cases, the following 'search order' is recommended: - - 1. The Diameter implementation consults its list of statically - (manually) configured Diameter agent locations. These will be - used if they exist and respond. - - 2. The Diameter implementation performs a NAPTR query for a server - in a particular realm. The Diameter implementation has to know, - in advance, in which realm to look for a Diameter agent. This - could be deduced, for example, from the 'realm' in an NAI on - which a Diameter implementation needed to perform a Diameter - operation. - - The NAPTR usage in Diameter follows the S-NAPTR DDDS application - [RFC3958] in which the SERVICE field includes tags for the - desired application and supported application protocol. The - application service tag for a Diameter application is 'aaa' and - the supported application protocol tags are 'diameter.tcp', - 'diameter.sctp', 'diameter.dtls', or 'diameter.tls.tcp' - [RFC6408]. - - The client can follow the resolution process defined by the - S-NAPTR DDDS [RFC3958] application to find a matching SRV, A, or - AAAA record of a suitable peer. The domain suffixes in the NAPTR - replacement field SHOULD match the domain of the original query. - An example can be found in Appendix B. - - 3. If no NAPTR records are found, the requester directly queries for - one of the following SRV records: for Diameter over TCP, use - "_diameter._tcp.realm"; for Diameter over TLS, use - "_diameters._tcp.realm"; for Diameter over SCTP, use - "_diameter._sctp.realm"; for Diameter over DTLS, use - "_diameters._sctp.realm". If SRV records are found, then the - requester can perform address record query (A RR's and/or AAAA - - - - -Fajardo, et al. Standards Track [Page 59] - -RFC 6733 Diameter Base Protocol October 2012 - - - RR's) for the target hostname specified in the SRV records - following the rules given in [RFC2782]. If no SRV records are - found, the requester gives up. - - If the server is using a site certificate, the domain name in the - NAPTR query and the domain name in the replacement field MUST both be - valid based on the site certificate handed out by the server in the - TLS/TCP and DTLS/SCTP or Internet Key Exchange Protocol (IKE) - exchange. Similarly, the domain name in the SRV query and the domain - name in the target in the SRV record MUST both be valid based on the - same site certificate. Otherwise, an attacker could modify the DNS - records to contain replacement values in a different domain, and the - client could not validate whether this was the desired behavior or - the result of an attack. - - Also, the Diameter peer MUST check to make sure that the discovered - peers are authorized to act in its role. Authentication via IKE or - TLS/TCP and DTLS/SCTP, or validation of DNS RRs via DNSSEC is not - sufficient to conclude this. For example, a web server may have - obtained a valid TLS/TCP and DTLS/SCTP certificate, and secured RRs - may be included in the DNS, but this does not imply that it is - authorized to act as a Diameter server. - - Authorization can be achieved, for example, by the configuration of a - Diameter server Certification Authority (CA). The server CA issues a - certificate to the Diameter server, which includes an Object - Identifier (OID) to indicate the subject is a Diameter server in the - Extended Key Usage extension [RFC5280]. This certificate is then - used during TLS/TCP, DTLS/SCTP, or IKE security negotiation. - However, note that, at the time of writing, no Diameter server - Certification Authorities exist. - - A dynamically discovered peer causes an entry in the peer table (see - Section 2.6) to be created. Note that entries created via DNS MUST - expire (or be refreshed) within the DNS Time to Live (TTL). If a - peer is discovered outside of the local realm, a routing table entry - (see Section 2.7) for the peer's realm is created. The routing table - entry's expiration MUST match the peer's expiration value. - -5.3. Capabilities Exchange - - When two Diameter peers establish a transport connection, they MUST - exchange the Capabilities Exchange messages, as specified in the peer - state machine (see Section 5.6). This message allows the discovery - of a peer's identity and its capabilities (protocol version number, - the identifiers of supported Diameter applications, security - mechanisms, etc.). - - - - -Fajardo, et al. Standards Track [Page 60] - -RFC 6733 Diameter Base Protocol October 2012 - - - The receiver only issues commands to its peers that have advertised - support for the Diameter application that defines the command. A - Diameter node MUST cache the supported Application Ids in order to - ensure that unrecognized commands and/or AVPs are not unnecessarily - sent to a peer. - - A receiver of a Capabilities-Exchange-Request (CER) message that does - not have any applications in common with the sender MUST return a - Capabilities-Exchange-Answer (CEA) with the Result-Code AVP set to - DIAMETER_NO_COMMON_APPLICATION and SHOULD disconnect the transport - layer connection. Note that receiving a CER or CEA from a peer - advertising itself as a relay (see Section 2.4) MUST be interpreted - as having common applications with the peer. - - The receiver of the Capabilities-Exchange-Request (CER) MUST - determine common applications by computing the intersection of its - own set of supported Application Ids against all of the - Application-Id AVPs (Auth-Application-Id, Acct-Application-Id, and - Vendor-Specific-Application-Id) present in the CER. The value of the - Vendor-Id AVP in the Vendor-Specific-Application-Id MUST NOT be used - during computation. The sender of the Capabilities-Exchange-Answer - (CEA) SHOULD include all of its supported applications as a hint to - the receiver regarding all of its application capabilities. - - Diameter implementations SHOULD first attempt to establish a TLS/TCP - and DTLS/SCTP connection prior to the CER/CEA exchange. This - protects the capabilities information of both peers. To support - older Diameter implementations that do not fully conform to this - document, the transport security MAY still be negotiated via an - Inband-Security AVP. In this case, the receiver of a Capabilities- - Exchange-Request (CER) message that does not have any security - mechanisms in common with the sender MUST return a Capabilities- - Exchange-Answer (CEA) with the Result-Code AVP set to - DIAMETER_NO_COMMON_SECURITY and SHOULD disconnect the transport layer - connection. - - CERs received from unknown peers MAY be silently discarded, or a CEA - MAY be issued with the Result-Code AVP set to DIAMETER_UNKNOWN_PEER. - In both cases, the transport connection is closed. If the local - policy permits receiving CERs from unknown hosts, a successful CEA - MAY be returned. If a CER from an unknown peer is answered with a - successful CEA, the lifetime of the peer entry is equal to the - lifetime of the transport connection. In case of a transport - failure, all the pending transactions destined to the unknown peer - can be discarded. - - The CER and CEA messages MUST NOT be proxied, redirected, or relayed. - - - - -Fajardo, et al. Standards Track [Page 61] - -RFC 6733 Diameter Base Protocol October 2012 - - - Since the CER/CEA messages cannot be proxied, it is still possible - that an upstream agent will receive a message for which it has no - available peers to handle the application that corresponds to the - Command Code. In such instances, the 'E' bit is set in the answer - message (Section 7) with the Result-Code AVP set to - DIAMETER_UNABLE_TO_DELIVER to inform the downstream agent to take - action (e.g., re-routing request to an alternate peer). - - With the exception of the Capabilities-Exchange-Request message, a - message of type Request that includes the Auth-Application-Id or - Acct-Application-Id AVPs, or a message with an application-specific - Command Code MAY only be forwarded to a host that has explicitly - advertised support for the application (or has advertised the Relay - Application Id). - -5.3.1. Capabilities-Exchange-Request - - The Capabilities-Exchange-Request (CER), indicated by the Command - Code set to 257 and the Command Flags' 'R' bit set, is sent to - exchange local capabilities. Upon detection of a transport failure, - this message MUST NOT be sent to an alternate peer. - - When Diameter is run over SCTP [RFC4960] or DTLS/SCTP [RFC6083], - which allow for connections to span multiple interfaces and multiple - IP addresses, the Capabilities-Exchange-Request message MUST contain - one Host-IP-Address AVP for each potential IP address that MAY be - locally used when transmitting Diameter messages. - - Message Format - - <CER> ::= < Diameter Header: 257, REQ > - { Origin-Host } - { Origin-Realm } - 1* { Host-IP-Address } - { Vendor-Id } - { Product-Name } - [ Origin-State-Id ] - * [ Supported-Vendor-Id ] - * [ Auth-Application-Id ] - * [ Inband-Security-Id ] - * [ Acct-Application-Id ] - * [ Vendor-Specific-Application-Id ] - [ Firmware-Revision ] - * [ AVP ] - - - - - - - -Fajardo, et al. Standards Track [Page 62] - -RFC 6733 Diameter Base Protocol October 2012 - - -5.3.2. Capabilities-Exchange-Answer - - The Capabilities-Exchange-Answer (CEA), indicated by the Command Code - set to 257 and the Command Flags' 'R' bit cleared, is sent in - response to a CER message. - - When Diameter is run over SCTP [RFC4960] or DTLS/SCTP [RFC6083], - which allow connections to span multiple interfaces, hence, multiple - IP addresses, the Capabilities-Exchange-Answer message MUST contain - one Host-IP-Address AVP for each potential IP address that MAY be - locally used when transmitting Diameter messages. - - Message Format - - <CEA> ::= < Diameter Header: 257 > - { Result-Code } - { Origin-Host } - { Origin-Realm } - 1* { Host-IP-Address } - { Vendor-Id } - { Product-Name } - [ Origin-State-Id ] - [ Error-Message ] - [ Failed-AVP ] - * [ Supported-Vendor-Id ] - * [ Auth-Application-Id ] - * [ Inband-Security-Id ] - * [ Acct-Application-Id ] - * [ Vendor-Specific-Application-Id ] - [ Firmware-Revision ] - * [ AVP ] - -5.3.3. Vendor-Id AVP - - The Vendor-Id AVP (AVP Code 266) is of type Unsigned32 and contains - the IANA "SMI Network Management Private Enterprise Codes" - [ENTERPRISE] value assigned to the Diameter Software vendor. It is - envisioned that the combination of the Vendor-Id, Product-Name - (Section 5.3.7), and Firmware-Revision (Section 5.3.4) AVPs may - provide useful debugging information. - - A Vendor-Id value of zero in the CER or CEA message is reserved and - indicates that this field is ignored. - - - - - - - - -Fajardo, et al. Standards Track [Page 63] - -RFC 6733 Diameter Base Protocol October 2012 - - -5.3.4. Firmware-Revision AVP - - The Firmware-Revision AVP (AVP Code 267) is of type Unsigned32 and is - used to inform a Diameter peer of the firmware revision of the - issuing device. - - For devices that do not have a firmware revision (general-purpose - computers running Diameter software modules, for instance), the - revision of the Diameter software module may be reported instead. - -5.3.5. Host-IP-Address AVP - - The Host-IP-Address AVP (AVP Code 257) is of type Address and is used - to inform a Diameter peer of the sender's IP address. All source - addresses that a Diameter node expects to use with SCTP [RFC4960] or - DTLS/SCTP [RFC6083] MUST be advertised in the CER and CEA messages by - including a Host-IP-Address AVP for each address. - -5.3.6. Supported-Vendor-Id AVP - - The Supported-Vendor-Id AVP (AVP Code 265) is of type Unsigned32 and - contains the IANA "SMI Network Management Private Enterprise Codes" - [ENTERPRISE] value assigned to a vendor other than the device vendor - but including the application vendor. This is used in the CER and - CEA messages in order to inform the peer that the sender supports (a - subset of) the Vendor-Specific AVPs defined by the vendor identified - in this AVP. The value of this AVP MUST NOT be set to zero. - Multiple instances of this AVP containing the same value SHOULD NOT - be sent. - -5.3.7. Product-Name AVP - - The Product-Name AVP (AVP Code 269) is of type UTF8String and - contains the vendor-assigned name for the product. The Product-Name - AVP SHOULD remain constant across firmware revisions for the same - product. - -5.4. Disconnecting Peer Connections - - When a Diameter node disconnects one of its transport connections, - its peer cannot know the reason for the disconnect and will most - likely assume that a connectivity problem occurred or that the peer - has rebooted. In these cases, the peer may periodically attempt to - reconnect, as stated in Section 2.1. In the event that the - disconnect was a result of either a shortage of internal resources or - simply that the node in question has no intentions of forwarding any - Diameter messages to the peer in the foreseeable future, a periodic - - - - -Fajardo, et al. Standards Track [Page 64] - -RFC 6733 Diameter Base Protocol October 2012 - - - connection request would not be welcomed. The Disconnection-Reason - AVP contains the reason the Diameter node issued the Disconnect-Peer- - Request message. - - The Disconnect-Peer-Request message is used by a Diameter node to - inform its peer of its intent to disconnect the transport layer and - that the peer shouldn't reconnect unless it has a valid reason to do - so (e.g., message to be forwarded). Upon receipt of the message, the - Disconnect-Peer-Answer message is returned, which SHOULD contain an - error if messages have recently been forwarded, and are likely in - flight, which would otherwise cause a race condition. - - The receiver of the Disconnect-Peer-Answer message initiates the - transport disconnect. The sender of the Disconnect-Peer-Answer - message should be able to detect the transport closure and clean up - the connection. - -5.4.1. Disconnect-Peer-Request - - The Disconnect-Peer-Request (DPR), indicated by the Command Code set - to 282 and the Command Flags' 'R' bit set, is sent to a peer to - inform it of its intentions to shut down the transport connection. - Upon detection of a transport failure, this message MUST NOT be sent - to an alternate peer. - - Message Format - - <DPR> ::= < Diameter Header: 282, REQ > - { Origin-Host } - { Origin-Realm } - { Disconnect-Cause } - * [ AVP ] - -5.4.2. Disconnect-Peer-Answer - - The Disconnect-Peer-Answer (DPA), indicated by the Command Code set - to 282 and the Command Flags' 'R' bit cleared, is sent as a response - to the Disconnect-Peer-Request message. Upon receipt of this - message, the transport connection is shut down. - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 65] - -RFC 6733 Diameter Base Protocol October 2012 - - - Message Format - - <DPA> ::= < Diameter Header: 282 > - { Result-Code } - { Origin-Host } - { Origin-Realm } - [ Error-Message ] - [ Failed-AVP ] - * [ AVP ] - - -5.4.3. Disconnect-Cause AVP - - The Disconnect-Cause AVP (AVP Code 273) is of type Enumerated. A - Diameter node MUST include this AVP in the Disconnect-Peer-Request - message to inform the peer of the reason for its intention to shut - down the transport connection. The following values are supported: - - REBOOTING 0 - A scheduled reboot is imminent. A receiver of a DPR with - above result code MAY attempt reconnection. - - BUSY 1 - The peer's internal resources are constrained, and it has - determined that the transport connection needs to be closed. - A receiver of a DPR with above result code SHOULD NOT attempt - reconnection. - - DO_NOT_WANT_TO_TALK_TO_YOU 2 - The peer has determined that it does not see a need for the - transport connection to exist, since it does not expect any - messages to be exchanged in the near future. A receiver of a - DPR with above result code SHOULD NOT attempt reconnection. - -5.5. Transport Failure Detection - - Given the nature of the Diameter protocol, it is recommended that - transport failures be detected as soon as possible. Detecting such - failures will minimize the occurrence of messages sent to unavailable - agents, resulting in unnecessary delays, and will provide better - failover performance. The Device-Watchdog-Request and Device- - Watchdog-Answer messages, defined in this section, are used to pro- - actively detect transport failures. - - - - - - - - -Fajardo, et al. Standards Track [Page 66] - -RFC 6733 Diameter Base Protocol October 2012 - - -5.5.1. Device-Watchdog-Request - - The Device-Watchdog-Request (DWR), indicated by the Command Code set - to 280 and the Command Flags' 'R' bit set, is sent to a peer when no - traffic has been exchanged between two peers (see Section 5.5.3). - Upon detection of a transport failure, this message MUST NOT be sent - to an alternate peer. - - Message Format - - <DWR> ::= < Diameter Header: 280, REQ > - { Origin-Host } - { Origin-Realm } - [ Origin-State-Id ] - * [ AVP ] - -5.5.2. Device-Watchdog-Answer - - The Device-Watchdog-Answer (DWA), indicated by the Command Code set - to 280 and the Command Flags' 'R' bit cleared, is sent as a response - to the Device-Watchdog-Request message. - - Message Format - - <DWA> ::= < Diameter Header: 280 > - { Result-Code } - { Origin-Host } - { Origin-Realm } - [ Error-Message ] - [ Failed-AVP ] - [ Origin-State-Id ] - * [ AVP ] - -5.5.3. Transport Failure Algorithm - - The transport failure algorithm is defined in [RFC3539]. All - Diameter implementations MUST support the algorithm defined in that - specification in order to be compliant to the Diameter base protocol. - -5.5.4. Failover and Failback Procedures - - In the event that a transport failure is detected with a peer, it is - necessary for all pending request messages to be forwarded to an - alternate agent, if possible. This is commonly referred to as - "failover". - - - - - - -Fajardo, et al. Standards Track [Page 67] - -RFC 6733 Diameter Base Protocol October 2012 - - - In order for a Diameter node to perform failover procedures, it is - necessary for the node to maintain a pending message queue for a - given peer. When an answer message is received, the corresponding - request is removed from the queue. The Hop-by-Hop Identifier field - is used to match the answer with the queued request. - - When a transport failure is detected, if possible, all messages in - the queue are sent to an alternate agent with the T flag set. On - booting a Diameter client or agent, the T flag is also set on any - remaining records in non-volatile storage that are still waiting to - be transmitted. An example of a case where it is not possible to - forward the message to an alternate server is when the message has a - fixed destination, and the unavailable peer is the message's final - destination (see Destination-Host AVP). Such an error requires that - the agent return an answer message with the 'E' bit set and the - Result-Code AVP set to DIAMETER_UNABLE_TO_DELIVER. - - It is important to note that multiple identical requests or answers - MAY be received as a result of a failover. The End-to-End Identifier - field in the Diameter header along with the Origin-Host AVP MUST be - used to identify duplicate messages. - - As described in Section 2.1, a connection request should be - periodically attempted with the failed peer in order to re-establish - the transport connection. Once a connection has been successfully - established, messages can once again be forwarded to the peer. This - is commonly referred to as "failback". - -5.6. Peer State Machine - - This section contains a finite state machine that MUST be observed by - all Diameter implementations. Each Diameter node MUST follow the - state machine described below when communicating with each peer. - Multiple actions are separated by commas, and may continue on - succeeding lines, as space requires. Similarly, state and next state - may also span multiple lines, as space requires. - - This state machine is closely coupled with the state machine - described in [RFC3539], which is used to open, close, failover, - probe, and reopen transport connections. In particular, note that - [RFC3539] requires the use of watchdog messages to probe connections. - For Diameter, DWR and DWA messages are to be used. - - The I- prefix is used to represent the initiator (connecting) - connection, while the R- prefix is used to represent the responder - (listening) connection. The lack of a prefix indicates that the - event or action is the same regardless of the connection on which the - event occurred. - - - -Fajardo, et al. Standards Track [Page 68] - -RFC 6733 Diameter Base Protocol October 2012 - - - The stable states that a state machine may be in are Closed, I-Open, - and R-Open; all other states are intermediate. Note that I-Open and - R-Open are equivalent except for whether the initiator or responder - transport connection is used for communication. - - A CER message is always sent on the initiating connection immediately - after the connection request is successfully completed. In the case - of an election, one of the two connections will shut down. The - responder connection will survive if the Origin-Host of the local - Diameter entity is higher than that of the peer; the initiator - connection will survive if the peer's Origin-Host is higher. All - subsequent messages are sent on the surviving connection. Note that - the results of an election on one peer are guaranteed to be the - inverse of the results on the other. - - For TLS/TCP and DTLS/SCTP usage, a TLS/TCP and DTLS/SCTP handshake - SHOULD begin when both ends are in the closed state prior to any - Diameter message exchanges. The TLS/TCP and DTLS/SCTP connection - SHOULD be established before sending any CER or CEA message to secure - and protect the capabilities information of both peers. The TLS/TCP - and DTLS/SCTP connection SHOULD be disconnected when the state - machine moves to the closed state. When connecting to responders - that do not conform to this document (i.e., older Diameter - implementations that are not prepared to received TLS/TCP and DTLS/ - SCTP connections in the closed state), the initial TLS/TCP and DTLS/ - SCTP connection attempt will fail. The initiator MAY then attempt to - connect via TCP or SCTP and initiate the TLS/TCP and DTLS/SCTP - handshake when both ends are in the open state. If the handshake is - successful, all further messages will be sent via TLS/TCP and DTLS/ - SCTP. If the handshake fails, both ends move to the closed state. - - The state machine constrains only the behavior of a Diameter - implementation as seen by Diameter peers through events on the wire. - - Any implementation that produces equivalent results is considered - compliant. - - - - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 69] - -RFC 6733 Diameter Base Protocol October 2012 - - - state event action next state - ----------------------------------------------------------------- - Closed Start I-Snd-Conn-Req Wait-Conn-Ack - R-Conn-CER R-Accept, R-Open - Process-CER, - R-Snd-CEA - - Wait-Conn-Ack I-Rcv-Conn-Ack I-Snd-CER Wait-I-CEA - I-Rcv-Conn-Nack Cleanup Closed - R-Conn-CER R-Accept, Wait-Conn-Ack/ - Process-CER Elect - Timeout Error Closed - - Wait-I-CEA I-Rcv-CEA Process-CEA I-Open - R-Conn-CER R-Accept, Wait-Returns - Process-CER, - Elect - I-Peer-Disc I-Disc Closed - I-Rcv-Non-CEA Error Closed - Timeout Error Closed - - Wait-Conn-Ack/ I-Rcv-Conn-Ack I-Snd-CER,Elect Wait-Returns - Elect I-Rcv-Conn-Nack R-Snd-CEA R-Open - R-Peer-Disc R-Disc Wait-Conn-Ack - R-Conn-CER R-Reject Wait-Conn-Ack/ - Elect - Timeout Error Closed - - Wait-Returns Win-Election I-Disc,R-Snd-CEA R-Open - I-Peer-Disc I-Disc, R-Open - R-Snd-CEA - I-Rcv-CEA R-Disc I-Open - R-Peer-Disc R-Disc Wait-I-CEA - R-Conn-CER R-Reject Wait-Returns - Timeout Error Closed - - R-Open Send-Message R-Snd-Message R-Open - R-Rcv-Message Process R-Open - R-Rcv-DWR Process-DWR, R-Open - R-Snd-DWA - R-Rcv-DWA Process-DWA R-Open - R-Conn-CER R-Reject R-Open - Stop R-Snd-DPR Closing - R-Rcv-DPR R-Snd-DPA Closing - R-Peer-Disc R-Disc Closed - - - - - - -Fajardo, et al. Standards Track [Page 70] - -RFC 6733 Diameter Base Protocol October 2012 - - - I-Open Send-Message I-Snd-Message I-Open - I-Rcv-Message Process I-Open - I-Rcv-DWR Process-DWR, I-Open - I-Snd-DWA - I-Rcv-DWA Process-DWA I-Open - R-Conn-CER R-Reject I-Open - Stop I-Snd-DPR Closing - I-Rcv-DPR I-Snd-DPA Closing - I-Peer-Disc I-Disc Closed - - Closing I-Rcv-DPA I-Disc Closed - R-Rcv-DPA R-Disc Closed - Timeout Error Closed - I-Peer-Disc I-Disc Closed - R-Peer-Disc R-Disc Closed - -5.6.1. Incoming Connections - - When a connection request is received from a Diameter peer, it is - not, in the general case, possible to know the identity of that peer - until a CER is received from it. This is because host and port - determine the identity of a Diameter peer; the source port of an - incoming connection is arbitrary. Upon receipt of a CER, the - identity of the connecting peer can be uniquely determined from the - Origin-Host. - - For this reason, a Diameter peer must employ logic separate from the - state machine to receive connection requests, accept them, and await - the CER. Once the CER arrives on a new connection, the Origin-Host - that identifies the peer is used to locate the state machine - associated with that peer, and the new connection and CER are passed - to the state machine as an R-Conn-CER event. - - The logic that handles incoming connections SHOULD close and discard - the connection if any message other than a CER arrives or if an - implementation-defined timeout occurs prior to receipt of CER. - - Because handling of incoming connections up to and including receipt - of a CER requires logic, separate from that of any individual state - machine associated with a particular peer, it is described separately - in this section rather than in the state machine above. - -5.6.2. Events - - Transitions and actions in the automaton are caused by events. In - this section, we will ignore the I- and R- prefixes, since the actual - event would be identical, but it would occur on one of two possible - connections. - - - -Fajardo, et al. Standards Track [Page 71] - -RFC 6733 Diameter Base Protocol October 2012 - - - Start The Diameter application has signaled that a - connection should be initiated with the peer. - - R-Conn-CER An acknowledgement is received stating that the - transport connection has been established, and the - associated CER has arrived. - - Rcv-Conn-Ack A positive acknowledgement is received confirming that - the transport connection is established. - - Rcv-Conn-Nack A negative acknowledgement was received stating that - the transport connection was not established. - - Timeout An application-defined timer has expired while waiting - for some event. - - Rcv-CER A CER message from the peer was received. - - Rcv-CEA A CEA message from the peer was received. - - Rcv-Non-CEA A message, other than a CEA, from the peer was - received. - - Peer-Disc A disconnection indication from the peer was received. - - Rcv-DPR A DPR message from the peer was received. - - Rcv-DPA A DPA message from the peer was received. - - Win-Election An election was held, and the local node was the - winner. - - Send-Message A message is to be sent. - - Rcv-Message A message other than CER, CEA, DPR, DPA, DWR, or DWA - was received. - - Stop The Diameter application has signaled that a - connection should be terminated (e.g., on system - shutdown). - -5.6.3. Actions - - Actions in the automaton are caused by events and typically indicate - the transmission of packets and/or an action to be taken on the - connection. In this section, we will ignore the I- and R- prefixes, - since the actual action would be identical, but it would occur on one - of two possible connections. - - - -Fajardo, et al. Standards Track [Page 72] - -RFC 6733 Diameter Base Protocol October 2012 - - - Snd-Conn-Req A transport connection is initiated with the peer. - - Accept The incoming connection associated with the R-Conn-CER - is accepted as the responder connection. - - Reject The incoming connection associated with the R-Conn-CER - is disconnected. - - Process-CER The CER associated with the R-Conn-CER is processed. - - Snd-CER A CER message is sent to the peer. - - Snd-CEA A CEA message is sent to the peer. - - Cleanup If necessary, the connection is shut down, and any - local resources are freed. - - Error The transport layer connection is disconnected, - either politely or abortively, in response to - an error condition. Local resources are freed. - - Process-CEA A received CEA is processed. - - Snd-DPR A DPR message is sent to the peer. - - Snd-DPA A DPA message is sent to the peer. - - Disc The transport layer connection is disconnected, - and local resources are freed. - - Elect An election occurs (see Section 5.6.4 for more - information). - - Snd-Message A message is sent. - - Snd-DWR A DWR message is sent. - - Snd-DWA A DWA message is sent. - - Process-DWR The DWR message is serviced. - - Process-DWA The DWA message is serviced. - - Process A message is serviced. - - - - - - - -Fajardo, et al. Standards Track [Page 73] - -RFC 6733 Diameter Base Protocol October 2012 - - -5.6.4. The Election Process - - The election is performed on the responder. The responder compares - the Origin-Host received in the CER with its own Origin-Host as two - streams of octets. If the local Origin-Host lexicographically - succeeds the received Origin-Host, a Win-Election event is issued - locally. Diameter identities are in ASCII form; therefore, the - lexical comparison is consistent with DNS case insensitivity, where - octets that fall in the ASCII range 'a' through 'z' MUST compare - equally to their uppercase counterparts between 'A' and 'Z'. See - Appendix D for interactions between the Diameter protocol and - Internationalized Domain Name (IDNs). - - The winner of the election MUST close the connection it initiated. - Historically, maintaining the responder side of a connection was more - efficient than maintaining the initiator side. However, current - practices makes this distinction irrelevant. - -6. Diameter Message Processing - - This section describes how Diameter requests and answers are created - and processed. - -6.1. Diameter Request Routing Overview - - A request is sent towards its final destination using one of the - following three combinations of the Destination-Realm and - Destination-Host AVPs: - - o A request that is not able to be proxied (such as a CER) MUST NOT - contain either Destination-Realm or Destination-Host AVPs. - - o A request that needs to be sent to a home server serving a - specific realm, but not to a specific server (such as the first - request of a series of round trips), MUST contain a Destination- - Realm AVP but MUST NOT contain a Destination-Host AVP. For - Diameter clients, the value of the Destination-Realm AVP MAY be - extracted from the User-Name AVP, or other methods. - - o Otherwise, a request that needs to be sent to a specific home - server among those serving a given realm MUST contain both the - Destination-Realm and Destination-Host AVPs. - - The Destination-Host AVP is used as described above when the - destination of the request is fixed, which includes: - - o Authentication requests that span multiple round trips. - - - - -Fajardo, et al. Standards Track [Page 74] - -RFC 6733 Diameter Base Protocol October 2012 - - - o A Diameter message that uses a security mechanism that makes use - of a pre-established session key shared between the source and the - final destination of the message. - - o Server-initiated messages that MUST be received by a specific - Diameter client (e.g., access device), such as the Abort-Session- - Request message, which is used to request that a particular user's - session be terminated. - - Note that an agent can only forward a request to a host described in - the Destination-Host AVP if the host in question is included in its - peer table (see Section 2.6). Otherwise, the request is routed based - on the Destination-Realm only (see Section 6.1.6). - - When a message is received, the message is processed in the following - order: - - o If the message is destined for the local host, the procedures - listed in Section 6.1.4 are followed. - - o If the message is intended for a Diameter peer with whom the local - host is able to directly communicate, the procedures listed in - Section 6.1.5 are followed. This is known as "Request - Forwarding". - - o The procedure listed in Section 6.1.6 is followed, which is known - as "Request Routing". - - o If none of the above are successful, an answer is returned with - the Result-Code set to DIAMETER_UNABLE_TO_DELIVER, with the 'E' - bit set. - - For routing of Diameter messages to work within an administrative - domain, all Diameter nodes within the realm MUST be peers. - - The overview contained in this section (6.1) is intended to provide - general guidelines to Diameter developers. Implementations are free - to use different methods than the ones described here as long as they - conform to the requirements specified in Sections 6.1.1 through - 6.1.9. See Section 7 for more details on error handling. - -6.1.1. Originating a Request - - When creating a request, in addition to any other procedures - described in the application definition for that specific request, - the following procedures MUST be followed: - - - - - -Fajardo, et al. Standards Track [Page 75] - -RFC 6733 Diameter Base Protocol October 2012 - - - o the Command Code is set to the appropriate value; - - o the 'R' bit is set; - - o the End-to-End Identifier is set to a locally unique value; - - o the Origin-Host and Origin-Realm AVPs MUST be set to the - appropriate values, used to identify the source of the message; - and - - o the Destination-Host and Destination-Realm AVPs MUST be set to the - appropriate values, as described in Section 6.1. - -6.1.2. Sending a Request - - When sending a request, originated either locally or as the result of - a forwarding or routing operation, the following procedures SHOULD be - followed: - - o The Hop-by-Hop Identifier SHOULD be set to a locally unique value. - - o The message SHOULD be saved in the list of pending requests. - - Other actions to perform on the message based on the particular role - the agent is playing are described in the following sections. - -6.1.3. Receiving Requests - - A relay or proxy agent MUST check for forwarding loops when receiving - requests. A loop is detected if the server finds its own identity in - a Route-Record AVP. When such an event occurs, the agent MUST answer - with the Result-Code AVP set to DIAMETER_LOOP_DETECTED. - -6.1.4. Processing Local Requests - - A request is known to be for local consumption when one of the - following conditions occurs: - - o The Destination-Host AVP contains the local host's identity; - - o The Destination-Host AVP is not present, the Destination-Realm AVP - contains a realm the server is configured to process locally, and - the Diameter application is locally supported; or - - o Both the Destination-Host and the Destination-Realm are not - present. - - - - - -Fajardo, et al. Standards Track [Page 76] - -RFC 6733 Diameter Base Protocol October 2012 - - - When a request is locally processed, the rules in Section 6.2 should - be used to generate the corresponding answer. - -6.1.5. Request Forwarding - - Request forwarding is done using the Diameter peer table. The - Diameter peer table contains all of the peers with which the local - node is able to directly communicate. - - When a request is received, and the host encoded in the Destination- - Host AVP is one that is present in the peer table, the message SHOULD - be forwarded to the peer. - -6.1.6. Request Routing - - Diameter request message routing is done via realms and Application - Ids. A Diameter message that may be forwarded by Diameter agents - (proxies, redirect agents, or relay agents) MUST include the target - realm in the Destination-Realm AVP. Request routing SHOULD rely on - the Destination-Realm AVP and the Application Id present in the - request message header to aid in the routing decision. The realm MAY - be retrieved from the User-Name AVP, which is in the form of a - Network Access Identifier (NAI). The realm portion of the NAI is - inserted in the Destination-Realm AVP. - - Diameter agents MAY have a list of locally supported realms and - applications, and they MAY have a list of externally supported realms - and applications. When a request is received that includes a realm - and/or application that is not locally supported, the message is - routed to the peer configured in the routing table (see Section 2.7). - - Realm names and Application Ids are the minimum supported routing - criteria, additional information may be needed to support redirect - semantics. - -6.1.7. Predictive Loop Avoidance - - Before forwarding or routing a request, Diameter agents, in addition - to performing the processing described in Section 6.1.3, SHOULD check - for the presence of a candidate route's peer identity in any of the - Route-Record AVPs. In the event of the agent detecting the presence - of a candidate route's peer identity in a Route-Record AVP, the agent - MUST ignore such a route for the Diameter request message and attempt - alternate routes if any exist. In case all the candidate routes are - eliminated by the above criteria, the agent SHOULD return a - DIAMETER_UNABLE_TO_DELIVER message. - - - - - -Fajardo, et al. Standards Track [Page 77] - -RFC 6733 Diameter Base Protocol October 2012 - - -6.1.8. Redirecting Requests - - When a redirect agent receives a request whose routing entry is set - to REDIRECT, it MUST reply with an answer message with the 'E' bit - set, while maintaining the Hop-by-Hop Identifier in the header, and - include the Result-Code AVP to DIAMETER_REDIRECT_INDICATION. Each of - the servers associated with the routing entry are added in a separate - Redirect-Host AVP. - - +------------------+ - | Diameter | - | Redirect Agent | - +------------------+ - ^ | 2. command + 'E' bit - 1. Request | | Result-Code = - [email protected] | | DIAMETER_REDIRECT_INDICATION + - | | Redirect-Host AVP(s) - | v - +-------------+ 3. Request +-------------+ - | example.com |------------->| example.net | - | Relay | | Diameter | - | Agent |<-------------| Server | - +-------------+ 4. Answer +-------------+ - - Figure 5: Diameter Redirect Agent - - The receiver of an answer message with the 'E' bit set and the - Result-Code AVP set to DIAMETER_REDIRECT_INDICATION uses the Hop-by- - Hop Identifier in the Diameter header to identify the request in the - pending message queue (see Section 5.5.4) that is to be redirected. - If no transport connection exists with the new peer, one is created, - and the request is sent directly to it. - - Multiple Redirect-Host AVPs are allowed. The receiver of the answer - message with the 'E' bit set selects exactly one of these hosts as - the destination of the redirected message. - - When the Redirect-Host-Usage AVP included in the answer message has a - non-zero value, a route entry for the redirect indications is created - and cached by the receiver. The redirect usage for such a route - entry is set by the value of Redirect-Host-Usage AVP and the lifetime - of the cached route entry is set by Redirect-Max-Cache-Time AVP - value. - - It is possible that multiple redirect indications can create multiple - cached route entries differing only in their redirect usage and the - peer to forward messages to. As an example, two(2) route entries - that are created by two(2) redirect indications results in two(2) - - - -Fajardo, et al. Standards Track [Page 78] - -RFC 6733 Diameter Base Protocol October 2012 - - - cached routes for the same realm and Application Id. However, one - has a redirect usage of ALL_SESSION, where matching requests will be - forwarded to one peer; the other has a redirect usage of ALL_REALM, - where request are forwarded to another peer. Therefore, an incoming - request that matches the realm and Application Id of both routes will - need additional resolution. In such a case, a routing precedence - rule MUST be used against the redirect usage value to resolve the - contention. The precedence rule can be found in Section 6.13. - -6.1.9. Relaying and Proxying Requests - - A relay or proxy agent MUST append a Route-Record AVP to all requests - forwarded. The AVP contains the identity of the peer from which the - request was received. - - The Hop-by-Hop Identifier in the request is saved and replaced with a - locally unique value. The source of the request is also saved, which - includes the IP address, port, and protocol. - - A relay or proxy agent MAY include the Proxy-Info AVP in requests if - it requires access to any local state information when the - corresponding response is received. The Proxy-Info AVP has security - implications as state information is distributed to other entities. - As such, it is RECOMMENDED that the content of the Proxy-Info AVP be - protected with cryptographic mechanisms, for example, by using a - keyed message digest such as HMAC-SHA1 [RFC2104]. Such a mechanism, - however, requires the management of keys, although only locally at - the Diameter server. Still, a full description of the management of - the keys used to protect the Proxy-Info AVP is beyond the scope of - this document. Below is a list of common recommendations: - - o The keys should be generated securely following the randomness - recommendations in [RFC4086]. - - o The keys and cryptographic protection algorithms should be at - least 128 bits in strength. - - o The keys should not be used for any other purpose than generating - and verifying instances of the Proxy-Info AVP. - - o The keys should be changed regularly. - - o The keys should be changed if the AVP format or cryptographic - protection algorithms change. - - The message is then forwarded to the next hop, as identified in the - routing table. - - - - -Fajardo, et al. Standards Track [Page 79] - -RFC 6733 Diameter Base Protocol October 2012 - - - Figure 6 provides an example of message routing using the procedures - listed in these sections. - - (Origin-Host=nas.example.net) (Origin-Host=nas.example.net) - (Origin-Realm=example.net) (Origin-Realm=example.net) - (Destination-Realm=example.com) (Destination-Realm=example.com) - (Route-Record=nas.example.net) - +------+ ------> +------+ ------> +------+ - | | (Request) | | (Request) | | - | NAS +-------------------+ DRL +-------------------+ HMS | - | | | | | | - +------+ <------ +------+ <------ +------+ - example.net (Answer) example.net (Answer) example.com - (Origin-Host=hms.example.com) (Origin-Host=hms.example.com) - (Origin-Realm=example.com) (Origin-Realm=example.com) - - Figure 6: Routing of Diameter messages - - Relay and proxy agents are not required to perform full inspection of - incoming messages. At a minimum, validation of the message header - and relevant routing AVPs has to be done when relaying messages. - Proxy agents may optionally perform more in-depth message validation - for applications in which it is interested. - -6.2. Diameter Answer Processing - - When a request is locally processed, the following procedures MUST be - applied to create the associated answer, in addition to any - additional procedures that MAY be discussed in the Diameter - application defining the command: - - o The same Hop-by-Hop Identifier in the request is used in the - answer. - - o The local host's identity is encoded in the Origin-Host AVP. - - o The Destination-Host and Destination-Realm AVPs MUST NOT be - present in the answer message. - - o The Result-Code AVP is added with its value indicating success or - failure. - - o If the Session-Id is present in the request, it MUST be included - in the answer. - - o Any Proxy-Info AVPs in the request MUST be added to the answer - message, in the same order they were present in the request. - - - - -Fajardo, et al. Standards Track [Page 80] - -RFC 6733 Diameter Base Protocol October 2012 - - - o The 'P' bit is set to the same value as the one in the request. - - o The same End-to-End identifier in the request is used in the - answer. - - Note that the error messages (see Section 7) are also subjected to - the above processing rules. - -6.2.1. Processing Received Answers - - A Diameter client or proxy MUST match the Hop-by-Hop Identifier in an - answer received against the list of pending requests. The - corresponding message should be removed from the list of pending - requests. It SHOULD ignore answers received that do not match a - known Hop-by-Hop Identifier. - -6.2.2. Relaying and Proxying Answers - - If the answer is for a request that was proxied or relayed, the agent - MUST restore the original value of the Diameter header's Hop-by-Hop - Identifier field. - - If the last Proxy-Info AVP in the message is targeted to the local - Diameter server, the AVP MUST be removed before the answer is - forwarded. - - If a relay or proxy agent receives an answer with a Result-Code AVP - indicating a failure, it MUST NOT modify the contents of the AVP. - Any additional local errors detected SHOULD be logged but not - reflected in the Result-Code AVP. If the agent receives an answer - message with a Result-Code AVP indicating success, and it wishes to - modify the AVP to indicate an error, it MUST modify the Result-Code - AVP to contain the appropriate error in the message destined towards - the access device as well as include the Error-Reporting-Host AVP; it - MUST also issue an STR on behalf of the access device towards the - Diameter server. - - The agent MUST then send the answer to the host that it received the - original request from. - -6.3. Origin-Host AVP - - The Origin-Host AVP (AVP Code 264) is of type DiameterIdentity, and - it MUST be present in all Diameter messages. This AVP identifies the - endpoint that originated the Diameter message. Relay agents MUST NOT - modify this AVP. - - - - - -Fajardo, et al. Standards Track [Page 81] - -RFC 6733 Diameter Base Protocol October 2012 - - - The value of the Origin-Host AVP is guaranteed to be unique within a - single host. - - Note that the Origin-Host AVP may resolve to more than one address as - the Diameter peer may support more than one address. - - This AVP SHOULD be placed as close to the Diameter header as - possible. - -6.4. Origin-Realm AVP - - The Origin-Realm AVP (AVP Code 296) is of type DiameterIdentity. - This AVP contains the Realm of the originator of any Diameter message - and MUST be present in all messages. - - This AVP SHOULD be placed as close to the Diameter header as - possible. - -6.5. Destination-Host AVP - - The Destination-Host AVP (AVP Code 293) is of type DiameterIdentity. - This AVP MUST be present in all unsolicited agent initiated messages, - MAY be present in request messages, and MUST NOT be present in answer - messages. - - The absence of the Destination-Host AVP will cause a message to be - sent to any Diameter server supporting the application within the - realm specified in Destination-Realm AVP. - - This AVP SHOULD be placed as close to the Diameter header as - possible. - -6.6. Destination-Realm AVP - - The Destination-Realm AVP (AVP Code 283) is of type DiameterIdentity - and contains the realm to which the message is to be routed. The - Destination-Realm AVP MUST NOT be present in answer messages. - Diameter clients insert the realm portion of the User-Name AVP. - Diameter servers initiating a request message use the value of the - Origin-Realm AVP from a previous message received from the intended - target host (unless it is known a priori). When present, the - Destination-Realm AVP is used to perform message routing decisions. - - The CCF for a request message that includes the Destination-Realm AVP - SHOULD list the Destination-Realm AVP as a required AVP (an AVP - indicated as {AVP}); otherwise, the message is inherently a non- - routable message. - - - - -Fajardo, et al. Standards Track [Page 82] - -RFC 6733 Diameter Base Protocol October 2012 - - - This AVP SHOULD be placed as close to the Diameter header as - possible. - -6.7. Routing AVPs - - The AVPs defined in this section are Diameter AVPs used for routing - purposes. These AVPs change as Diameter messages are processed by - agents. - -6.7.1. Route-Record AVP - - The Route-Record AVP (AVP Code 282) is of type DiameterIdentity. The - identity added in this AVP MUST be the same as the one received in - the Origin-Host of the Capabilities Exchange message. - -6.7.2. Proxy-Info AVP - - The Proxy-Info AVP (AVP Code 284) is of type Grouped. This AVP - contains the identity and local state information of the Diameter - node that creates and adds it to a message. The Grouped Data field - has the following CCF grammar: - - Proxy-Info ::= < AVP Header: 284 > - { Proxy-Host } - { Proxy-State } - * [ AVP ] - -6.7.3. Proxy-Host AVP - - The Proxy-Host AVP (AVP Code 280) is of type DiameterIdentity. This - AVP contains the identity of the host that added the Proxy-Info AVP. - -6.7.4. Proxy-State AVP - - The Proxy-State AVP (AVP Code 33) is of type OctetString. It - contains state information that would otherwise be stored at the - Diameter entity that created it. As such, this AVP MUST be treated - as opaque data by other Diameter entities. - -6.8. Auth-Application-Id AVP - - The Auth-Application-Id AVP (AVP Code 258) is of type Unsigned32 and - is used in order to advertise support of the Authentication and - Authorization portion of an application (see Section 2.4). If - present in a message other than CER and CEA, the value of the Auth- - Application-Id AVP MUST match the Application Id present in the - Diameter message header. - - - - -Fajardo, et al. Standards Track [Page 83] - -RFC 6733 Diameter Base Protocol October 2012 - - -6.9. Acct-Application-Id AVP - - The Acct-Application-Id AVP (AVP Code 259) is of type Unsigned32 and - is used in order to advertise support of the accounting portion of an - application (see Section 2.4). If present in a message other than - CER and CEA, the value of the Acct-Application-Id AVP MUST match the - Application Id present in the Diameter message header. - -6.10. Inband-Security-Id AVP - - The Inband-Security-Id AVP (AVP Code 299) is of type Unsigned32 and - is used in order to advertise support of the security portion of the - application. The use of this AVP in CER and CEA messages is NOT - RECOMMENDED. Instead, discovery of a Diameter entity's security - capabilities can be done either through static configuration or via - Diameter Peer Discovery as described in Section 5.2. - - The following values are supported: - - - NO_INBAND_SECURITY 0 - - This peer does not support TLS/TCP and DTLS/SCTP. This is the - default value, if the AVP is omitted. - - TLS 1 - - This node supports TLS/TCP [RFC5246] and DTLS/SCTP [RFC6083] - security. - -6.11. Vendor-Specific-Application-Id AVP - - The Vendor-Specific-Application-Id AVP (AVP Code 260) is of type - Grouped and is used to advertise support of a vendor-specific - Diameter application. Exactly one instance of either Auth- - Application-Id or Acct-Application-Id AVP MUST be present. The - Application Id carried by either Auth-Application-Id or Acct- - Application-Id AVP MUST comply with vendor-specific Application Id - assignment described in Section 11.3. It MUST also match the - Application Id present in the Diameter header except when used in a - CER or CEA message. - - The Vendor-Id AVP is an informational AVP pertaining to the vendor - who may have authorship of the vendor-specific Diameter application. - It MUST NOT be used as a means of defining a completely separate - vendor-specific Application Id space. - - - - - -Fajardo, et al. Standards Track [Page 84] - -RFC 6733 Diameter Base Protocol October 2012 - - - The Vendor-Specific-Application-Id AVP SHOULD be placed as close to - the Diameter header as possible. - - AVP Format - - <Vendor-Specific-Application-Id> ::= < AVP Header: 260 > - { Vendor-Id } - [ Auth-Application-Id ] - [ Acct-Application-Id ] - - A Vendor-Specific-Application-Id AVP MUST contain exactly one of - either Auth-Application-Id or Acct-Application-Id. If a Vendor- - Specific-Application-Id is received without one of these two AVPs, - then the recipient SHOULD issue an answer with a Result-Code set to - DIAMETER_MISSING_AVP. The answer SHOULD also include a Failed-AVP, - which MUST contain an example of an Auth-Application-Id AVP and an - Acct-Application-Id AVP. - - If a Vendor-Specific-Application-Id is received that contains both - Auth-Application-Id and Acct-Application-Id, then the recipient MUST - issue an answer with Result-Code set to - DIAMETER_AVP_OCCURS_TOO_MANY_TIMES. The answer MUST also include a - Failed-AVP, which MUST contain the received Auth-Application-Id AVP - and Acct-Application-Id AVP. - -6.12. Redirect-Host AVP - - The Redirect-Host AVP (AVP Code 292) is of type DiameterURI. One or - more instances of this AVP MUST be present if the answer message's - 'E' bit is set and the Result-Code AVP is set to - DIAMETER_REDIRECT_INDICATION. - - Upon receiving the above, the receiving Diameter node SHOULD forward - the request directly to one of the hosts identified in these AVPs. - The server contained in the selected Redirect-Host AVP SHOULD be used - for all messages matching the criteria set by the Redirect-Host-Usage - AVP. - -6.13. Redirect-Host-Usage AVP - - The Redirect-Host-Usage AVP (AVP Code 261) is of type Enumerated. - This AVP MAY be present in answer messages whose 'E' bit is set and - the Result-Code AVP is set to DIAMETER_REDIRECT_INDICATION. - - When present, this AVP provides hints about how the routing entry - resulting from the Redirect-Host is to be used. The following values - are supported: - - - - -Fajardo, et al. Standards Track [Page 85] - -RFC 6733 Diameter Base Protocol October 2012 - - - DONT_CACHE 0 - - The host specified in the Redirect-Host AVP SHOULD NOT be cached. - This is the default value. - - ALL_SESSION 1 - - All messages within the same session, as defined by the same value - of the Session-ID AVP SHOULD be sent to the host specified in the - Redirect-Host AVP. - - ALL_REALM 2 - - All messages destined for the realm requested SHOULD be sent to - the host specified in the Redirect-Host AVP. - - REALM_AND_APPLICATION 3 - - All messages for the application requested to the realm specified - SHOULD be sent to the host specified in the Redirect-Host AVP. - - ALL_APPLICATION 4 - - All messages for the application requested SHOULD be sent to the - host specified in the Redirect-Host AVP. - - ALL_HOST 5 - - All messages that would be sent to the host that generated the - Redirect-Host SHOULD be sent to the host specified in the - Redirect-Host AVP. - - ALL_USER 6 - - All messages for the user requested SHOULD be sent to the host - specified in the Redirect-Host AVP. - - When multiple cached routes are created by redirect indications and - they differ only in redirect usage and peers to forward requests to - (see Section 6.1.8), a precedence rule MUST be applied to the - redirect usage values of the cached routes during normal routing to - resolve contentions that may occur. The precedence rule is the order - that dictate which redirect usage should be considered before any - other as they appear. The order is as follows: - - - - - - - -Fajardo, et al. Standards Track [Page 86] - -RFC 6733 Diameter Base Protocol October 2012 - - - 1. ALL_SESSION - - 2. ALL_USER - - 3. REALM_AND_APPLICATION - - 4. ALL_REALM - - 5. ALL_APPLICATION - - 6. ALL_HOST - -6.14. Redirect-Max-Cache-Time AVP - - The Redirect-Max-Cache-Time AVP (AVP Code 262) is of type Unsigned32. - This AVP MUST be present in answer messages whose 'E' bit is set, - whose Result-Code AVP is set to DIAMETER_REDIRECT_INDICATION, and - whose Redirect-Host-Usage AVP set to a non-zero value. - - This AVP contains the maximum number of seconds the peer and route - table entries, created as a result of the Redirect-Host, SHOULD be - cached. Note that once a host is no longer reachable, any associated - cache, peer, and routing table entries MUST be deleted. - -7. Error Handling - - There are two different types of errors in Diameter; protocol errors - and application errors. A protocol error is one that occurs at the - base protocol level and MAY require per-hop attention (e.g., a - message routing error). Application errors, on the other hand, - generally occur due to a problem with a function specified in a - Diameter application (e.g., user authentication, missing AVP). - - Result-Code AVP values that are used to report protocol errors MUST - only be present in answer messages whose 'E' bit is set. When a - request message is received that causes a protocol error, an answer - message is returned with the 'E' bit set, and the Result-Code AVP is - set to the appropriate protocol error value. As the answer is sent - back towards the originator of the request, each proxy or relay agent - MAY take action on the message. - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 87] - -RFC 6733 Diameter Base Protocol October 2012 - - - 1. Request +---------+ Link Broken - +-------------------------->|Diameter |----///----+ - | +---------------------| | v - +------+--+ | 2. answer + 'E' set | Relay 2 | +--------+ - |Diameter |<-+ (Unable to Forward) +---------+ |Diameter| - | | | Home | - | Relay 1 |--+ +---------+ | Server | - +---------+ | 3. Request |Diameter | +--------+ - +-------------------->| | ^ - | Relay 3 |-----------+ - +---------+ - - Figure 7: Example of Protocol Error Causing Answer Message - - Figure 7 provides an example of a message forwarded upstream by a - Diameter relay. When the message is received by Relay 2, and it - detects that it cannot forward the request to the home server, an - answer message is returned with the 'E' bit set and the Result-Code - AVP set to DIAMETER_UNABLE_TO_DELIVER. Given that this error falls - within the protocol error category, Relay 1 would take special - action, and given the error, attempt to route the message through its - alternate Relay 3. - - +---------+ 1. Request +---------+ 2. Request +---------+ - | Access |------------>|Diameter |------------>|Diameter | - | | | | | Home | - | Device |<------------| Relay |<------------| Server | - +---------+ 4. Answer +---------+ 3. Answer +---------+ - (Missing AVP) (Missing AVP) - - Figure 8: Example of Application Error Answer Message - - Figure 8 provides an example of a Diameter message that caused an - application error. When application errors occur, the Diameter - entity reporting the error clears the 'R' bit in the Command Flags - and adds the Result-Code AVP with the proper value. Application - errors do not require any proxy or relay agent involvement; - therefore, the message would be forwarded back to the originator of - the request. - - In the case where the answer message itself contains errors, any - related session SHOULD be terminated by sending an STR or ASR - message. The Termination-Cause AVP in the STR MAY be filled with the - appropriate value to indicate the cause of the error. An application - MAY also send an application-specific request instead of an STR or - ASR message to signal the error in the case where no state is - maintained or to allow for some form of error recovery with the - corresponding Diameter entity. - - - -Fajardo, et al. Standards Track [Page 88] - -RFC 6733 Diameter Base Protocol October 2012 - - - There are certain Result-Code AVP application errors that require - additional AVPs to be present in the answer. In these cases, the - Diameter node that sets the Result-Code AVP to indicate the error - MUST add the AVPs. Examples are as follows: - - o A request with an unrecognized AVP is received with the 'M' bit - (Mandatory bit) set causes an answer to be sent with the Result- - Code AVP set to DIAMETER_AVP_UNSUPPORTED and the Failed-AVP AVP - containing the offending AVP. - - o A request with an AVP that is received with an unrecognized value - causes an answer to be returned with the Result-Code AVP set to - DIAMETER_INVALID_AVP_VALUE, with the Failed-AVP AVP containing the - AVP causing the error. - - o A received command that is missing AVPs that are defined as - required in the commands CCF; examples are AVPs indicated as - {AVP}. The receiver issues an answer with the Result-Code set to - DIAMETER_MISSING_AVP and creates an AVP with the AVP Code and - other fields set as expected in the missing AVP. The created AVP - is then added to the Failed-AVP AVP. - - The Result-Code AVP describes the error that the Diameter node - encountered in its processing. In case there are multiple errors, - the Diameter node MUST report only the first error it encountered - (detected possibly in some implementation-dependent order). The - specific errors that can be described by this AVP are described in - the following section. - -7.1. Result-Code AVP - - The Result-Code AVP (AVP Code 268) is of type Unsigned32 and - indicates whether a particular request was completed successfully or - an error occurred. All Diameter answer messages in IETF-defined - Diameter application specifications MUST include one Result-Code AVP. - A non-successful Result-Code AVP (one containing a non-2xxx value - other than DIAMETER_REDIRECT_INDICATION) MUST include the Error- - Reporting-Host AVP if the host setting the Result-Code AVP is - different from the identity encoded in the Origin-Host AVP. - - The Result-Code data field contains an IANA-managed 32-bit address - space representing errors (see Section 11.3.2). Diameter provides - the following classes of errors, all identified by the thousands - digit in the decimal notation: - - - - - - - -Fajardo, et al. Standards Track [Page 89] - -RFC 6733 Diameter Base Protocol October 2012 - - - o 1xxx (Informational) - - o 2xxx (Success) - - o 3xxx (Protocol Errors) - - o 4xxx (Transient Failures) - - o 5xxx (Permanent Failure) - - An unrecognized class (one whose first digit is not defined in this - section) MUST be handled as a permanent failure. - -7.1.1. Informational - - Errors that fall within this category are used to inform the - requester that a request could not be satisfied, and additional - action is required on its part before access is granted. - - DIAMETER_MULTI_ROUND_AUTH 1001 - - This informational error is returned by a Diameter server to - inform the access device that the authentication mechanism being - used requires multiple round trips, and a subsequent request needs - to be issued in order for access to be granted. - -7.1.2. Success - - Errors that fall within the Success category are used to inform a - peer that a request has been successfully completed. - - DIAMETER_SUCCESS 2001 - - The request was successfully completed. - - DIAMETER_LIMITED_SUCCESS 2002 - - When returned, the request was successfully completed, but - additional processing is required by the application in order to - provide service to the user. - -7.1.3. Protocol Errors - - Errors that fall within the Protocol Error category SHOULD be treated - on a per-hop basis, and Diameter proxies MAY attempt to correct the - error, if it is possible. Note that these errors MUST only be used - in answer messages whose 'E' bit is set. - - - - -Fajardo, et al. Standards Track [Page 90] - -RFC 6733 Diameter Base Protocol October 2012 - - - DIAMETER_COMMAND_UNSUPPORTED 3001 - - This error code is used when a Diameter entity receives a message - with a Command Code that it does not support. - - DIAMETER_UNABLE_TO_DELIVER 3002 - - This error is given when Diameter cannot deliver the message to - the destination, either because no host within the realm - supporting the required application was available to process the - request or because the Destination-Host AVP was given without the - associated Destination-Realm AVP. - - DIAMETER_REALM_NOT_SERVED 3003 - - The intended realm of the request is not recognized. - - DIAMETER_TOO_BUSY 3004 - - When returned, a Diameter node SHOULD attempt to send the message - to an alternate peer. This error MUST only be used when a - specific server is requested, and it cannot provide the requested - service. - - DIAMETER_LOOP_DETECTED 3005 - - An agent detected a loop while trying to get the message to the - intended recipient. The message MAY be sent to an alternate peer, - if one is available, but the peer reporting the error has - identified a configuration problem. - - DIAMETER_REDIRECT_INDICATION 3006 - - A redirect agent has determined that the request could not be - satisfied locally, and the initiator of the request SHOULD direct - the request directly to the server, whose contact information has - been added to the response. When set, the Redirect-Host AVP MUST - be present. - - DIAMETER_APPLICATION_UNSUPPORTED 3007 - - A request was sent for an application that is not supported. - - DIAMETER_INVALID_HDR_BITS 3008 - - A request was received whose bits in the Diameter header were set - either to an invalid combination or to a value that is - inconsistent with the Command Code's definition. - - - -Fajardo, et al. Standards Track [Page 91] - -RFC 6733 Diameter Base Protocol October 2012 - - - DIAMETER_INVALID_AVP_BITS 3009 - - A request was received that included an AVP whose flag bits are - set to an unrecognized value or that is inconsistent with the - AVP's definition. - - DIAMETER_UNKNOWN_PEER 3010 - - A CER was received from an unknown peer. - -7.1.4. Transient Failures - - Errors that fall within the transient failures category are used to - inform a peer that the request could not be satisfied at the time it - was received but MAY be able to satisfy the request in the future. - Note that these errors MUST be used in answer messages whose 'E' bit - is not set. - - DIAMETER_AUTHENTICATION_REJECTED 4001 - - The authentication process for the user failed, most likely due to - an invalid password used by the user. Further attempts MUST only - be tried after prompting the user for a new password. - - DIAMETER_OUT_OF_SPACE 4002 - - A Diameter node received the accounting request but was unable to - commit it to stable storage due to a temporary lack of space. - - ELECTION_LOST 4003 - - The peer has determined that it has lost the election process and - has therefore disconnected the transport connection. - -7.1.5. Permanent Failures - - Errors that fall within the permanent failures category are used to - inform the peer that the request failed and should not be attempted - again. Note that these errors SHOULD be used in answer messages - whose 'E' bit is not set. In error conditions where it is not - possible or efficient to compose application-specific answer grammar, - answer messages with the 'E' bit set and which comply to the grammar - described in Section 7.2 MAY also be used for permanent errors. - - - - - - - - -Fajardo, et al. Standards Track [Page 92] - -RFC 6733 Diameter Base Protocol October 2012 - - - DIAMETER_AVP_UNSUPPORTED 5001 - - The peer received a message that contained an AVP that is not - recognized or supported and was marked with the 'M' (Mandatory) - bit. A Diameter message with this error MUST contain one or more - Failed-AVP AVPs containing the AVPs that caused the failure. - - DIAMETER_UNKNOWN_SESSION_ID 5002 - - The request contained an unknown Session-Id. - - DIAMETER_AUTHORIZATION_REJECTED 5003 - - A request was received for which the user could not be authorized. - This error could occur if the service requested is not permitted - to the user. - - DIAMETER_INVALID_AVP_VALUE 5004 - - The request contained an AVP with an invalid value in its data - portion. A Diameter message indicating this error MUST include - the offending AVPs within a Failed-AVP AVP. - - DIAMETER_MISSING_AVP 5005 - - The request did not contain an AVP that is required by the Command - Code definition. If this value is sent in the Result-Code AVP, a - Failed-AVP AVP SHOULD be included in the message. The Failed-AVP - AVP MUST contain an example of the missing AVP complete with the - Vendor-Id if applicable. The value field of the missing AVP - should be of correct minimum length and contain zeroes. - - DIAMETER_RESOURCES_EXCEEDED 5006 - - A request was received that cannot be authorized because the user - has already expended allowed resources. An example of this error - condition is when a user that is restricted to one dial-up PPP - port attempts to establish a second PPP connection. - - DIAMETER_CONTRADICTING_AVPS 5007 - - The Home Diameter server has detected AVPs in the request that - contradicted each other, and it is not willing to provide service - to the user. The Failed-AVP AVP MUST be present, which contain - the AVPs that contradicted each other. - - - - - - -Fajardo, et al. Standards Track [Page 93] - -RFC 6733 Diameter Base Protocol October 2012 - - - DIAMETER_AVP_NOT_ALLOWED 5008 - - A message was received with an AVP that MUST NOT be present. The - Failed-AVP AVP MUST be included and contain a copy of the - offending AVP. - - DIAMETER_AVP_OCCURS_TOO_MANY_TIMES 5009 - - A message was received that included an AVP that appeared more - often than permitted in the message definition. The Failed-AVP - AVP MUST be included and contain a copy of the first instance of - the offending AVP that exceeded the maximum number of occurrences. - - DIAMETER_NO_COMMON_APPLICATION 5010 - - This error is returned by a Diameter node that receives a CER - whereby no applications are common between the CER sending peer - and the CER receiving peer. - - DIAMETER_UNSUPPORTED_VERSION 5011 - - This error is returned when a request was received, whose version - number is unsupported. - - DIAMETER_UNABLE_TO_COMPLY 5012 - - This error is returned when a request is rejected for unspecified - reasons. - - DIAMETER_INVALID_BIT_IN_HEADER 5013 - - This error is returned when a reserved bit in the Diameter header - is set to one (1) or the bits in the Diameter header are set - incorrectly. - - DIAMETER_INVALID_AVP_LENGTH 5014 - - The request contained an AVP with an invalid length. A Diameter - message indicating this error MUST include the offending AVPs - within a Failed-AVP AVP. In cases where the erroneous AVP length - value exceeds the message length or is less than the minimum AVP - header length, it is sufficient to include the offending AVP - header and a zero filled payload of the minimum required length - for the payloads data type. If the AVP is a Grouped AVP, the - Grouped AVP header with an empty payload would be sufficient to - indicate the offending AVP. In the case where the offending AVP - header cannot be fully decoded when the AVP length is less than - - - - -Fajardo, et al. Standards Track [Page 94] - -RFC 6733 Diameter Base Protocol October 2012 - - - the minimum AVP header length, it is sufficient to include an - offending AVP header that is formulated by padding the incomplete - AVP header with zero up to the minimum AVP header length. - - DIAMETER_INVALID_MESSAGE_LENGTH 5015 - - This error is returned when a request is received with an invalid - message length. - - DIAMETER_INVALID_AVP_BIT_COMBO 5016 - - The request contained an AVP with which is not allowed to have the - given value in the AVP Flags field. A Diameter message indicating - this error MUST include the offending AVPs within a Failed-AVP - AVP. - - DIAMETER_NO_COMMON_SECURITY 5017 - - This error is returned when a CER message is received, and there - are no common security mechanisms supported between the peers. A - Capabilities-Exchange-Answer (CEA) message MUST be returned with - the Result-Code AVP set to DIAMETER_NO_COMMON_SECURITY. - -7.2. Error Bit - - The 'E' (Error Bit) in the Diameter header is set when the request - caused a protocol-related error (see Section 7.1.3). A message with - the 'E' bit MUST NOT be sent as a response to an answer message. - Note that a message with the 'E' bit set is still subjected to the - processing rules defined in Section 6.2. When set, the answer - message will not conform to the CCF specification for the command; - instead, it and will conform to the following CCF: - - Message Format - - <answer-message> ::= < Diameter Header: code, ERR [, PXY] > - 0*1< Session-Id > - { Origin-Host } - { Origin-Realm } - { Result-Code } - [ Origin-State-Id ] - [ Error-Message ] - [ Error-Reporting-Host ] - [ Failed-AVP ] - [ Experimental-Result ] - * [ Proxy-Info ] - * [ AVP ] - - - - -Fajardo, et al. Standards Track [Page 95] - -RFC 6733 Diameter Base Protocol October 2012 - - - Note that the code used in the header is the same than the one found - in the request message, but with the 'R' bit cleared and the 'E' bit - set. The 'P' bit in the header is set to the same value as the one - found in the request message. - -7.3. Error-Message AVP - - The Error-Message AVP (AVP Code 281) is of type UTF8String. It MAY - accompany a Result-Code AVP as a human-readable error message. The - Error-Message AVP is not intended to be useful in an environment - where error messages are processed automatically. It SHOULD NOT be - expected that the content of this AVP be parsed by network entities. - -7.4. Error-Reporting-Host AVP - - The Error-Reporting-Host AVP (AVP Code 294) is of type - DiameterIdentity. This AVP contains the identity of the Diameter - host that sent the Result-Code AVP to a value other than 2001 - (Success), only if the host setting the Result-Code is different from - the one encoded in the Origin-Host AVP. This AVP is intended to be - used for troubleshooting purposes, and it MUST be set when the - Result-Code AVP indicates a failure. - -7.5. Failed-AVP AVP - - The Failed-AVP AVP (AVP Code 279) is of type Grouped and provides - debugging information in cases where a request is rejected or not - fully processed due to erroneous information in a specific AVP. The - value of the Result-Code AVP will provide information on the reason - for the Failed-AVP AVP. A Diameter answer message SHOULD contain an - instance of the Failed-AVP AVP that corresponds to the error - indicated by the Result-Code AVP. For practical purposes, this - Failed-AVP would typically refer to the first AVP processing error - that a Diameter node encounters. - - The possible reasons for this AVP are the presence of an improperly - constructed AVP, an unsupported or unrecognized AVP, an invalid AVP - value, the omission of a required AVP, the presence of an explicitly - excluded AVP (see tables in Section 10) or the presence of two or - more occurrences of an AVP that is restricted to 0, 1, or 0-1 - occurrences. - - A Diameter message SHOULD contain one Failed-AVP AVP, containing the - entire AVP that could not be processed successfully. If the failure - reason is omission of a required AVP, an AVP with the missing AVP - code, the missing Vendor-Id, and a zero-filled payload of the minimum - required length for the omitted AVP will be added. If the failure - reason is an invalid AVP length where the reported length is less - - - -Fajardo, et al. Standards Track [Page 96] - -RFC 6733 Diameter Base Protocol October 2012 - - - than the minimum AVP header length or greater than the reported - message length, a copy of the offending AVP header and a zero-filled - payload of the minimum required length SHOULD be added. - - In the case where the offending AVP is embedded within a Grouped AVP, - the Failed-AVP MAY contain the grouped AVP, which in turn contains - the single offending AVP. The same method MAY be employed if the - grouped AVP itself is embedded in yet another grouped AVP and so on. - In this case, the Failed-AVP MAY contain the grouped AVP hierarchy up - to the single offending AVP. This enables the recipient to detect - the location of the offending AVP when embedded in a group. - - AVP Format - - <Failed-AVP> ::= < AVP Header: 279 > - 1* {AVP} - -7.6. Experimental-Result AVP - - The Experimental-Result AVP (AVP Code 297) is of type Grouped, and - indicates whether a particular vendor-specific request was completed - successfully or whether an error occurred. This AVP has the - following structure: - - AVP Format - - Experimental-Result ::= < AVP Header: 297 > - { Vendor-Id } - { Experimental-Result-Code } - - The Vendor-Id AVP (see Section 5.3.3) in this grouped AVP identifies - the vendor responsible for the assignment of the result code that - follows. All Diameter answer messages defined in vendor-specific - applications MUST include either one Result-Code AVP or one - Experimental-Result AVP. - -7.7. Experimental-Result-Code AVP - - The Experimental-Result-Code AVP (AVP Code 298) is of type Unsigned32 - and contains a vendor-assigned value representing the result of - processing the request. - - It is recommended that vendor-specific result codes follow the same - conventions given for the Result-Code AVP regarding the different - types of result codes and the handling of errors (for non-2xxx - values). - - - - - -Fajardo, et al. Standards Track [Page 97] - -RFC 6733 Diameter Base Protocol October 2012 - - -8. Diameter User Sessions - - In general, Diameter can provide two different types of services to - applications. The first involves authentication and authorization, - and it can optionally make use of accounting. The second only makes - use of accounting. - - When a service makes use of the authentication and/or authorization - portion of an application, and a user requests access to the network, - the Diameter client issues an auth request to its local server. The - auth request is defined in a service-specific Diameter application - (e.g., NASREQ). The request contains a Session-Id AVP, which is used - in subsequent messages (e.g., subsequent authorization, accounting, - etc.) relating to the user's session. The Session-Id AVP is a means - for the client and servers to correlate a Diameter message with a - user session. - - When a Diameter server authorizes a user to implement network - resources for a finite amount of time, and it is willing to extend - the authorization via a future request, it MUST add the - Authorization- Lifetime AVP to the answer message. The - Authorization-Lifetime AVP defines the maximum number of seconds a - user MAY make use of the resources before another authorization - request is expected by the server. The Auth-Grace-Period AVP - contains the number of seconds following the expiration of the - Authorization-Lifetime, after which the server will release all state - information related to the user's session. Note that if payment for - services is expected by the serving realm from the user's home realm, - the Authorization-Lifetime AVP, combined with the Auth-Grace-Period - AVP, implies the maximum length of the session for which the home - realm is willing to be fiscally responsible. Services provided past - the expiration of the Authorization-Lifetime and Auth-Grace-Period - AVPs are the responsibility of the access device. Of course, the - actual cost of services rendered is clearly outside the scope of the - protocol. - - An access device that does not expect to send a re-authorization or a - session termination request to the server MAY include the Auth- - Session-State AVP with the value set to NO_STATE_MAINTAINED as a hint - to the server. If the server accepts the hint, it agrees that since - no session termination message will be received once service to the - user is terminated, it cannot maintain state for the session. If the - answer message from the server contains a different value in the - Auth-Session-State AVP (or the default value if the AVP is absent), - the access device MUST follow the server's directives. Note that the - value NO_STATE_MAINTAINED MUST NOT be set in subsequent re- - authorization requests and answers. - - - - -Fajardo, et al. Standards Track [Page 98] - -RFC 6733 Diameter Base Protocol October 2012 - - - The base protocol does not include any authorization request - messages, since these are largely application-specific and are - defined in a Diameter application document. However, the base - protocol does define a set of messages that are used to terminate - user sessions. These are used to allow servers that maintain state - information to free resources. - - When a service only makes use of the accounting portion of the - Diameter protocol, even in combination with an application, the - Session-Id is still used to identify user sessions. However, the - session termination messages are not used, since a session is - signaled as being terminated by issuing an accounting stop message. - - Diameter may also be used for services that cannot be easily - categorized as authentication, authorization, or accounting (e.g., - certain Third Generation Partnership Project Internet Multimedia - System (3GPP IMS) interfaces). In such cases, the finite state - machine defined in subsequent sections may not be applicable. - Therefore, the application itself MAY need to define its own finite - state machine. However, such application-specific state machines - SHOULD follow the general state machine framework outlined in this - document such as the use of Session-Id AVPs and the use of STR/STA, - ASR/ASA messages for stateful sessions. - -8.1. Authorization Session State Machine - - This section contains a set of finite state machines, which represent - the life cycle of Diameter sessions and which MUST be observed by all - Diameter implementations that make use of the authentication and/or - authorization portion of a Diameter application. The term "Service- - Specific" below refers to a message defined in a Diameter application - (e.g., Mobile IPv4, NASREQ). - - There are four different authorization session state machines - supported in the Diameter base protocol. The first two describe a - session in which the server is maintaining session state, indicated - by the value of the Auth-Session-State AVP (or its absence). One - describes the session from a client perspective, the other from a - server perspective. The second two state machines are used when the - server does not maintain session state. Here again, one describes - the session from a client perspective, the other from a server - perspective. - - When a session is moved to the Idle state, any resources that were - allocated for the particular session must be released. Any event not - listed in the state machines MUST be considered an error condition, - and an answer, if applicable, MUST be returned to the originator of - the message. - - - -Fajardo, et al. Standards Track [Page 99] - -RFC 6733 Diameter Base Protocol October 2012 - - - In the case that an application does not support re-auth, the state - transitions related to server-initiated re-auth, when both client and - server sessions maintain state (e.g., Send RAR, Pending, Receive - RAA), MAY be ignored. - - In the state table, the event "Failure to send X" means that the - Diameter agent is unable to send command X to the desired - destination. This could be due to the peer being down or due to the - peer sending back a transient failure or temporary protocol error - notification DIAMETER_TOO_BUSY or DIAMETER_LOOP_DETECTED in the - Result-Code AVP of the corresponding Answer command. The event 'X - successfully sent' is the complement of 'Failure to send X'. - - The following state machine is observed by a client when state is - maintained on the server: - - CLIENT, STATEFUL - State Event Action New State - --------------------------------------------------------------- - Idle Client or device requests Send Pending - access service- - specific - auth req - - Idle ASR Received Send ASA Idle - for unknown session with - Result-Code = - UNKNOWN_ - SESSION_ID - - Idle RAR Received Send RAA Idle - for unknown session with - Result-Code = - UNKNOWN_ - SESSION_ID - - Pending Successful service-specific Grant Open - authorization answer Access - received with default - Auth-Session-State value - - Pending Successful service-specific Sent STR Discon - authorization answer received, - but service not provided - - Pending Error processing successful Sent STR Discon - service-specific authorization - answer - - - -Fajardo, et al. Standards Track [Page 100] - -RFC 6733 Diameter Base Protocol October 2012 - - - Pending Failed service-specific Clean up Idle - authorization answer received - - Open User or client device Send Open - requests access to service service- - specific - auth req - - Open Successful service-specific Provide Open - authorization answer received service - - Open Failed service-specific Discon. Idle - authorization answer user/device - received. - - Open RAR received and client will Send RAA Open - perform subsequent re-auth with - Result-Code = - SUCCESS - - Open RAR received and client will Send RAA Idle - not perform subsequent with - re-auth Result-Code != - SUCCESS, - Discon. - user/device - - Open Session-Timeout expires on Send STR Discon - access device - - Open ASR received, Send ASA Discon - client will comply with - with request to end the Result-Code = - session = SUCCESS, - Send STR. - - Open ASR Received, Send ASA Open - client will not comply with - with request to end the Result-Code != - session != SUCCESS - - Open Authorization-Lifetime + Send STR Discon - Auth-Grace-Period expires on - access device - - Discon ASR received Send ASA Discon - - - - - -Fajardo, et al. Standards Track [Page 101] - -RFC 6733 Diameter Base Protocol October 2012 - - - Discon STA received Discon. Idle - user/device - - The following state machine is observed by a server when it is - maintaining state for the session: - - SERVER, STATEFUL - State Event Action New State - --------------------------------------------------------------- - Idle Service-specific authorization Send Open - request received, and successful - user is authorized service- - specific - answer - - Idle Service-specific authorization Send Idle - request received, and failed - user is not authorized service- - specific - answer - - Open Service-specific authorization Send Open - request received, and user successful - is authorized service- - specific - answer - - Open Service-specific authorization Send Idle - request received, and user failed - is not authorized service- - specific - answer, - Clean up - - Open Home server wants to confirm Send RAR Pending - authentication and/or - authorization of the user - - Pending Received RAA with a failed Clean up Idle - Result-Code - - Pending Received RAA with Result-Code Update Open - = SUCCESS session - - Open Home server wants to Send ASR Discon - terminate the service - - - - - -Fajardo, et al. Standards Track [Page 102] - -RFC 6733 Diameter Base Protocol October 2012 - - - Open Authorization-Lifetime (and Clean up Idle - Auth-Grace-Period) expires - on home server - - Open Session-Timeout expires on Clean up Idle - home server - - Discon Failure to send ASR Wait, Discon - resend ASR - - Discon ASR successfully sent and Clean up Idle - ASA Received with Result-Code - - Not ASA Received None No Change - Discon - - Any STR Received Send STA, Idle - Clean up - - The following state machine is observed by a client when state is not - maintained on the server: - - CLIENT, STATELESS - State Event Action New State - --------------------------------------------------------------- - Idle Client or device requests Send Pending - access service- - specific - auth req - - Pending Successful service-specific Grant Open - authorization answer access - received with Auth-Session- - State set to - NO_STATE_MAINTAINED - - Pending Failed service-specific Clean up Idle - authorization answer - received - - Open Session-Timeout expires on Discon. Idle - access device user/device - - Open Service to user is terminated Discon. Idle - user/device - - - - - - -Fajardo, et al. Standards Track [Page 103] - -RFC 6733 Diameter Base Protocol October 2012 - - - The following state machine is observed by a server when it is not - maintaining state for the session: - - SERVER, STATELESS - State Event Action New State - --------------------------------------------------------------- - Idle Service-specific authorization Send Idle - request received, and service- - successfully processed specific - answer - -8.2. Accounting Session State Machine - - The following state machines MUST be supported for applications that - have an accounting portion or that require only accounting services. - The first state machine is to be observed by clients. - - See Section 9.7 for Accounting Command Codes and Section 9.8 for - Accounting AVPs. - - The server side in the accounting state machine depends in some cases - on the particular application. The Diameter base protocol defines a - default state machine that MUST be followed by all applications that - have not specified other state machines. This is the second state - machine in this section described below. - - The default server side state machine requires the reception of - accounting records in any order and at any time, and it does not - place any standards requirement on the processing of these records. - Implementations of Diameter may perform checking, ordering, - correlation, fraud detection, and other tasks based on these records. - AVPs may need to be inspected as a part of these tasks. The tasks - can happen either immediately after record reception or in a post- - processing phase. However, as these tasks are typically application - or even policy dependent, they are not standardized by the Diameter - specifications. Applications MAY define requirements on when to - accept accounting records based on the used value of Accounting- - Realtime-Required AVP, credit-limit checks, and so on. - - However, the Diameter base protocol defines one optional server side - state machine that MAY be followed by applications that require - keeping track of the session state at the accounting server. Note - that such tracking is incompatible with the ability to sustain long - duration connectivity problems. Therefore, the use of this state - machine is recommended only in applications where the value of the - Accounting-Realtime-Required AVP is DELIVER_AND_GRANT; hence, - accounting connectivity problems are required to cause the serviced - user to be disconnected. Otherwise, records produced by the client - - - -Fajardo, et al. Standards Track [Page 104] - -RFC 6733 Diameter Base Protocol October 2012 - - - may be lost by the server, which no longer accepts them after the - connectivity is re-established. This state machine is the third - state machine in this section. The state machine is supervised by a - supervision session timer Ts, whose value should be reasonably higher - than the Acct_Interim_Interval value. Ts MAY be set to two times the - value of the Acct_Interim_Interval so as to avoid the accounting - session in the Diameter server to change to Idle state in case of - short transient network failure. - - Any event not listed in the state machines MUST be considered as an - error condition, and a corresponding answer, if applicable, MUST be - returned to the originator of the message. - - In the state table, the event "Failure to send" means that the - Diameter client is unable to communicate with the desired - destination. This could be due to the peer being down, or due to the - peer sending back a transient failure or temporary protocol error - notification DIAMETER_OUT_OF_SPACE, DIAMETER_TOO_BUSY, or - DIAMETER_LOOP_DETECTED in the Result-Code AVP of the Accounting - Answer command. - - The event "Failed answer" means that the Diameter client received a - non-transient failure notification in the Accounting Answer command. - - Note that the action "Disconnect user/dev" MUST also have an effect - on the authorization session state table, e.g., cause the STR message - to be sent, if the given application has both authentication/ - authorization and accounting portions. - - The states PendingS, PendingI, PendingL, PendingE, and PendingB stand - for pending states to wait for an answer to an accounting request - related to a Start, Interim, Stop, Event, or buffered record, - respectively. - - CLIENT, ACCOUNTING - State Event Action New State - --------------------------------------------------------------- - Idle Client or device requests Send PendingS - access accounting - start req. - - Idle Client or device requests Send PendingE - a one-time service accounting - event req - - Idle Records in storage Send PendingB - record - - - - -Fajardo, et al. Standards Track [Page 105] - -RFC 6733 Diameter Base Protocol October 2012 - - - PendingS Successful accounting Open - start answer received - - PendingS Failure to send and buffer Store Open - space available and real time Start - not equal to DELIVER_AND_GRANT Record - - PendingS Failure to send and no buffer Open - space available and real time - equal to GRANT_AND_LOSE - - PendingS Failure to send and no Disconnect Idle - buffer space available and user/dev - real time not equal to - GRANT_AND_LOSE - - PendingS Failed accounting start answer Open - received and real time equal - to GRANT_AND_LOSE - - PendingS Failed accounting start answer Disconnect Idle - received and real time not user/dev - equal to GRANT_AND_LOSE - - PendingS User service terminated Store PendingS - stop - record - - Open Interim interval elapses Send PendingI - accounting - interim - record - - Open User service terminated Send PendingL - accounting - stop req. - - PendingI Successful accounting interim Open - answer received - - PendingI Failure to send and (buffer Store Open - space available or old interim - record can be overwritten) record - and real time not equal to - DELIVER_AND_GRANT - - - - - - -Fajardo, et al. Standards Track [Page 106] - -RFC 6733 Diameter Base Protocol October 2012 - - - PendingI Failure to send and no buffer Open - space available and real time - equal to GRANT_AND_LOSE - - PendingI Failure to send and no Disconnect Idle - buffer space available and user/dev - real time not equal to - GRANT_AND_LOSE - - PendingI Failed accounting interim Open - answer received and real time - equal to GRANT_AND_LOSE - - PendingI Failed accounting interim Disconnect Idle - answer received and user/dev - real time not equal to - GRANT_AND_LOSE - - PendingI User service terminated Store PendingI - stop - record - PendingE Successful accounting Idle - event answer received - - PendingE Failure to send and buffer Store Idle - space available event - record - - PendingE Failure to send and no buffer Idle - space available - - PendingE Failed accounting event answer Idle - received - - PendingB Successful accounting answer Delete Idle - received record - - PendingB Failure to send Idle - - PendingB Failed accounting answer Delete Idle - received record - - PendingL Successful accounting Idle - stop answer received - - PendingL Failure to send and buffer Store Idle - space available stop - record - - - -Fajardo, et al. Standards Track [Page 107] - -RFC 6733 Diameter Base Protocol October 2012 - - - PendingL Failure to send and no buffer Idle - space available - - PendingL Failed accounting stop answer Idle - received - - - SERVER, STATELESS ACCOUNTING - State Event Action New State - --------------------------------------------------------------- - - Idle Accounting start request Send Idle - received and successfully accounting - processed. start - answer - - Idle Accounting event request Send Idle - received and successfully accounting - processed. event - answer - - Idle Interim record received Send Idle - and successfully processed. accounting - interim - answer - - Idle Accounting stop request Send Idle - received and successfully accounting - processed stop answer - - Idle Accounting request received; Send Idle - no space left to store accounting - records answer; - Result-Code = - OUT_OF_ - SPACE - - - - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 108] - -RFC 6733 Diameter Base Protocol October 2012 - - - SERVER, STATEFUL ACCOUNTING - State Event Action New State - --------------------------------------------------------------- - - Idle Accounting start request Send Open - received and successfully accounting - processed. start - answer; - Start Ts - - Idle Accounting event request Send Idle - received and successfully accounting - processed. event - answer - Idle Accounting request received; Send Idle - no space left to store accounting - records answer; - Result-Code = - OUT_OF_ - SPACE - - Open Interim record received Send Open - and successfully processed. accounting - interim - answer; - Restart Ts - - Open Accounting stop request Send Idle - received and successfully accounting - processed stop answer; - Stop Ts - - Open Accounting request received; Send Idle - no space left to store accounting - records answer; - Result-Code = - OUT_OF_ - SPACE; - Stop Ts - - Open Session supervision timer Ts Stop Ts Idle - expired - - - - - - - - - -Fajardo, et al. Standards Track [Page 109] - -RFC 6733 Diameter Base Protocol October 2012 - - -8.3. Server-Initiated Re-Auth - - A Diameter server may initiate a re-authentication and/or re- - authorization service for a particular session by issuing a Re-Auth- - Request (RAR). - - For example, for prepaid services, the Diameter server that - originally authorized a session may need some confirmation that the - user is still using the services. - - An access device that receives an RAR message with the Session-Id - equal to a currently active session MUST initiate a re-auth towards - the user, if the service supports this particular feature. Each - Diameter application MUST state whether server-initiated re-auth is - supported, since some applications do not allow access devices to - prompt the user for re-auth. - -8.3.1. Re-Auth-Request - - The Re-Auth-Request (RAR), indicated by the Command Code set to 258 - and the message flags' 'R' bit set, may be sent by any server to the - access device that is providing session service, to request that the - user be re-authenticated and/or re-authorized. - - - Message Format - - <RAR> ::= < Diameter Header: 258, REQ, PXY > - < Session-Id > - { Origin-Host } - { Origin-Realm } - { Destination-Realm } - { Destination-Host } - { Auth-Application-Id } - { Re-Auth-Request-Type } - [ User-Name ] - [ Origin-State-Id ] - * [ Proxy-Info ] - * [ Route-Record ] - * [ AVP ] - -8.3.2. Re-Auth-Answer - - The Re-Auth-Answer (RAA), indicated by the Command Code set to 258 - and the message flags' 'R' bit clear, is sent in response to the RAR. - The Result-Code AVP MUST be present, and it indicates the disposition - of the request. - - - - -Fajardo, et al. Standards Track [Page 110] - -RFC 6733 Diameter Base Protocol October 2012 - - - A successful RAA message MUST be followed by an application-specific - authentication and/or authorization message. - - Message Format - - <RAA> ::= < Diameter Header: 258, PXY > - < Session-Id > - { Result-Code } - { Origin-Host } - { Origin-Realm } - [ User-Name ] - [ Origin-State-Id ] - [ Error-Message ] - [ Error-Reporting-Host ] - [ Failed-AVP ] - * [ Redirect-Host ] - [ Redirect-Host-Usage ] - [ Redirect-Max-Cache-Time ] - * [ Proxy-Info ] - * [ AVP ] - -8.4. Session Termination - - It is necessary for a Diameter server that authorized a session, for - which it is maintaining state, to be notified when that session is no - longer active, both for tracking purposes as well as to allow - stateful agents to release any resources that they may have provided - for the user's session. For sessions whose state is not being - maintained, this section is not used. - - When a user session that required Diameter authorization terminates, - the access device that provided the service MUST issue a Session- - Termination-Request (STR) message to the Diameter server that - authorized the service, to notify it that the session is no longer - active. An STR MUST be issued when a user session terminates for any - reason, including user logoff, expiration of Session-Timeout, - administrative action, termination upon receipt of an Abort-Session- - Request (see below), orderly shutdown of the access device, etc. - - The access device also MUST issue an STR for a session that was - authorized but never actually started. This could occur, for - example, due to a sudden resource shortage in the access device, or - because the access device is unwilling to provide the type of service - requested in the authorization, or because the access device does not - support a mandatory AVP returned in the authorization, etc. - - It is also possible that a session that was authorized is never - actually started due to action of a proxy. For example, a proxy may - - - -Fajardo, et al. Standards Track [Page 111] - -RFC 6733 Diameter Base Protocol October 2012 - - - modify an authorization answer, converting the result from success to - failure, prior to forwarding the message to the access device. If - the answer did not contain an Auth-Session-State AVP with the value - NO_STATE_MAINTAINED, a proxy that causes an authorized session not to - be started MUST issue an STR to the Diameter server that authorized - the session, since the access device has no way of knowing that the - session had been authorized. - - A Diameter server that receives an STR message MUST clean up - resources (e.g., session state) associated with the Session-Id - specified in the STR and return a Session-Termination-Answer. - - A Diameter server also MUST clean up resources when the Session- - Timeout expires, or when the Authorization-Lifetime and the Auth- - Grace-Period AVPs expire without receipt of a re-authorization - request, regardless of whether an STR for that session is received. - The access device is not expected to provide service beyond the - expiration of these timers; thus, expiration of either of these - timers implies that the access device may have unexpectedly shut - down. - -8.4.1. Session-Termination-Request - - The Session-Termination-Request (STR), indicated by the Command Code - set to 275 and the Command Flags' 'R' bit set, is sent by a Diameter - client or by a Diameter proxy to inform the Diameter server that an - authenticated and/or authorized session is being terminated. - - Message Format - - <STR> ::= < Diameter Header: 275, REQ, PXY > - < Session-Id > - { Origin-Host } - { Origin-Realm } - { Destination-Realm } - { Auth-Application-Id } - { Termination-Cause } - [ User-Name ] - [ Destination-Host ] - * [ Class ] - [ Origin-State-Id ] - * [ Proxy-Info ] - * [ Route-Record ] - * [ AVP ] - - - - - - - -Fajardo, et al. Standards Track [Page 112] - -RFC 6733 Diameter Base Protocol October 2012 - - -8.4.2. Session-Termination-Answer - - The Session-Termination-Answer (STA), indicated by the Command Code - set to 275 and the message flags' 'R' bit clear, is sent by the - Diameter server to acknowledge the notification that the session has - been terminated. The Result-Code AVP MUST be present, and it MAY - contain an indication that an error occurred while servicing the STR. - - Upon sending or receipt of the STA, the Diameter server MUST release - all resources for the session indicated by the Session-Id AVP. Any - intermediate server in the Proxy-Chain MAY also release any - resources, if necessary. - - Message Format - - <STA> ::= < Diameter Header: 275, PXY > - < Session-Id > - { Result-Code } - { Origin-Host } - { Origin-Realm } - [ User-Name ] - * [ Class ] - [ Error-Message ] - [ Error-Reporting-Host ] - [ Failed-AVP ] - [ Origin-State-Id ] - * [ Redirect-Host ] - [ Redirect-Host-Usage ] - [ Redirect-Max-Cache-Time ] - * [ Proxy-Info ] - * [ AVP ] - -8.5. Aborting a Session - - A Diameter server may request that the access device stop providing - service for a particular session by issuing an Abort-Session-Request - (ASR). - - For example, the Diameter server that originally authorized the - session may be required to cause that session to be stopped for lack - of credit or other reasons that were not anticipated when the session - was first authorized. - - An access device that receives an ASR with Session-ID equal to a - currently active session MAY stop the session. Whether the access - device stops the session or not is implementation and/or - configuration dependent. For example, an access device may honor - ASRs from certain agents only. In any case, the access device MUST - - - -Fajardo, et al. Standards Track [Page 113] - -RFC 6733 Diameter Base Protocol October 2012 - - - respond with an Abort-Session-Answer, including a Result-Code AVP to - indicate what action it took. - -8.5.1. Abort-Session-Request - - The Abort-Session-Request (ASR), indicated by the Command Code set to - 274 and the message flags' 'R' bit set, may be sent by any Diameter - server or any Diameter proxy to the access device that is providing - session service, to request that the session identified by the - Session-Id be stopped. - - Message Format - - <ASR> ::= < Diameter Header: 274, REQ, PXY > - < Session-Id > - { Origin-Host } - { Origin-Realm } - { Destination-Realm } - { Destination-Host } - { Auth-Application-Id } - [ User-Name ] - [ Origin-State-Id ] - * [ Proxy-Info ] - * [ Route-Record ] - * [ AVP ] - -8.5.2. Abort-Session-Answer - - The Abort-Session-Answer (ASA), indicated by the Command Code set to - 274 and the message flags' 'R' bit clear, is sent in response to the - ASR. The Result-Code AVP MUST be present and indicates the - disposition of the request. - - If the session identified by Session-Id in the ASR was successfully - terminated, the Result-Code is set to DIAMETER_SUCCESS. If the - session is not currently active, the Result-Code is set to - DIAMETER_UNKNOWN_SESSION_ID. If the access device does not stop the - session for any other reason, the Result-Code is set to - DIAMETER_UNABLE_TO_COMPLY. - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 114] - -RFC 6733 Diameter Base Protocol October 2012 - - - Message Format - - <ASA> ::= < Diameter Header: 274, PXY > - < Session-Id > - { Result-Code } - { Origin-Host } - { Origin-Realm } - [ User-Name ] - [ Origin-State-Id ] - [ Error-Message ] - [ Error-Reporting-Host ] - [ Failed-AVP ] - * [ Redirect-Host ] - [ Redirect-Host-Usage ] - [ Redirect-Max-Cache-Time ] - * [ Proxy-Info ] - * [ AVP ] - -8.6. Inferring Session Termination from Origin-State-Id - - The Origin-State-Id is used to allow detection of terminated sessions - for which no STR would have been issued, due to unanticipated - shutdown of an access device. - - A Diameter client or access device increments the value of the - Origin-State-Id every time it is started or powered up. The new - Origin-State-Id is then sent in the CER/CEA message immediately upon - connection to the server. The Diameter server receiving the new - Origin-State-Id can determine whether the sending Diameter client had - abruptly shut down by comparing the old value of the Origin-State-Id - it has kept for that specific client is less than the new value and - whether it has un-terminated sessions originating from that client. - - An access device can also include the Origin-State-Id in request - messages other than the CER if there are relays or proxies in between - the access device and the server. In this case, however, the server - cannot discover that the access device has been restarted unless and - until it receives a new request from it. Therefore, this mechanism - is more opportunistic across proxies and relays. - - The Diameter server may assume that all sessions that were active - prior to detection of a client restart have been terminated. The - Diameter server MAY clean up all session state associated with such - lost sessions, and it MAY also issue STRs for all such lost sessions - that were authorized on upstream servers, to allow session state to - be cleaned up globally. - - - - - -Fajardo, et al. Standards Track [Page 115] - -RFC 6733 Diameter Base Protocol October 2012 - - -8.7. Auth-Request-Type AVP - - The Auth-Request-Type AVP (AVP Code 274) is of type Enumerated and is - included in application-specific auth requests to inform the peers - whether a user is to be authenticated only, authorized only, or both. - Note any value other than both MAY cause RADIUS interoperability - issues. The following values are defined: - - AUTHENTICATE_ONLY 1 - - The request being sent is for authentication only, and it MUST - contain the relevant application-specific authentication AVPs that - are needed by the Diameter server to authenticate the user. - - AUTHORIZE_ONLY 2 - - The request being sent is for authorization only, and it MUST - contain the application-specific authorization AVPs that are - necessary to identify the service being requested/offered. - - AUTHORIZE_AUTHENTICATE 3 - - The request contains a request for both authentication and - authorization. The request MUST include both the relevant - application-specific authentication information and authorization - information necessary to identify the service being requested/ - offered. - -8.8. Session-Id AVP - - The Session-Id AVP (AVP Code 263) is of type UTF8String and is used - to identify a specific session (see Section 8). All messages - pertaining to a specific session MUST include only one Session-Id - AVP, and the same value MUST be used throughout the life of a - session. When present, the Session-Id SHOULD appear immediately - following the Diameter header (see Section 3). - - The Session-Id MUST be globally and eternally unique, as it is meant - to uniquely identify a user session without reference to any other - information, and it may be needed to correlate historical - authentication information with accounting information. The - Session-Id includes a mandatory portion and an implementation-defined - portion; a recommended format for the implementation-defined portion - is outlined below. - - The Session-Id MUST begin with the sender's identity encoded in the - DiameterIdentity type (see Section 4.3.1). The remainder of the - Session-Id is delimited by a ";" character, and it MAY be any - - - -Fajardo, et al. Standards Track [Page 116] - -RFC 6733 Diameter Base Protocol October 2012 - - - sequence that the client can guarantee to be eternally unique; - however, the following format is recommended, (square brackets [] - indicate an optional element): - - <DiameterIdentity>;<high 32 bits>;<low 32 bits>[;<optional value>] - - <high 32 bits> and <low 32 bits> are decimal representations of the - high and low 32 bits of a monotonically increasing 64-bit value. The - 64-bit value is rendered in two part to simplify formatting by 32-bit - processors. At startup, the high 32 bits of the 64-bit value MAY be - initialized to the time in NTP format [RFC5905], and the low 32 bits - MAY be initialized to zero. This will for practical purposes - eliminate the possibility of overlapping Session-Ids after a reboot, - assuming the reboot process takes longer than a second. - Alternatively, an implementation MAY keep track of the increasing - value in non-volatile memory. - - - <optional value> is implementation specific, but it may include a - modem's device Id, a Layer 2 address, timestamp, etc. - - Example, in which there is no optional value: - - accesspoint7.example.com;1876543210;523 - - Example, in which there is an optional value: - - accesspoint7.example.com;1876543210;523;[email protected] - - The Session-Id is created by the Diameter application initiating the - session, which, in most cases, is done by the client. Note that a - Session-Id MAY be used for both the authentication, authorization, - and accounting commands of a given application. - -8.9. Authorization-Lifetime AVP - - The Authorization-Lifetime AVP (AVP Code 291) is of type Unsigned32 - and contains the maximum number of seconds of service to be provided - to the user before the user is to be re-authenticated and/or re- - authorized. Care should be taken when the Authorization-Lifetime - value is determined, since a low, non-zero value could create - significant Diameter traffic, which could congest both the network - and the agents. - - A value of zero (0) means that immediate re-auth is necessary by the - access device. The absence of this AVP, or a value of all ones - (meaning all bits in the 32-bit field are set to one) means no re- - auth is expected. - - - -Fajardo, et al. Standards Track [Page 117] - -RFC 6733 Diameter Base Protocol October 2012 - - - If both this AVP and the Session-Timeout AVP are present in a - message, the value of the latter MUST NOT be smaller than the - Authorization-Lifetime AVP. - - An Authorization-Lifetime AVP MAY be present in re-authorization - messages, and it contains the number of seconds the user is - authorized to receive service from the time the re-auth answer - message is received by the access device. - - This AVP MAY be provided by the client as a hint of the maximum - lifetime that it is willing to accept. The server MUST return a - value that is equal to, or smaller than, the one provided by the - client. - -8.10. Auth-Grace-Period AVP - - The Auth-Grace-Period AVP (AVP Code 276) is of type Unsigned32 and - contains the number of seconds the Diameter server will wait - following the expiration of the Authorization-Lifetime AVP before - cleaning up resources for the session. - -8.11. Auth-Session-State AVP - - The Auth-Session-State AVP (AVP Code 277) is of type Enumerated and - specifies whether state is maintained for a particular session. The - client MAY include this AVP in requests as a hint to the server, but - the value in the server's answer message is binding. The following - values are supported: - - STATE_MAINTAINED 0 - - This value is used to specify that session state is being - maintained, and the access device MUST issue a session termination - message when service to the user is terminated. This is the - default value. - - NO_STATE_MAINTAINED 1 - - This value is used to specify that no session termination messages - will be sent by the access device upon expiration of the - Authorization-Lifetime. - -8.12. Re-Auth-Request-Type AVP - - The Re-Auth-Request-Type AVP (AVP Code 285) is of type Enumerated and - is included in application-specific auth answers to inform the client - of the action expected upon expiration of the Authorization-Lifetime. - - - - -Fajardo, et al. Standards Track [Page 118] - -RFC 6733 Diameter Base Protocol October 2012 - - - If the answer message contains an Authorization-Lifetime AVP with a - positive value, the Re-Auth-Request-Type AVP MUST be present in an - answer message. The following values are defined: - - AUTHORIZE_ONLY 0 - - An authorization only re-auth is expected upon expiration of the - Authorization-Lifetime. This is the default value if the AVP is - not present in answer messages that include the Authorization- - Lifetime. - - AUTHORIZE_AUTHENTICATE 1 - - An authentication and authorization re-auth is expected upon - expiration of the Authorization-Lifetime. - -8.13. Session-Timeout AVP - - The Session-Timeout AVP (AVP Code 27) [RFC2865] is of type Unsigned32 - and contains the maximum number of seconds of service to be provided - to the user before termination of the session. When both the - Session-Timeout and the Authorization-Lifetime AVPs are present in an - answer message, the former MUST be equal to or greater than the value - of the latter. - - A session that terminates on an access device due to the expiration - of the Session-Timeout MUST cause an STR to be issued, unless both - the access device and the home server had previously agreed that no - session termination messages would be sent (see Section 8). - - A Session-Timeout AVP MAY be present in a re-authorization answer - message, and it contains the remaining number of seconds from the - beginning of the re-auth. - - A value of zero, or the absence of this AVP, means that this session - has an unlimited number of seconds before termination. - - This AVP MAY be provided by the client as a hint of the maximum - timeout that it is willing to accept. However, the server MAY return - a value that is equal to, or smaller than, the one provided by the - client. - -8.14. User-Name AVP - - The User-Name AVP (AVP Code 1) [RFC2865] is of type UTF8String, which - contains the User-Name, in a format consistent with the NAI - specification [RFC4282]. - - - - -Fajardo, et al. Standards Track [Page 119] - -RFC 6733 Diameter Base Protocol October 2012 - - -8.15. Termination-Cause AVP - - The Termination-Cause AVP (AVP Code 295) is of type Enumerated, and - is used to indicate the reason why a session was terminated on the - access device. The currently assigned values for this AVP can be - found in the IANA registry for Termination-Cause AVP Values - [IANATCV]. - -8.16. Origin-State-Id AVP - - The Origin-State-Id AVP (AVP Code 278), of type Unsigned32, is a - monotonically increasing value that is advanced whenever a Diameter - entity restarts with loss of previous state, for example, upon - reboot. Origin-State-Id MAY be included in any Diameter message, - including CER. - - A Diameter entity issuing this AVP MUST create a higher value for - this AVP each time its state is reset. A Diameter entity MAY set - Origin-State-Id to the time of startup, or it MAY use an incrementing - counter retained in non-volatile memory across restarts. - - The Origin-State-Id, if present, MUST reflect the state of the entity - indicated by Origin-Host. If a proxy modifies Origin-Host, it MUST - either remove Origin-State-Id or modify it appropriately as well. - Typically, Origin-State-Id is used by an access device that always - starts up with no active sessions; that is, any session active prior - to restart will have been lost. By including Origin-State-Id in a - message, it allows other Diameter entities to infer that sessions - associated with a lower Origin-State-Id are no longer active. If an - access device does not intend for such inferences to be made, it MUST - either not include Origin-State-Id in any message or set its value to - 0. - -8.17. Session-Binding AVP - - The Session-Binding AVP (AVP Code 270) is of type Unsigned32, and it - MAY be present in application-specific authorization answer messages. - If present, this AVP MAY inform the Diameter client that all future - application-specific re-auth and Session-Termination-Request messages - for this session MUST be sent to the same authorization server. - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 120] - -RFC 6733 Diameter Base Protocol October 2012 - - - This field is a bit mask, and the following bits have been defined: - - RE_AUTH 1 - - When set, future re-auth messages for this session MUST NOT - include the Destination-Host AVP. When cleared, the default - value, the Destination-Host AVP MUST be present in all re-auth - messages for this session. - - STR 2 - - When set, the STR message for this session MUST NOT include the - Destination-Host AVP. When cleared, the default value, the - Destination-Host AVP MUST be present in the STR message for this - session. - - ACCOUNTING 4 - - When set, all accounting messages for this session MUST NOT - include the Destination-Host AVP. When cleared, the default - value, the Destination-Host AVP, if known, MUST be present in all - accounting messages for this session. - -8.18. Session-Server-Failover AVP - - The Session-Server-Failover AVP (AVP Code 271) is of type Enumerated - and MAY be present in application-specific authorization answer - messages that either do not include the Session-Binding AVP or - include the Session-Binding AVP with any of the bits set to a zero - value. If present, this AVP MAY inform the Diameter client that if a - re-auth or STR message fails due to a delivery problem, the Diameter - client SHOULD issue a subsequent message without the Destination-Host - AVP. When absent, the default value is REFUSE_SERVICE. - - The following values are supported: - - REFUSE_SERVICE 0 - - If either the re-auth or the STR message delivery fails, terminate - service with the user and do not attempt any subsequent attempts. - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 121] - -RFC 6733 Diameter Base Protocol October 2012 - - - TRY_AGAIN 1 - - If either the re-auth or the STR message delivery fails, resend - the failed message without the Destination-Host AVP present. - - ALLOW_SERVICE 2 - - If re-auth message delivery fails, assume that re-authorization - succeeded. If STR message delivery fails, terminate the session. - - TRY_AGAIN_ALLOW_SERVICE 3 - - If either the re-auth or the STR message delivery fails, resend - the failed message without the Destination-Host AVP present. If - the second delivery fails for re-auth, assume re-authorization - succeeded. If the second delivery fails for STR, terminate the - session. - -8.19. Multi-Round-Time-Out AVP - - The Multi-Round-Time-Out AVP (AVP Code 272) is of type Unsigned32 and - SHOULD be present in application-specific authorization answer - messages whose Result-Code AVP is set to DIAMETER_MULTI_ROUND_AUTH. - This AVP contains the maximum number of seconds that the access - device MUST provide the user in responding to an authentication - request. - -8.20. Class AVP - - The Class AVP (AVP Code 25) is of type OctetString and is used by - Diameter servers to return state information to the access device. - When one or more Class AVPs are present in application-specific - authorization answer messages, they MUST be present in subsequent re- - authorization, session termination and accounting messages. Class - AVPs found in a re-authorization answer message override the ones - found in any previous authorization answer message. Diameter server - implementations SHOULD NOT return Class AVPs that require more than - 4096 bytes of storage on the Diameter client. A Diameter client that - receives Class AVPs whose size exceeds local available storage MUST - terminate the session. - -8.21. Event-Timestamp AVP - - The Event-Timestamp (AVP Code 55) is of type Time and MAY be included - in an Accounting-Request and Accounting-Answer messages to record the - time that the reported event occurred, in seconds since January 1, - 1900 00:00 UTC. - - - - -Fajardo, et al. Standards Track [Page 122] - -RFC 6733 Diameter Base Protocol October 2012 - - -9. Accounting - - This accounting protocol is based on a server directed model with - capabilities for real-time delivery of accounting information. - Several fault resilience methods [RFC2975] have been built into the - protocol in order minimize loss of accounting data in various fault - situations and under different assumptions about the capabilities of - the used devices. - -9.1. Server Directed Model - - The server directed model means that the device generating the - accounting data gets information from either the authorization server - (if contacted) or the accounting server regarding the way accounting - data shall be forwarded. This information includes accounting record - timeliness requirements. - - As discussed in [RFC2975], real-time transfer of accounting records - is a requirement, such as the need to perform credit-limit checks and - fraud detection. Note that batch accounting is not a requirement, - and is therefore not supported by Diameter. Should batched - accounting be required in the future, a new Diameter application will - need to be created, or it could be handled using another protocol. - Note, however, that even if at the Diameter layer, accounting - requests are processed one by one; transport protocols used under - Diameter typically batch several requests in the same packet under - heavy traffic conditions. This may be sufficient for many - applications. - - The authorization server (chain) directs the selection of proper - transfer strategy, based on its knowledge of the user and - relationships of roaming partnerships. The server (or agents) uses - the Acct-Interim-Interval and Accounting-Realtime-Required AVPs to - control the operation of the Diameter peer operating as a client. - The Acct-Interim-Interval AVP, when present, instructs the Diameter - node acting as a client to produce accounting records continuously - even during a session. Accounting-Realtime-Required AVP is used to - control the behavior of the client when the transfer of accounting - records from the Diameter client is delayed or unsuccessful. - - The Diameter accounting server MAY override the interim interval or - the real-time requirements by including the Acct-Interim-Interval or - Accounting-Realtime-Required AVP in the Accounting-Answer message. - When one of these AVPs is present, the latest value received SHOULD - be used in further accounting activities for the same session. - - - - - - -Fajardo, et al. Standards Track [Page 123] - -RFC 6733 Diameter Base Protocol October 2012 - - -9.2. Protocol Messages - - A Diameter node that receives a successful authentication and/or - authorization message from the Diameter server SHOULD collect - accounting information for the session. The Accounting-Request - message is used to transmit the accounting information to the - Diameter server, which MUST reply with the Accounting-Answer message - to confirm reception. The Accounting-Answer message includes the - Result-Code AVP, which MAY indicate that an error was present in the - accounting message. The value of the Accounting-Realtime-Required - AVP received earlier for the session in question may indicate that - the user's session has to be terminated when a rejected Accounting- - Request message was received. - -9.3. Accounting Application Extension and Requirements - - Each Diameter application (e.g., NASREQ, Mobile IP) SHOULD define its - service-specific AVPs that MUST be present in the Accounting-Request - message in a section titled "Accounting AVPs". The application MUST - assume that the AVPs described in this document will be present in - all Accounting messages, so only their respective service-specific - AVPs need to be defined in that section. - - Applications have the option of using one or both of the following - accounting application extension models: - - Split Accounting Service - - The accounting message will carry the Application Id of the - Diameter base accounting application (see Section 2.4). - Accounting messages may be routed to Diameter nodes other than the - corresponding Diameter application. These nodes might be - centralized accounting servers that provide accounting service for - multiple different Diameter applications. These nodes MUST - advertise the Diameter base accounting Application Id during - capabilities exchange. - - Coupled Accounting Service - - The accounting message will carry the Application Id of the - application that is using it. The application itself will process - the received accounting records or forward them to an accounting - server. There is no accounting application advertisement required - during capabilities exchange, and the accounting messages will be - routed the same way as any of the other application messages. - - In cases where an application does not define its own accounting - service, it is preferred that the split accounting model be used. - - - -Fajardo, et al. Standards Track [Page 124] - -RFC 6733 Diameter Base Protocol October 2012 - - -9.4. Fault Resilience - - Diameter base protocol mechanisms are used to overcome small message - loss and network faults of a temporary nature. - - Diameter peers acting as clients MUST implement the use of failover - to guard against server failures and certain network failures. - Diameter peers acting as agents or related off-line processing - systems MUST detect duplicate accounting records caused by the - sending of the same record to several servers and duplication of - messages in transit. This detection MUST be based on the inspection - of the Session-Id and Accounting-Record-Number AVP pairs. Appendix C - discusses duplicate detection needs and implementation issues. - - Diameter clients MAY have non-volatile memory for the safe storage of - accounting records over reboots or extended network failures, network - partitions, and server failures. If such memory is available, the - client SHOULD store new accounting records there as soon as the - records are created and until a positive acknowledgement of their - reception from the Diameter server has been received. Upon a reboot, - the client MUST start sending the records in the non-volatile memory - to the accounting server with the appropriate modifications in - termination cause, session length, and other relevant information in - the records. - - A further application of this protocol may include AVPs to control - the maximum number of accounting records that may be stored in the - Diameter client without committing them to the non-volatile memory or - transferring them to the Diameter server. - - The client SHOULD NOT remove the accounting data from any of its - memory areas before the correct Accounting-Answer has been received. - The client MAY remove the oldest, undelivered, or as yet - unacknowledged accounting data if it runs out of resources such as - memory. It is an implementation-dependent matter for the client to - accept new sessions under this condition. - -9.5. Accounting Records - - In all accounting records, the Session-Id AVP MUST be present; the - User-Name AVP MUST be present if it is available to the Diameter - client. - - Different types of accounting records are sent depending on the - actual type of accounted service and the authorization server's - directions for interim accounting. If the accounted service is a - - - - - -Fajardo, et al. Standards Track [Page 125] - -RFC 6733 Diameter Base Protocol October 2012 - - - one-time event, meaning that the start and stop of the event are - simultaneous, then the Accounting-Record-Type AVP MUST be present and - set to the value EVENT_RECORD. - - If the accounted service is of a measurable length, then the AVP MUST - use the values START_RECORD, STOP_RECORD, and possibly, - INTERIM_RECORD. If the authorization server has not directed interim - accounting to be enabled for the session, two accounting records MUST - be generated for each service of type session. When the initial - Accounting-Request for a given session is sent, the Accounting- - Record-Type AVP MUST be set to the value START_RECORD. When the last - Accounting-Request is sent, the value MUST be STOP_RECORD. - - If the authorization server has directed interim accounting to be - enabled, the Diameter client MUST produce additional records between - the START_RECORD and STOP_RECORD, marked INTERIM_RECORD. The - production of these records is directed by Acct-Interim-Interval as - well as any re-authentication or re-authorization of the session. - The Diameter client MUST overwrite any previous interim accounting - records that are locally stored for delivery, if a new record is - being generated for the same session. This ensures that only one - pending interim record can exist on an access device for any given - session. - - A particular value of Accounting-Sub-Session-Id MUST appear only in - one sequence of accounting records from a Diameter client, except for - the purposes of retransmission. The one sequence that is sent MUST - be either one record with Accounting-Record-Type AVP set to the value - EVENT_RECORD or several records starting with one having the value - START_RECORD, followed by zero or more INTERIM_RECORDs and a single - STOP_RECORD. A particular Diameter application specification MUST - define the type of sequences that MUST be used. - -9.6. Correlation of Accounting Records - - If an application uses accounting messages, it can correlate - accounting records with a specific application session by using the - Session-Id of the particular application session in the accounting - messages. Accounting messages MAY also use a different Session-Id - from that of the application sessions, in which case, other session- - related information is needed to perform correlation. - - In cases where an application requires multiple accounting sub- - sessions, an Accounting-Sub-Session-Id AVP is used to differentiate - each sub-session. The Session-Id would remain constant for all sub- - sessions and is used to correlate all the sub-sessions to a - particular application session. Note that receiving a STOP_RECORD - - - - -Fajardo, et al. Standards Track [Page 126] - -RFC 6733 Diameter Base Protocol October 2012 - - - with no Accounting-Sub-Session-Id AVP when sub-sessions were - originally used in the START_RECORD messages implies that all sub- - sessions are terminated. - - There are also cases where an application needs to correlate multiple - application sessions into a single accounting record; the accounting - record may span multiple different Diameter applications and sessions - used by the same user at a given time. In such cases, the Acct- - Multi-Session-Id AVP is used. The Acct-Multi-Session-Id AVP SHOULD - be signaled by the server to the access device (typically, during - authorization) when it determines that a request belongs to an - existing session. The access device MUST then include the Acct- - Multi-Session-Id AVP in all subsequent accounting messages. - - The Acct-Multi-Session-Id AVP MAY include the value of the original - Session-Id. Its contents are implementation specific, but the MUST - be globally unique across other Acct-Multi-Session-Ids and MUST NOT - change during the life of a session. - - A Diameter application document MUST define the exact concept of a - session that is being accounted, and it MAY define the concept of a - multi-session. For instance, the NASREQ DIAMETER application treats - a single PPP connection to a Network Access Server as one session and - a set of Multilink PPP sessions as one multi-session. - -9.7. Accounting Command Codes - - This section defines Command Code values that MUST be supported by - all Diameter implementations that provide accounting services. - -9.7.1. Accounting-Request - - The Accounting-Request (ACR) command, indicated by the Command Code - field set to 271 and the Command Flags' 'R' bit set, is sent by a - Diameter node, acting as a client, in order to exchange accounting - information with a peer. - - In addition to the AVPs listed below, Accounting-Request messages - SHOULD include service-specific accounting AVPs. - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 127] - -RFC 6733 Diameter Base Protocol October 2012 - - - Message Format - - <ACR> ::= < Diameter Header: 271, REQ, PXY > - < Session-Id > - { Origin-Host } - { Origin-Realm } - { Destination-Realm } - { Accounting-Record-Type } - { Accounting-Record-Number } - [ Acct-Application-Id ] - [ Vendor-Specific-Application-Id ] - [ User-Name ] - [ Destination-Host ] - [ Accounting-Sub-Session-Id ] - [ Acct-Session-Id ] - [ Acct-Multi-Session-Id ] - [ Acct-Interim-Interval ] - [ Accounting-Realtime-Required ] - [ Origin-State-Id ] - [ Event-Timestamp ] - * [ Proxy-Info ] - * [ Route-Record ] - * [ AVP ] - -9.7.2. Accounting-Answer - - The Accounting-Answer (ACA) command, indicated by the Command Code - field set to 271 and the Command Flags' 'R' bit cleared, is used to - acknowledge an Accounting-Request command. The Accounting-Answer - command contains the same Session-Id as the corresponding request. - - Only the target Diameter server, known as the home Diameter server, - SHOULD respond with the Accounting-Answer command. - - In addition to the AVPs listed below, Accounting-Answer messages - SHOULD include service-specific accounting AVPs. - - - - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 128] - -RFC 6733 Diameter Base Protocol October 2012 - - - Message Format - - <ACA> ::= < Diameter Header: 271, PXY > - < Session-Id > - { Result-Code } - { Origin-Host } - { Origin-Realm } - { Accounting-Record-Type } - { Accounting-Record-Number } - [ Acct-Application-Id ] - [ Vendor-Specific-Application-Id ] - [ User-Name ] - [ Accounting-Sub-Session-Id ] - [ Acct-Session-Id ] - [ Acct-Multi-Session-Id ] - [ Error-Message ] - [ Error-Reporting-Host ] - [ Failed-AVP ] - [ Acct-Interim-Interval ] - [ Accounting-Realtime-Required ] - [ Origin-State-Id ] - [ Event-Timestamp ] - * [ Proxy-Info ] - * [ AVP ] - -9.8. Accounting AVPs - - This section contains AVPs that describe accounting usage information - related to a specific session. - -9.8.1. Accounting-Record-Type AVP - - The Accounting-Record-Type AVP (AVP Code 480) is of type Enumerated - and contains the type of accounting record being sent. The following - values are currently defined for the Accounting-Record-Type AVP: - - EVENT_RECORD 1 - - An Accounting Event Record is used to indicate that a one-time - event has occurred (meaning that the start and end of the event - are simultaneous). This record contains all information relevant - to the service, and it is the only record of the service. - - - - - - - - - -Fajardo, et al. Standards Track [Page 129] - -RFC 6733 Diameter Base Protocol October 2012 - - - START_RECORD 2 - - Accounting Start, Interim, and Stop Records are used to indicate - that a service of a measurable length has been given. An - Accounting Start Record is used to initiate an accounting session - and contains accounting information that is relevant to the - initiation of the session. - - INTERIM_RECORD 3 - - An Interim Accounting Record contains cumulative accounting - information for an existing accounting session. Interim - Accounting Records SHOULD be sent every time a re-authentication - or re-authorization occurs. Further, additional interim record - triggers MAY be defined by application-specific Diameter - applications. The selection of whether to use INTERIM_RECORD - records is done by the Acct-Interim-Interval AVP. - - STOP_RECORD 4 - - An Accounting Stop Record is sent to terminate an accounting - session and contains cumulative accounting information relevant to - the existing session. - -9.8.2. Acct-Interim-Interval AVP - - The Acct-Interim-Interval AVP (AVP Code 85) is of type Unsigned32 and - is sent from the Diameter home authorization server to the Diameter - client. The client uses information in this AVP to decide how and - when to produce accounting records. With different values in this - AVP, service sessions can result in one, two, or two+N accounting - records, based on the needs of the home organization. The following - accounting record production behavior is directed by the inclusion of - this AVP: - - 1. The omission of the Acct-Interim-Interval AVP or its inclusion - with Value field set to 0 means that EVENT_RECORD, START_RECORD, - and STOP_RECORD are produced, as appropriate for the service. - - 2. The inclusion of the AVP with Value field set to a non-zero value - means that INTERIM_RECORD records MUST be produced between the - START_RECORD and STOP_RECORD records. The Value field of this - AVP is the nominal interval between these records in seconds. - The Diameter node that originates the accounting information, - known as the client, MUST produce the first INTERIM_RECORD record - roughly at the time when this nominal interval has elapsed from - - - - - -Fajardo, et al. Standards Track [Page 130] - -RFC 6733 Diameter Base Protocol October 2012 - - - the START_RECORD, the next one again as the interval has elapsed - once more, and so on until the session ends and a STOP_RECORD - record is produced. - - The client MUST ensure that the interim record production times - are randomized so that large accounting message storms are not - created either among records or around a common service start - time. - -9.8.3. Accounting-Record-Number AVP - - The Accounting-Record-Number AVP (AVP Code 485) is of type Unsigned32 - and identifies this record within one session. As Session-Id AVPs - are globally unique, the combination of Session-Id and Accounting- - Record-Number AVPs is also globally unique and can be used in - matching accounting records with confirmations. An easy way to - produce unique numbers is to set the value to 0 for records of type - EVENT_RECORD and START_RECORD and set the value to 1 for the first - INTERIM_RECORD, 2 for the second, and so on until the value for - STOP_RECORD is one more than for the last INTERIM_RECORD. - -9.8.4. Acct-Session-Id AVP - - The Acct-Session-Id AVP (AVP Code 44) is of type OctetString is only - used when RADIUS/Diameter translation occurs. This AVP contains the - contents of the RADIUS Acct-Session-Id attribute. - -9.8.5. Acct-Multi-Session-Id AVP - - The Acct-Multi-Session-Id AVP (AVP Code 50) is of type UTF8String, - following the format specified in Section 8.8. The Acct-Multi- - Session-Id AVP is used to link multiple related accounting sessions, - where each session would have a unique Session-Id but the same Acct- - Multi-Session-Id AVP. This AVP MAY be returned by the Diameter - server in an authorization answer, and it MUST be used in all - accounting messages for the given session. - -9.8.6. Accounting-Sub-Session-Id AVP - - The Accounting-Sub-Session-Id AVP (AVP Code 287) is of type - Unsigned64 and contains the accounting sub-session identifier. The - combination of the Session-Id and this AVP MUST be unique per sub- - session, and the value of this AVP MUST be monotonically increased by - one for all new sub-sessions. The absence of this AVP implies no - sub-sessions are in use, with the exception of an Accounting-Request - whose Accounting-Record-Type is set to STOP_RECORD. A STOP_RECORD - message with no Accounting-Sub-Session-Id AVP present will signal the - termination of all sub-sessions for a given Session-Id. - - - -Fajardo, et al. Standards Track [Page 131] - -RFC 6733 Diameter Base Protocol October 2012 - - -9.8.7. Accounting-Realtime-Required AVP - - The Accounting-Realtime-Required AVP (AVP Code 483) is of type - Enumerated and is sent from the Diameter home authorization server to - the Diameter client or in the Accounting-Answer from the accounting - server. The client uses information in this AVP to decide what to do - if the sending of accounting records to the accounting server has - been temporarily prevented due to, for instance, a network problem. - - DELIVER_AND_GRANT 1 - - The AVP with Value field set to DELIVER_AND_GRANT means that the - service MUST only be granted as long as there is a connection to - an accounting server. Note that the set of alternative accounting - servers are treated as one server in this sense. Having to move - the accounting record stream to a backup server is not a reason to - discontinue the service to the user. - - GRANT_AND_STORE 2 - - The AVP with Value field set to GRANT_AND_STORE means that service - SHOULD be granted if there is a connection, or as long as records - can still be stored as described in Section 9.4. - - This is the default behavior if the AVP isn't included in the - reply from the authorization server. - - GRANT_AND_LOSE 3 - - The AVP with Value field set to GRANT_AND_LOSE means that service - SHOULD be granted even if the records cannot be delivered or - stored. - -10. AVP Occurrence Tables - - The following tables present the AVPs defined in this document and - specify in which Diameter messages they MAY or MAY NOT be present. - AVPs that occur only inside a Grouped AVP are not shown in these - tables. - - The tables use the following symbols: - - 0 The AVP MUST NOT be present in the message. - - 0+ Zero or more instances of the AVP MAY be present in the - message. - - - - - -Fajardo, et al. Standards Track [Page 132] - -RFC 6733 Diameter Base Protocol October 2012 - - - 0-1 Zero or one instance of the AVP MAY be present in the message. - It is considered an error if there are more than one instance - of the AVP. - - 1 One instance of the AVP MUST be present in the message. - - 1+ At least one instance of the AVP MUST be present in the - message. - -10.1. Base Protocol Command AVP Table - - The table in this section is limited to the non-Accounting Command - Codes defined in this specification. - - +-----------------------------------------------+ - | Command Code | - +---+---+---+---+---+---+---+---+---+---+---+---+ - Attribute Name |CER|CEA|DPR|DPA|DWR|DWA|RAR|RAA|ASR|ASA|STR|STA| - --------------------+---+---+---+---+---+---+---+---+---+---+---+---+ - Acct-Interim- |0 |0 |0 |0 |0 |0 |0-1|0 |0 |0 |0 |0 | - Interval | | | | | | | | | | | | | - Accounting-Realtime-|0 |0 |0 |0 |0 |0 |0-1|0 |0 |0 |0 |0 | - Required | | | | | | | | | | | | | - Acct-Application-Id |0+ |0+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Auth-Application-Id |0+ |0+ |0 |0 |0 |0 |1 |0 |1 |0 |1 |0 | - Auth-Grace-Period |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Auth-Request-Type |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Auth-Session-State |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Authorization- |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Lifetime | | | | | | | | | | | | | - Class |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0+ |0+ | - Destination-Host |0 |0 |0 |0 |0 |0 |1 |0 |1 |0 |0-1|0 | - Destination-Realm |0 |0 |0 |0 |0 |0 |1 |0 |1 |0 |1 |0 | - Disconnect-Cause |0 |0 |1 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Error-Message |0 |0-1|0 |0-1|0 |0-1|0 |0-1|0 |0-1|0 |0-1| - Error-Reporting-Host|0 |0 |0 |0 |0 |0 |0 |0-1|0 |0-1|0 |0-1| - Failed-AVP |0 |0-1|0 |0-1|0 |0-1|0 |0-1|0 |0-1|0 |0-1| - Firmware-Revision |0-1|0-1|0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Host-IP-Address |1+ |1+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Inband-Security-Id |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Multi-Round-Time-Out|0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - - - - - - - - - - -Fajardo, et al. Standards Track [Page 133] - -RFC 6733 Diameter Base Protocol October 2012 - - - Origin-Host |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 | - Origin-Realm |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 |1 | - Origin-State-Id |0-1|0-1|0 |0 |0-1|0-1|0-1|0-1|0-1|0-1|0-1|0-1| - Product-Name |1 |1 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Proxy-Info |0 |0 |0 |0 |0 |0 |0+ |0+ |0+ |0+ |0+ |0+ | - Redirect-Host |0 |0 |0 |0 |0 |0 |0 |0+ |0 |0+ |0 |0+ | - Redirect-Host-Usage |0 |0 |0 |0 |0 |0 |0 |0-1|0 |0-1|0 |0-1| - Redirect-Max-Cache- |0 |0 |0 |0 |0 |0 |0 |0-1|0 |0-1|0 |0-1| - Time | | | | | | | | | | | | | - Result-Code |0 |1 |0 |1 |0 |1 |0 |1 |0 |1 |0 |1 | - Re-Auth-Request-Type|0 |0 |0 |0 |0 |0 |1 |0 |0 |0 |0 |0 | - Route-Record |0 |0 |0 |0 |0 |0 |0+ |0 |0+ |0 |0+ |0 | - Session-Binding |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Session-Id |0 |0 |0 |0 |0 |0 |1 |1 |1 |1 |1 |1 | - Session-Server- |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Failover | | | | | | | | | | | | | - Session-Timeout |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Supported-Vendor-Id |0+ |0+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Termination-Cause |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 |1 |0 | - User-Name |0 |0 |0 |0 |0 |0 |0-1|0-1|0-1|0-1|0-1|0-1| - Vendor-Id |1 |1 |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Vendor-Specific- |0+ |0+ |0 |0 |0 |0 |0 |0 |0 |0 |0 |0 | - Application-Id | | | | | | | | | | | | | - --------------------+---+---+---+---+---+---+---+---+---+---+---+---+ - -10.2. Accounting AVP Table - - The table in this section is used to represent which AVPs defined in - this document are to be present in the Accounting messages. These - AVP occurrence requirements are guidelines, which may be expanded, - and/or overridden by application-specific requirements in the - Diameter applications documents. - - - - - - - - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 134] - -RFC 6733 Diameter Base Protocol October 2012 - - - +-----------+ - | Command | - | Code | - +-----+-----+ - Attribute Name | ACR | ACA | - ------------------------------+-----+-----+ - Acct-Interim-Interval | 0-1 | 0-1 | - Acct-Multi-Session-Id | 0-1 | 0-1 | - Accounting-Record-Number | 1 | 1 | - Accounting-Record-Type | 1 | 1 | - Acct-Session-Id | 0-1 | 0-1 | - Accounting-Sub-Session-Id | 0-1 | 0-1 | - Accounting-Realtime-Required | 0-1 | 0-1 | - Acct-Application-Id | 0-1 | 0-1 | - Auth-Application-Id | 0 | 0 | - Class | 0+ | 0+ | - Destination-Host | 0-1 | 0 | - Destination-Realm | 1 | 0 | - Error-Reporting-Host | 0 | 0+ | - Event-Timestamp | 0-1 | 0-1 | - Failed-AVP | 0 | 0-1 | - Origin-Host | 1 | 1 | - Origin-Realm | 1 | 1 | - Proxy-Info | 0+ | 0+ | - Route-Record | 0+ | 0 | - Result-Code | 0 | 1 | - Session-Id | 1 | 1 | - Termination-Cause | 0 | 0 | - User-Name | 0-1 | 0-1 | - Vendor-Specific-Application-Id| 0-1 | 0-1 | - ------------------------------+-----+-----+ - -11. IANA Considerations - - This section provides guidance to the Internet Assigned Numbers - Authority (IANA) regarding registration of values related to the - Diameter protocol, in accordance with [RFC5226]. Existing IANA - registries and assignments put in place by RFC 3588 remain the same - unless explicitly updated or deprecated in this section. - -11.1. AVP Header - - As defined in Section 4, the AVP header contains three fields that - require IANA namespace management: the AVP Code, Vendor-ID, and Flags - fields. - - - - - - -Fajardo, et al. Standards Track [Page 135] - -RFC 6733 Diameter Base Protocol October 2012 - - -11.1.1. AVP Codes - - There are multiple namespaces. Vendors can have their own AVP Codes - namespace that will be identified by their Vendor-ID (also known as - Enterprise-Number), and they control the assignments of their vendor- - specific AVP Codes within their own namespace. The absence of a - Vendor-ID or a Vendor-ID value of zero (0) identifies the IETF AVP - Codes namespace, which is under IANA control. The AVP Codes and - sometimes possible values in an AVP are controlled and maintained by - IANA. AVP Code 0 is not used. AVP Codes 1-255 are managed - separately as RADIUS Attribute Types. Where a Vendor-Specific AVP is - implemented by more than one vendor, allocation of global AVPs should - be encouraged instead. - - AVPs may be allocated following Expert Review (by a Designated - Expert) with Specification Required [RFC5226]. A block allocation - (release of more than three AVPs at a time for a given purpose) - requires IETF Review [RFC5226]. - -11.1.2. AVP Flags - - Section 4.1 describes the existing AVP Flags. The remaining bits can - only be assigned via a Standards Action [RFC5226]. - -11.2. Diameter Header - -11.2.1. Command Codes - - For the Diameter header, the Command Code namespace allocation has - changed. The new allocation rules are as follows: - - The Command Code values 256 - 8,388,607 (0x100 to 0x7fffff) are - for permanent, standard commands, allocated by IETF Review - [RFC5226]. - - The values 8,388,608 - 16,777,213 (0x800000 - 0xfffffd) are - reserved for vendor-specific Command Codes, to be allocated on a - First Come, First Served basis by IANA [RFC5226]. The request to - IANA for a Vendor-Specific Command Code SHOULD include a reference - to a publicly available specification that documents the command - in sufficient detail to aid in interoperability between - independent implementations. If the specification cannot be made - publicly available, the request for a vendor-specific Command Code - MUST include the contact information of persons and/or entities - responsible for authoring and maintaining the command. - - - - - - -Fajardo, et al. Standards Track [Page 136] - -RFC 6733 Diameter Base Protocol October 2012 - - - The values 16,777,214 and 16,777,215 (hexadecimal values 0xfffffe - - 0xffffff) are reserved for experimental commands. As these - codes are only for experimental and testing purposes, no guarantee - is made for interoperability between Diameter peers using - experimental commands. - -11.2.2. Command Flags - - Section 3 describes the existing Command Flags field. The remaining - bits can only be assigned via a Standards Action [RFC5226]. - -11.3. AVP Values - - For AVP values, the Experimental-Result-Code AVP value allocation has - been added; see Section 11.3.1. The old AVP value allocation rule, - IETF Consensus, has been updated to IETF Review as per [RFC5226], and - affected AVPs are listed as reminders. - -11.3.1. Experimental-Result-Code AVP - - Values for this AVP are purely local to the indicated vendor, and no - IANA registry is maintained for them. - -11.3.2. Result-Code AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.3. Accounting-Record-Type AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.4. Termination-Cause AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.5. Redirect-Host-Usage AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.6. Session-Server-Failover AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.7. Session-Binding AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - - - - - -Fajardo, et al. Standards Track [Page 137] - -RFC 6733 Diameter Base Protocol October 2012 - - -11.3.8. Disconnect-Cause AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.9. Auth-Request-Type AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.10. Auth-Session-State AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.11. Re-Auth-Request-Type AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.12. Accounting-Realtime-Required AVP Values - - New values are available for assignment via IETF Review [RFC5226]. - -11.3.13. Inband-Security-Id AVP (code 299) - - The use of this AVP has been deprecated. - -11.4. _diameters Service Name and Port Number Registration - - IANA has registered the "_diameters" service name and assigned port - numbers for TLS/TCP and DTLS/SCTP according to the guidelines given - in [RFC6335]. - - Service Name: _diameters - - Transport Protocols: TCP, SCTP - - Assignee: IESG <[email protected]> - - Contact: IETF Chair <[email protected]> - - Description: Diameter over TLS/TCP and DTLS/SCTP - - Reference: RFC 6733 - - Port Number: 5868, from the User Range - - - - - - - - -Fajardo, et al. Standards Track [Page 138] - -RFC 6733 Diameter Base Protocol October 2012 - - -11.5. SCTP Payload Protocol Identifiers - - Two SCTP payload protocol identifiers have been registered in the - SCTP Payload Protocol Identifiers registry: - - - Value | SCTP Payload Protocol Identifier - -------|----------------------------------- - 46 | Diameter in a SCTP DATA chunk - 47 | Diameter in a DTLS/SCTP DATA chunk - - -11.6. S-NAPTR Parameters - - The following tag has been registered in the S-NAPTR Application - Protocol Tags registry: - - Tag | Protocol - -------------------|--------- - diameter.dtls.sctp | DTLS/SCTP - -12. Diameter Protocol-Related Configurable Parameters - - This section contains the configurable parameters that are found - throughout this document: - - Diameter Peer - - A Diameter entity MAY communicate with peers that are statically - configured. A statically configured Diameter peer would require - that either the IP address or the fully qualified domain name - (FQDN) be supplied, which would then be used to resolve through - DNS. - - Routing Table - - A Diameter proxy server routes messages based on the realm portion - of a Network Access Identifier (NAI). The server MUST have a - table of Realm Names, and the address of the peer to which the - message must be forwarded. The routing table MAY also include a - "default route", which is typically used for all messages that - cannot be locally processed. - - Tc timer - - The Tc timer controls the frequency that transport connection - attempts are done to a peer with whom no active transport - connection exists. The recommended value is 30 seconds. - - - -Fajardo, et al. Standards Track [Page 139] - -RFC 6733 Diameter Base Protocol October 2012 - - -13. Security Considerations - - The Diameter base protocol messages SHOULD be secured by using TLS - [RFC5246] or DTLS/SCTP [RFC6083]. Additional security mechanisms - such as IPsec [RFC4301] MAY also be deployed to secure connections - between peers. However, all Diameter base protocol implementations - MUST support the use of TLS/TCP and DTLS/SCTP, and the Diameter - protocol MUST NOT be used without one of TLS, DTLS, or IPsec. - - If a Diameter connection is to be protected via TLS/TCP and DTLS/SCTP - or IPsec, then TLS/TCP and DTLS/SCTP or IPsec/IKE SHOULD begin prior - to any Diameter message exchange. All security parameters for TLS/ - TCP and DTLS/SCTP or IPsec are configured independent of the Diameter - protocol. All Diameter messages will be sent through the TLS/TCP and - DTLS/SCTP or IPsec connection after a successful setup. - - For TLS/TCP and DTLS/SCTP connections to be established in the open - state, the CER/CEA exchange MUST include an Inband-Security-ID AVP - with a value of TLS/TCP and DTLS/SCTP. The TLS/TCP and DTLS/SCTP - handshake will begin when both ends successfully reach the open - state, after completion of the CER/CEA exchange. If the TLS/TCP and - DTLS/SCTP handshake is successful, all further messages will be sent - via TLS/TCP and DTLS/SCTP. If the handshake fails, both ends MUST - move to the closed state. See Section 13.1 for more details. - -13.1. TLS/TCP and DTLS/SCTP Usage - - Diameter nodes using TLS/TCP and DTLS/SCTP for security MUST mutually - authenticate as part of TLS/TCP and DTLS/SCTP session establishment. - In order to ensure mutual authentication, the Diameter node acting as - the TLS/TCP and DTLS/SCTP server MUST request a certificate from the - Diameter node acting as TLS/TCP and DTLS/SCTP client, and the - Diameter node acting as the TLS/TCP and DTLS/SCTP client MUST be - prepared to supply a certificate on request. - - Diameter nodes MUST be able to negotiate the following TLS/TCP and - DTLS/SCTP cipher suites: - - TLS_RSA_WITH_RC4_128_MD5 - TLS_RSA_WITH_RC4_128_SHA - TLS_RSA_WITH_3DES_EDE_CBC_SHA - - Diameter nodes SHOULD be able to negotiate the following TLS/TCP and - DTLS/SCTP cipher suite: - - TLS_RSA_WITH_AES_128_CBC_SHA - - - - - -Fajardo, et al. Standards Track [Page 140] - -RFC 6733 Diameter Base Protocol October 2012 - - - Note that it is quite possible that support for the - TLS_RSA_WITH_AES_128_CBC_SHA cipher suite will be REQUIRED at some - future date. Diameter nodes MAY negotiate other TLS/TCP and DTLS/ - SCTP cipher suites. - - If public key certificates are used for Diameter security (for - example, with TLS), the value of the expiration times in the routing - and peer tables MUST NOT be greater than the expiry time in the - relevant certificates. - -13.2. Peer-to-Peer Considerations - - As with any peer-to-peer protocol, proper configuration of the trust - model within a Diameter peer is essential to security. When - certificates are used, it is necessary to configure the root - certificate authorities trusted by the Diameter peer. These root CAs - are likely to be unique to Diameter usage and distinct from the root - CAs that might be trusted for other purposes such as Web browsing. - In general, it is expected that those root CAs will be configured so - as to reflect the business relationships between the organization - hosting the Diameter peer and other organizations. As a result, a - Diameter peer will typically not be configured to allow connectivity - with any arbitrary peer. With certificate authentication, Diameter - peers may not be known beforehand and therefore peer discovery may be - required. - -13.3. AVP Considerations - - Diameter AVPs often contain security-sensitive data; for example, - user passwords and location data, network addresses and cryptographic - keys. The following AVPs defined in this document are considered to - be security-sensitive: - - o Acct-Interim-Interval - - o Accounting-Realtime-Required - - o Acct-Multi-Session-Id - - o Accounting-Record-Number - - o Accounting-Record-Type - - o Accounting-Session-Id - - o Accounting-Sub-Session-Id - - o Class - - - -Fajardo, et al. Standards Track [Page 141] - -RFC 6733 Diameter Base Protocol October 2012 - - - o Session-Id - - o Session-Binding - - o Session-Server-Failover - - o User-Name - - Diameter messages containing these or any other AVPs considered to be - security-sensitive MUST only be sent protected via mutually - authenticated TLS or IPsec. In addition, those messages MUST NOT be - sent via intermediate nodes unless there is end-to-end security - between the originator and recipient or the originator has locally - trusted configuration that indicates that end-to-end security is not - needed. For example, end-to-end security may not be required in the - case where an intermediary node is known to be operated as part of - the same administrative domain as the endpoints so that an ability to - successfully compromise the intermediary would imply a high - probability of being able to compromise the endpoints as well. Note - that no end-to-end security mechanism is specified in this document. - -14. References - -14.1. Normative References - - [FLOATPOINT] - Institute of Electrical and Electronics Engineers, "IEEE - Standard for Binary Floating-Point Arithmetic, ANSI/IEEE - Standard 754-1985", August 1985. - - [IANAADFAM] - IANA, "Address Family Numbers", - <http://www.iana.org/assignments/address-family-numbers>. - - [RFC0791] Postel, J., "Internet Protocol", STD 5, RFC 791, - September 1981. - - [RFC0793] Postel, J., "Transmission Control Protocol", STD 7, - RFC 793, September 1981. - - [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate - Requirement Levels", BCP 14, RFC 2119, March 1997. - - [RFC3492] Costello, A., "Punycode: A Bootstring encoding of Unicode - for Internationalized Domain Names in Applications - (IDNA)", RFC 3492, March 2003. - - - - - -Fajardo, et al. Standards Track [Page 142] - -RFC 6733 Diameter Base Protocol October 2012 - - - [RFC3539] Aboba, B. and J. Wood, "Authentication, Authorization and - Accounting (AAA) Transport Profile", RFC 3539, June 2003. - - [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO - 10646", STD 63, RFC 3629, November 2003. - - [RFC3958] Daigle, L. and A. Newton, "Domain-Based Application - Service Location Using SRV RRs and the Dynamic Delegation - Discovery Service (DDDS)", RFC 3958, January 2005. - - [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform - Resource Identifier (URI): Generic Syntax", STD 66, - RFC 3986, January 2005. - - [RFC4004] Calhoun, P., Johansson, T., Perkins, C., Hiller, T., and - P. McCann, "Diameter Mobile IPv4 Application", RFC 4004, - August 2005. - - [RFC4005] Calhoun, P., Zorn, G., Spence, D., and D. Mitton, - "Diameter Network Access Server Application", RFC 4005, - August 2005. - - [RFC4006] Hakala, H., Mattila, L., Koskinen, J-P., Stura, M., and J. - Loughney, "Diameter Credit-Control Application", RFC 4006, - August 2005. - - [RFC4086] Eastlake, D., Schiller, J., and S. Crocker, "Randomness - Requirements for Security", BCP 106, RFC 4086, June 2005. - - [RFC4282] Aboba, B., Beadles, M., Arkko, J., and P. Eronen, "The - Network Access Identifier", RFC 4282, December 2005. - - [RFC4291] Hinden, R. and S. Deering, "IP Version 6 Addressing - Architecture", RFC 4291, February 2006. - - [RFC4960] Stewart, R., "Stream Control Transmission Protocol", - RFC 4960, September 2007. - - [RFC5226] Narten, T. and H. Alvestrand, "Guidelines for Writing an - IANA Considerations Section in RFCs", BCP 26, RFC 5226, - May 2008. - - [RFC5234] Crocker, D. and P. Overell, "Augmented BNF for Syntax - Specifications: ABNF", STD 68, RFC 5234, January 2008. - - [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security - (TLS) Protocol Version 1.2", RFC 5246, August 2008. - - - - -Fajardo, et al. Standards Track [Page 143] - -RFC 6733 Diameter Base Protocol October 2012 - - - [RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S., - Housley, R., and W. Polk, "Internet X.509 Public Key - Infrastructure Certificate and Certificate Revocation List - (CRL) Profile", RFC 5280, May 2008. - - [RFC5729] Korhonen, J., Jones, M., Morand, L., and T. Tsou, - "Clarifications on the Routing of Diameter Requests Based - on the Username and the Realm", RFC 5729, December 2009. - - [RFC5890] Klensin, J., "Internationalized Domain Names for - Applications (IDNA): Definitions and Document Framework", - RFC 5890, August 2010. - - [RFC5891] Klensin, J., "Internationalized Domain Names in - Applications (IDNA): Protocol", RFC 5891, August 2010. - - [RFC6083] Tuexen, M., Seggelmann, R., and E. Rescorla, "Datagram - Transport Layer Security (DTLS) for Stream Control - Transmission Protocol (SCTP)", RFC 6083, January 2011. - - [RFC6347] Rescorla, E. and N. Modadugu, "Datagram Transport Layer - Security Version 1.2", RFC 6347, January 2012. - - [RFC6408] Jones, M., Korhonen, J., and L. Morand, "Diameter - Straightforward-Naming Authority Pointer (S-NAPTR) Usage", - RFC 6408, November 2011. - -14.2. Informative References - - [ENTERPRISE] IANA, "SMI Network Management Private Enterprise - Codes", - <http://www.iana.org/assignments/enterprise-numbers>. - - [IANATCV] IANA, "Termination-Cause AVP Values (code 295)", - <http://www.iana.org/assignments/aaa-parameters/ - aaa-parameters.xml#aaa-parameters-16>. - - [RFC1492] Finseth, C., "An Access Control Protocol, Sometimes - Called TACACS", RFC 1492, July 1993. - - [RFC1661] Simpson, W., "The Point-to-Point Protocol (PPP)", - STD 51, RFC 1661, July 1994. - - [RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: - Keyed-Hashing for Message Authentication", RFC 2104, - February 1997. - - - - - -Fajardo, et al. Standards Track [Page 144] - -RFC 6733 Diameter Base Protocol October 2012 - - - [RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR - for specifying the location of services (DNS SRV)", - RFC 2782, February 2000. - - [RFC2865] Rigney, C., Willens, S., Rubens, A., and W. Simpson, - "Remote Authentication Dial In User Service (RADIUS)", - RFC 2865, June 2000. - - [RFC2866] Rigney, C., "RADIUS Accounting", RFC 2866, June 2000. - - [RFC2869] Rigney, C., Willats, W., and P. Calhoun, "RADIUS - Extensions", RFC 2869, June 2000. - - [RFC2881] Mitton, D. and M. Beadles, "Network Access Server - Requirements Next Generation (NASREQNG) NAS Model", - RFC 2881, July 2000. - - [RFC2975] Aboba, B., Arkko, J., and D. Harrington, "Introduction - to Accounting Management", RFC 2975, October 2000. - - [RFC2989] Aboba, B., Calhoun, P., Glass, S., Hiller, T., McCann, - P., Shiino, H., Walsh, P., Zorn, G., Dommety, G., - Perkins, C., Patil, B., Mitton, D., Manning, S., - Beadles, M., Chen, X., Sivalingham, S., Hameed, A., - Munson, M., Jacobs, S., Lim, B., Hirschman, B., Hsu, - R., Koo, H., Lipford, M., Campbell, E., Xu, Y., Baba, - S., and E. Jaques, "Criteria for Evaluating AAA - Protocols for Network Access", RFC 2989, November 2000. - - [RFC3162] Aboba, B., Zorn, G., and D. Mitton, "RADIUS and IPv6", - RFC 3162, August 2001. - - [RFC3748] Aboba, B., Blunk, L., Vollbrecht, J., Carlson, J., and - H. Levkowetz, "Extensible Authentication Protocol - (EAP)", RFC 3748, June 2004. - - [RFC4301] Kent, S. and K. Seo, "Security Architecture for the - Internet Protocol", RFC 4301, December 2005. - - [RFC4690] Klensin, J., Faltstrom, P., Karp, C., and IAB, "Review - and Recommendations for Internationalized Domain Names - (IDNs)", RFC 4690, September 2006. - - [RFC5176] Chiba, M., Dommety, G., Eklund, M., Mitton, D., and B. - Aboba, "Dynamic Authorization Extensions to Remote - Authentication Dial In User Service (RADIUS)", - RFC 5176, January 2008. - - - - -Fajardo, et al. Standards Track [Page 145] - -RFC 6733 Diameter Base Protocol October 2012 - - - [RFC5461] Gont, F., "TCP's Reaction to Soft Errors", RFC 5461, - February 2009. - - [RFC5905] Mills, D., Martin, J., Burbank, J., and W. Kasch, - "Network Time Protocol Version 4: Protocol and - Algorithms Specification", RFC 5905, June 2010. - - [RFC5927] Gont, F., "ICMP Attacks against TCP", RFC 5927, - July 2010. - - [RFC6335] Cotton, M., Eggert, L., Touch, J., Westerlund, M., and - S. Cheshire, "Internet Assigned Numbers Authority - (IANA) Procedures for the Management of the Service - Name and Transport Protocol Port Number Registry", - BCP 165, RFC 6335, August 2011. - - [RFC6737] Kang, J. and G. Zorn, "The Diameter Capabilities Update - Application", RFC 6737, October 2012. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Fajardo, et al. Standards Track [Page 146] - -RFC 6733 Diameter Base Protocol October 2012 - - -Appendix A. Acknowledgements - -A.1. This Document - - The authors would like to thank the following people that have - provided proposals and contributions to this document: - - To Vishnu Ram and Satendra Gera for their contributions on - capabilities updates, predictive loop avoidance, as well as many - other technical proposals. To Tolga Asveren for his insights and - contributions on almost all of the proposed solutions incorporated - into this document. To Timothy Smith for helping on the capabilities - Update and other topics. To Tony Zhang for providing fixes to - loopholes on composing Failed-AVPs as well as many other issues and - topics. To Jan Nordqvist for clearly stating the usage of - Application Ids. To Anders Kristensen for providing needed technical - opinions. To David Frascone for providing invaluable review of the - document. To Mark Jones for providing clarifying text on vendor - command codes and other vendor-specific indicators. To Victor - Pascual and Sebastien Decugis for new text and recommendations on - SCTP/DTLS. To Jouni Korhonen for taking over the editing task and - resolving last bits from versions 27 through 29. - - Special thanks to the Diameter extensibility design team, which - helped resolve the tricky question of mandatory AVPs and ABNF - semantics. The members of this team are as follows: - - Avi Lior, Jari Arkko, Glen Zorn, Lionel Morand, Mark Jones, Tolga - Asveren, Jouni Korhonen, and Glenn McGregor. - - Special thanks also to people who have provided invaluable comments - and inputs especially in resolving controversial issues: - - Glen Zorn, Yoshihiro Ohba, Marco Stura, Stephen Farrel, Pete Resnick, - Peter Saint-Andre, Robert Sparks, Krishna Prasad, Sean Turner, Barry - Leiba, and Pasi Eronen. - - Finally, we would like to thank the original authors of this - document: - - Pat Calhoun, John Loughney, Jari Arkko, Erik Guttman, and Glen Zorn. - - Their invaluable knowledge and experience has given us a robust and - flexible AAA protocol that many people have seen great value in - adopting. We greatly appreciate their support and stewardship for - the continued improvements of Diameter as a protocol. We would also - like to extend our gratitude to folks aside from the authors who have - - - - -Fajardo, et al. Standards Track [Page 147] - -RFC 6733 Diameter Base Protocol October 2012 - - - assisted and contributed to the original version of this document. - Their efforts significantly contributed to the success of Diameter. - -A.2. RFC 3588 - - The authors would like to thank Nenad Trifunovic, Tony Johansson and - Pankaj Patel for their participation in the pre-IETF Document Reading - Party. Allison Mankin, Jonathan Wood, and Bernard Aboba provided - invaluable assistance in working out transport issues and this was - also the case with Steven Bellovin in the security area. - - Paul Funk and David Mitton were instrumental in getting the Peer - State Machine correct, and our deep thanks go to them for their time. - - Text in this document was also provided by Paul Funk, Mark Eklund, - Mark Jones, and Dave Spence. Jacques Caron provided many great - comments as a result of a thorough review of the spec. - - The authors would also like to acknowledge the following people for - their contribution in the development of the Diameter protocol: - - Allan C. Rubens, Haseeb Akhtar, William Bulley, Stephen Farrell, - David Frascone, Daniel C. Fox, Lol Grant, Ignacio Goyret, Nancy - Greene, Peter Heitman, Fredrik Johansson, Mark Jones, Martin Julien, - Bob Kopacz, Paul Krumviede, Fergal Ladley, Ryan Moats, Victor Muslin, - Kenneth Peirce, John Schnizlein, Sumit Vakil, John R. Vollbrecht, and - Jeff Weisberg. - - Finally, Pat Calhoun would like to thank Sun Microsystems since most - of the effort put into this document was done while he was in their - employ. - -Appendix B. S-NAPTR Example - - As an example, consider a client that wishes to resolve aaa: - ex1.example.com. The client performs a NAPTR query for that domain, - and the following NAPTR records are returned: - - ;; order pref flags service regexp replacement - IN NAPTR 50 50 "s" "aaa:diameter.tls.tcp" "" - _diameter._tls.ex1.example.com - IN NAPTR 100 50 "s" "aaa:diameter.tcp" "" - _aaa._tcp.ex1.example.com - IN NAPTR 150 50 "s" "aaa:diameter.sctp" "" - _diameter._sctp.ex1.example.com - - This indicates that the server supports TLS, TCP, and SCTP in that - order. If the client supports TLS, TLS will be used, targeted to a - - - -Fajardo, et al. Standards Track [Page 148] - -RFC 6733 Diameter Base Protocol October 2012 - - - host determined by an SRV lookup of _diameter._tls.ex1.example.com. - That lookup would return: - - ;; Priority Weight Port Target - IN SRV 0 1 5060 server1.ex1.example.com - IN SRV 0 2 5060 server2.ex1.example.com - - As an alternative example, a client that wishes to resolve aaa: - ex2.example.com. The client performs a NAPTR query for that domain, - and the following NAPTR records are returned: - - ;; order pref flags service regexp replacement - IN NAPTR 150 50 "a" "aaa:diameter.tls.tcp" "" - server1.ex2.example.com - IN NAPTR 150 50 "a" "aaa:diameter.tls.tcp" "" - server2.ex2.example.com - - This indicates that the server supports TCP available at the returned - host names. - -Appendix C. Duplicate Detection - - As described in Section 9.4, accounting record duplicate detection is - based on session identifiers. Duplicates can appear for various - reasons: - - o Failover to an alternate server. Where close to real-time - performance is required, failover thresholds need to be kept low. - This may lead to an increased likelihood of duplicates. Failover - can occur at the client or within Diameter agents. - - o Failure of a client or agent after sending a record from non- - volatile memory, but prior to receipt of an application-layer ACK - and deletion of the record to be sent. This will result in - retransmission of the record soon after the client or agent has - rebooted. - - o Duplicates received from RADIUS gateways. Since the - retransmission behavior of RADIUS is not defined within [RFC2865], - the likelihood of duplication will vary according to the - implementation. - - o Implementation problems and misconfiguration. - - The T flag is used as an indication of an application-layer - retransmission event, e.g., due to failover to an alternate server. - It is defined only for request messages sent by Diameter clients or - agents. For instance, after a reboot, a client may not know whether - - - -Fajardo, et al. Standards Track [Page 149] - -RFC 6733 Diameter Base Protocol October 2012 - - - it has already tried to send the accounting records in its non- - volatile memory before the reboot occurred. Diameter servers MAY use - the T flag as an aid when processing requests and detecting duplicate - messages. However, servers that do this MUST ensure that duplicates - are found even when the first transmitted request arrives at the - server after the retransmitted request. It can be used only in cases - where no answer has been received from the server for a request and - the request is sent again, (e.g., due to a failover to an alternate - peer, due to a recovered primary peer or due to a client re-sending a - stored record from non-volatile memory such as after reboot of a - client or agent). - - In some cases, the Diameter accounting server can delay the duplicate - detection and accounting record processing until a post-processing - phase takes place. At that time records are likely to be sorted - according to the included User-Name and duplicate elimination is easy - in this case. In other situations, it may be necessary to perform - real-time duplicate detection, such as when credit limits are imposed - or real-time fraud detection is desired. - - In general, only generation of duplicates due to failover or re- - sending of records in non-volatile storage can be reliably detected - by Diameter clients or agents. In such cases, the Diameter client or - agents can mark the message as a possible duplicate by setting the T - flag. Since the Diameter server is responsible for duplicate - detection, it can choose whether or not to make use of the T flag, in - order to optimize duplicate detection. Since the T flag does not - affect interoperability, and it may not be needed by some servers, - generation of the T flag is REQUIRED for Diameter clients and agents, - but it MAY be implemented by Diameter servers. - - As an example, it can be usually be assumed that duplicates appear - within a time window of longest recorded network partition or device - fault, perhaps a day. So only records within this time window need - to be looked at in the backward direction. Secondly, hashing - techniques or other schemes, such as the use of the T flag in the - received messages, may be used to eliminate the need to do a full - search even in this set except for rare cases. - - The following is an example of how the T flag may be used by the - server to detect duplicate requests. - - A Diameter server MAY check the T flag of the received message to - determine if the record is a possible duplicate. If the T flag is - set in the request message, the server searches for a duplicate - within a configurable duplication time window backward and - forward. This limits database searching to those records where - the T flag is set. In a well-run network, network partitions and - - - -Fajardo, et al. Standards Track [Page 150] - -RFC 6733 Diameter Base Protocol October 2012 - - - device faults will presumably be rare events, so this approach - represents a substantial optimization of the duplicate detection - process. During failover, it is possible for the original record - to be received after the T-flag-marked record, due to differences - in network delays experienced along the path by the original and - duplicate transmissions. The likelihood of this occurring - increases as the failover interval is decreased. In order to be - able to detect duplicates that are out of order, the Diameter - server should use backward and forward time windows when - performing duplicate checking for the T-flag-marked request. For - example, in order to allow time for the original record to exit - the network and be recorded by the accounting server, the Diameter - server can delay processing records with the T flag set until a - time period TIME_WAIT + RECORD_PROCESSING_TIME has elapsed after - the closing of the original transport connection. After this time - period, it may check the T-flag-marked records against the - database with relative assurance that the original records, if - sent, have been received and recorded. - -Appendix D. Internationalized Domain Names - - To be compatible with the existing DNS infrastructure and simplify - host and domain name comparison, Diameter identities (FQDNs) are - represented in ASCII form. This allows the Diameter protocol to fall - in-line with the DNS strategy of being transparent from the effects - of Internationalized Domain Names (IDNs) by following the - recommendations in [RFC4690] and [RFC5890]. Applications that - provide support for IDNs outside of the Diameter protocol but - interacting with it SHOULD use the representation and conversion - framework described in [RFC5890], [RFC5891], and [RFC3492]. -</pre> - -</section> diff --git a/lib/diameter/doc/src/diameter_tcp.xml b/lib/diameter/doc/src/diameter_tcp.xml index 1d65d14257..9f84eeb9fd 100644 --- a/lib/diameter/doc/src/diameter_tcp.xml +++ b/lib/diameter/doc/src/diameter_tcp.xml @@ -27,7 +27,8 @@ <erlref> <header> <copyright> -<year>2011</year><year>2016</year> +<year>2011</year> +<year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -99,7 +100,9 @@ before configuring TLS capability on diameter transports.</p> | {rport, integer()} | {accept, Match} | {port, integer()} - | {fragment_timer, infinity | 0..16#FFFFFFFF}</v> + | {fragment_timer, infinity | 0..16#FFFFFFFF} + | {message_cb, &mod_eval;} + | {sender, boolean()}</v> <v>SslOpt = {ssl_options, true | list()}</v> <v>TcpOpt = term()</v> <v>Match = &ip_address; | string() | [Match]</v> @@ -140,6 +143,44 @@ such a message is received over the transport interface after two successive timeouts without the reception of additional bytes. Defaults to 1000.</p> +<marker id="sender"/> +<p> +Option <c>sender</c> specifies whether or not to use a dedicated +process for sending outgoing messages, which avoids the possibility of +send blocking reception. +Defaults to <c>false</c>. +If set to <c>true</c> then a <c>message_cb</c> that avoids the +possibility of messages being queued in the sender process without +bound should be configured.</p> + +<p> +Option <c>message_cb</c> specifies a callback that is invoked on +incoming and outgoing messages, that can be used to implement +flow control. +It is applied to two arguments: an atom indicating the +reason for the callback (<c>send</c>, <c>recv</c>, or <c>ack</c> after +a completed send), and the message in question (binary() on +<c>recv</c>, binary() or diameter_packet record on <c>send</c> or +<c>ack</c>, or <c>false</c> on <c>ack</c> when an incoming request has +been discarded). +It should return a list of actions and a new callback as +tail; eg. <c>[fun cb/3, State]</c>. +Valid actions are the atoms <c>send</c> or <c>recv</c>, to +cause a following message-valued action to be sent/received, +a message to send/receive (binary() or +diameter_packet record), or a boolean() to enable/disable reading on +the socket. +More than one <c>send</c>/<c>recv</c>/message sequence can be +returned from the same callback, and an initial +<c>send</c>/<c>recv</c> can be omitted if the same as the value passed +as the callback's first argument. +Reading is initially enabled, and returning <c>false</c> does not +imply there cannot be subsequent <c>recv</c> callbacks since +messages may already have been read. +An empty tail is equivalent to the prevailing callback. +Defaults to a callback equivalent to <c>fun(ack, _) -> []; (_, Msg) -> +[Msg] end</c>.</p> + <p> Remaining options are any accepted by &ssl_connect3; or &gen_tcp_connect3; for diff --git a/lib/diameter/doc/src/files.mk b/lib/diameter/doc/src/files.mk index cb4f88a375..4c1297f6cc 100644 --- a/lib/diameter/doc/src/files.mk +++ b/lib/diameter/doc/src/files.mk @@ -2,7 +2,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 2010-2016. All Rights Reserved. +# Copyright Ericsson AB 2010-2017. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -40,8 +40,7 @@ XML_PART_FILES = \ user_man.xml XML_EXTRA_FILES = \ - seealso.ent \ - diameter_soc_rfc6733.xml + seealso.ent XML_CHAPTER_FILES = \ diameter_intro.xml \ diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml index 60478606ad..d1ad00de5c 100644 --- a/lib/diameter/doc/src/notes.xml +++ b/lib/diameter/doc/src/notes.xml @@ -43,6 +43,208 @@ first.</p> <!-- ===================================================================== --> +<section><title>diameter 2.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix handling of Proxy-Info in answer messages setting the + E-bit.</p> + <p> + RFC 6733 requires that Proxy-Info AVPs in an incoming + request be echoed in an outgoing answer. This was not + done in answers formulated by diameter; for example, as a + result of a handle_request callback having returned an + 'answer-message' or protocol_error tuple.</p> + <p> + Own Id: OTP-9869</p> + </item> + <item> + <p> + React to nodeup/nodedown when sharing peer connections.</p> + <p> + Service configuration share_peers and use_shared_peers + did not respond to the coming and going of remote nodes.</p> + <p> + Own Id: OTP-14011</p> + </item> + <item> + <p> + Fix inappropriate message callbacks.</p> + <p> + An incoming CER or DPR was regarded as discarded, + resulting in a corresponding message callback (if + configured) in diameter_tcp/sctp.</p> + <p> + Own Id: OTP-14486</p> + </item> + <item> + <p> + Fix handling of 5009 errors (DIAMETER_AVP_OCCURS_TOO_MANY + TIMES).</p> + <p> + RFC 6733 says that the first AVP that exceeds the bound + should be reported, but the suggestions in the errors + field of a diameter_packet record counted AVPs from the + rear of the message, not the front. Additionally, + diameter 2.0 in OTP 20.0 broke the counting by accepting + one more AVP than the message grammar in question + allowed.</p> + <p> + Own Id: OTP-14512</p> + </item> + <item> + <p> + Match case insensitively in diameter_tcp/sctp accept + tuple.</p> + <p> + Matching of remote addresses when accepting connections + in a listening transport was case-sensitive, causing the + semantics to change as a consequence of (kernel) + OTP-13006.</p> + <p> + Own Id: OTP-14535 Aux Id: OTP-13006 </p> + </item> + <item> + <p> + Fix backwards incompatibility of remote send when sharing + transports.</p> + <p> + The sending of requests over a transport connection on a + remote node running an older version of diameter was + broken by diameter 2.0 in OTP 20.0.</p> + <p> + Own Id: OTP-14552</p> + </item> + <item> + <p> + Fix diameter_packet.avps decode of Grouped AVP errors in + Failed-AVP.</p> + <p> + Decode didn't produce a list of diameter_avp records, so + information about faulty component AVPs was lost.</p> + <p> + Own Id: OTP-14607</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Let unordered delivery be configured in diameter_sctp.</p> + <p> + With option {unordered, boolean() | pos_integer()}, with + false the default, and N equivalent to OS =< N, where + OS is the number of outbound streams negotiated on the + association in question. If configured, unordered sending + commences upon reception of a second message, outgoing + messages being sent on stream 0 before this.</p> + <p> + The default false is for backwards compatibility, but + false or 1 should be set to follow RFC 6733's + recommendation on the use of unordered sending to avoid + head-of-line blocking. There is typically no meaningful + order to preserve, since the order in which outgoing + messages are received by a transport process isn't known + to the sender.</p> + <p> + Own Id: OTP-10889</p> + </item> + <item> + <p> + Complete/simplify Standards Compliance in User's Guide.</p> + <p> + Own Id: OTP-10927</p> + </item> + <item> + <p> + Add service option decode_format.</p> + <p> + To allow incoming messages to be decoded into maps or + lists instead of records. Messages can be presented in + any of the formats for encode.</p> + <p> + Decode performance has also been improved.</p> + <p> + Own Id: OTP-14511 Aux Id: OTP-14343 </p> + </item> + <item> + <p> + Add service option traffic_counters.</p> + <p> + To let message-related counters be disabled, which can be + a performance improvement in some usecases.</p> + <p> + Own Id: OTP-14521</p> + </item> + <item> + <p> + Allow loopback/any as local addresses in + diameter_tcp/sctp.</p> + <p> + The atoms were implied by documentation, but not handled + in code.</p> + <p> + Own Id: OTP-14544</p> + </item> + <item> + <p> + Add transport option strict_capx.</p> + <p> + To allow the RFC 6733 requirement that a transport + connection be closed if a message is received before + capabilities exchange to be relaxed.</p> + <p> + Own Id: OTP-14546</p> + </item> + <item> + <p> + Be consistent with service/transport configuration.</p> + <p> + For options for which it's meaningful, defaults values + for transport options can now be configured on a service. + This was previously the case only for an arbitrary subset + of options.</p> + <p> + Own Id: OTP-14555</p> + </item> + <item> + <p> + Add service/transport option avp_dictionaries.</p> + <p> + To provide better support for AVPs that are not defined + in the application dictionary: configuring additional + dictionaries in an avp_dictionaries tuple allows their + AVPs to be encoded/decoded in much the same fashion as + application AVPs.</p> + <p> + The motivation is RFC 7683 Diameter Overload, Indicator + Conveyance (DOIC), that defines AVPs intended to be + piggybacked onto arbitrary messages. A DOIC dictionary + has been included in the installation, in module + diameter_gen_doic_rfc7683.</p> + <p> + Own Id: OTP-14588</p> + </item> + <item> + <p> + Decode application AVPs in answers setting the E-bit.</p> + <p> + AVPs defined in the application of the message being sent + were previously not decoded, only those in the common + application that defines the answer-message grammar.</p> + <p> + Own Id: OTP-14596</p> + </item> + </list> + </section> + +</section> + <section><title>diameter 2.0</title> <section><title>Improvements and New Features</title> diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl index f510f40a17..d2856ae530 100644 --- a/lib/diameter/src/base/diameter_traffic.erl +++ b/lib/diameter/src/base/diameter_traffic.erl @@ -684,7 +684,7 @@ resend(false, Route = #diameter_avp{data = {Dict0, 'Route-Record', OH}}, Seq = diameter_session:sequence(Mask), Hdr = Hdr0#diameter_header{hop_by_hop_id = Seq}, - Msg = [Hdr, Route | Avps], %% reordered at encode + Msg = [Hdr | Avps ++ [Route]], case send_request(SvcName, App, Msg, Opts) of #diameter_packet{} = Ans -> Ans; diff --git a/lib/diameter/src/diameter.appup.src b/lib/diameter/src/diameter.appup.src index 07d0389bfd..7566cf25c3 100644 --- a/lib/diameter/src/diameter.appup.src +++ b/lib/diameter/src/diameter.appup.src @@ -52,7 +52,8 @@ {"1.11.2", [{restart_application, diameter}]}, %% 18.3 {"1.12", [{restart_application, diameter}]}, %% 19.0 {"1.12.1", [{restart_application, diameter}]}, %% 19.1 - {"1.12.2", [{restart_application, diameter}]} %% 19.3 + {"1.12.2", [{restart_application, diameter}]}, %% 19.3 + {"2.0", [{restart_application, diameter}]} %% 20.0 ], [ {"0.9", [{restart_application, diameter}]}, @@ -86,6 +87,7 @@ {"1.11.2", [{restart_application, diameter}]}, {"1.12", [{restart_application, diameter}]}, {"1.12.1", [{restart_application, diameter}]}, - {"1.12.2", [{restart_application, diameter}]} + {"1.12.2", [{restart_application, diameter}]}, + {"2.0", [{restart_application, diameter}]} ] }. diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl index 4eb3379d59..64b34da690 100644 --- a/lib/diameter/src/transport/diameter_sctp.erl +++ b/lib/diameter/src/transport/diameter_sctp.erl @@ -103,6 +103,8 @@ | undefined, os = 0 :: uint(), %% next output stream rotate = 1 :: boolean() | 0 | 1, %% rotate os? + unordered = false :: boolean() %% always send unordered? + | pos_integer(),% or if =< N outbound streams? packet = true :: boolean() %% legacy transport_data? | raw, message_cb = false :: false | diameter:eval(), @@ -242,8 +244,11 @@ i(#monitor{transport = TPid} = S) -> i({listen, Ref, {Opts, SvcPid, Addrs}}) -> monitor(process, SvcPid), [_] = diameter_config:subscribe(Ref, transport), %% assert existence - {Split, Rest} - = proplists:split(Opts, [accept, packet, sender, message_cb]), + {Split, Rest} = proplists:split(Opts, [accept, + packet, + sender, + message_cb, + unordered]), OwnOpts = lists:append(Split), {LAs, Sock} = AS = open(Addrs, Rest, ?DEFAULT_PORT), ok = gen_sctp:listen(Sock, true), @@ -255,12 +260,16 @@ i({listen, Ref, {Opts, SvcPid, Addrs}}) -> opts = [[[M] || {accept, M} <- OwnOpts], proplists:get_value(packet, OwnOpts, true) | [proplists:get_value(K, OwnOpts, false) - || K <- [sender, message_cb]]]}; + || K <- [sender, message_cb, unordered]]]}; %% A connecting transport. i({connect, Pid, Opts, Addrs, Ref}) -> - {[Ps | Split], Rest} - = proplists:split(Opts, [rport, raddr, packet, sender, message_cb]), + {[Ps | Split], Rest} = proplists:split(Opts, [rport, + raddr, + packet, + sender, + message_cb, + unordered]), OwnOpts = lists:append(Split), CB = proplists:get_value(message_cb, OwnOpts, false), false == CB orelse (Pid ! {diameter, ack}), @@ -274,6 +283,7 @@ i({connect, Pid, Opts, Addrs, Ref}) -> mode = {connect, connect(Sock, RAs, RP, [])}, socket = Sock, message_cb = CB, + unordered = proplists:get_value(ordered, OwnOpts, false), packet = proplists:get_value(packet, OwnOpts, true), send = proplists:get_value(sender, OwnOpts, false)}; @@ -311,12 +321,13 @@ i({K, Ref}, #transport{mode = {accept, _}} = S) -> S#transport{parent = Pid}; {K, T, Opts} when K == peeloff -> %% association {sctp, Sock, _RA, _RP, _Data} = T, - [Matches, Packet, Sender, CB] = Opts, + [Matches, Packet, Sender, CB, Unordered] = Opts, ok = accept_peer(Sock, Matches), demonitor(Ref, [flush]), false == CB orelse (S#transport.parent ! {diameter, ack}), t(T, S#transport{socket = Sock, message_cb = CB, + unordered = Unordered, packet = Packet, send = Sender}); accept_timeout = T -> @@ -799,14 +810,30 @@ recv(#transport{rotate = B} = S) when is_boolean(B) -> S; -recv(#transport{rotate = 0, streams = {_,N}, socket = Sock} = S) -> - ok = inet:setopts(Sock, [{sctp_default_send_param, - #sctp_sndrcvinfo{flags = [unordered]}}]), - S#transport{rotate = 1 < N}; +recv(#transport{rotate = 0, + streams = {_,OS}, + socket = Sock, + unordered = B} + = S) -> + ok = unordered(Sock, OS, B), + S#transport{rotate = 1 < OS}; recv(#transport{rotate = N} = S) -> S#transport{rotate = N-1}. +%% unordered/3 + +unordered(Sock, OS, B) + when B; + is_integer(B), OS =< B -> + inet:setopts(Sock, [{sctp_default_send_param, + #sctp_sndrcvinfo{flags = [unordered]}}]); + +unordered(_, OS, B) + when not B; + is_integer(B), B < OS -> + ok. + %% publish/4 publish(T, Ref, Id, Sock) -> diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl index ffb4a508cd..c224f9a27e 100644 --- a/lib/diameter/test/diameter_traffic_SUITE.erl +++ b/lib/diameter/test/diameter_traffic_SUITE.erl @@ -533,9 +533,10 @@ add_transports(Config) -> LRef = ?util:listen(SN, [T, {sender, SS}, - {message_cb, ST andalso {?MODULE, message, [0]}} - | [{packet, hd(?util:scramble([false, raw]))} - || T == sctp andalso CS]], + {message_cb, ST andalso {?MODULE, message, [0]}}] + ++ [{packet, hd(?util:scramble([false, raw]))} + || T == sctp andalso CS] + ++ [{unordered, unordered()} || T == sctp], [{capabilities_cb, fun capx/2}, {pool_size, 8} | server_apps()] @@ -551,13 +552,17 @@ add_transports(Config) -> Id <- [{D,E}]], ?util:write_priv(Config, "transport", [LRef | Cs]). +unordered() -> + element(rand:uniform(4), {true, false, 1, 2}). + client_opts(tcp) -> []; client_opts(sctp) -> - [{sctp_initmsg, #sctp_initmsg{num_ostreams = N, - max_instreams = 5}} - || N <- [rand:uniform(8)], - N =< 6]. + [{unordered, unordered()} + | [{sctp_initmsg, #sctp_initmsg{num_ostreams = N, + max_instreams = 5}} + || N <- [rand:uniform(8)], + N =< 6]]. server_apps() -> B = have_nas(), diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk index 4801f542fb..e6dfddb5b2 100644 --- a/lib/diameter/vsn.mk +++ b/lib/diameter/vsn.mk @@ -17,5 +17,5 @@ # %CopyrightEnd% APPLICATION = diameter -DIAMETER_VSN = 2.0 +DIAMETER_VSN = 2.1 APP_VSN = $(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN) diff --git a/lib/edoc/doc/src/notes.xml b/lib/edoc/doc/src/notes.xml index 7894811c78..96d7597d83 100644 --- a/lib/edoc/doc/src/notes.xml +++ b/lib/edoc/doc/src/notes.xml @@ -32,6 +32,21 @@ <p>This document describes the changes made to the EDoc application.</p> +<section><title>Edoc 0.9.1</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Tools are updated to show Unicode atoms correctly.</p> + <p> + Own Id: OTP-14464</p> + </item> + </list> + </section> + +</section> + <section><title>Edoc 0.9</title> <section><title>Improvements and New Features</title> diff --git a/lib/edoc/src/edoc_layout.erl b/lib/edoc/src/edoc_layout.erl index eafab0588e..baa147410b 100644 --- a/lib/edoc/src/edoc_layout.erl +++ b/lib/edoc/src/edoc_layout.erl @@ -608,7 +608,7 @@ etypef([Cs | L], St, O, R, Opts) -> app_fix(L, Opts) -> try {"//" ++ R1,L2} = app_fix1(L, 1), - [App, Mod] = string:tokens(R1, "/"), + [App, Mod] = string:lexemes(R1, "/"), "//" ++ atom(App, Opts) ++ "/" ++ atom(Mod, Opts) ++ L2 catch _:_ -> L end. @@ -1120,13 +1120,13 @@ ot_integer(E) -> {integer,0,list_to_integer(get_attrval(value, E))}. ot_range(E) -> - [I1, I2] = string:tokens(get_attrval(value, E), "."), + [I1, I2] = string:lexemes(get_attrval(value, E), "."), {type,0,range,[{integer,0,list_to_integer(I1)}, {integer,0,list_to_integer(I2)}]}. ot_binary(E) -> {Base, Unit} = - case string:tokens(get_attrval(value, E), ",:*><") of + case string:lexemes(get_attrval(value, E), ",:*><") of [] -> {0, 0}; ["_",B] -> diff --git a/lib/edoc/src/edoc_specs.erl b/lib/edoc/src/edoc_specs.erl index fb04bfce0e..26b7202462 100644 --- a/lib/edoc/src/edoc_specs.erl +++ b/lib/edoc/src/edoc_specs.erl @@ -83,7 +83,7 @@ spec(Form, Clause) -> %% the given Erlang spec and an empty list of arguments. dummy_spec(Form) -> {#t_name{name = Name}, Arity, TypeSpecs} = get_spec(Form), - As = string:join(lists:duplicate(Arity, "_X"), ","), + As = lists:join(",", lists:duplicate(Arity, "_X")), S = lists:flatten(io_lib:format("~p(~s) -> true\n", [Name, As])), #tag{name = spec, line = get_line(element(2, hd(TypeSpecs))), origin = code, data = S}. diff --git a/lib/edoc/vsn.mk b/lib/edoc/vsn.mk index 1a933b2ad8..065944ccef 100644 --- a/lib/edoc/vsn.mk +++ b/lib/edoc/vsn.mk @@ -1 +1 @@ -EDOC_VSN = 0.9 +EDOC_VSN = 0.9.1 diff --git a/lib/eldap/src/eldap.erl b/lib/eldap/src/eldap.erl index 625309271b..2b84872b92 100644 --- a/lib/eldap/src/eldap.erl +++ b/lib/eldap/src/eldap.erl @@ -1368,9 +1368,9 @@ rm_leading_slash(Tail) -> Tail. parse_attributes([$?|Tail]) -> case split_string(Tail,$?) of {[],Attributes} -> - {[],{attributes,string:tokens(Attributes,",")}}; + {[],{attributes,string:lexemes(Attributes,",")}}; {Attributes,Rest} -> - {Rest,{attributes,string:tokens(Attributes,",")}} + {Rest,{attributes,string:lexemes(Attributes,",")}} end. parse_hostport(Str) -> diff --git a/lib/erl_docgen/doc/src/notes.xml b/lib/erl_docgen/doc/src/notes.xml index 59a268d6ac..59c65665d4 100644 --- a/lib/erl_docgen/doc/src/notes.xml +++ b/lib/erl_docgen/doc/src/notes.xml @@ -31,7 +31,22 @@ </header> <p>This document describes the changes made to the <em>erl_docgen</em> application.</p> - <section><title>Erl_Docgen 0.7</title> + <section><title>Erl_Docgen 0.7.1</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + General Unicode improvements.</p> + <p> + Own Id: OTP-14462</p> + </item> + </list> + </section> + +</section> + +<section><title>Erl_Docgen 0.7</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/erl_docgen/priv/dtd/chapter.dtd b/lib/erl_docgen/priv/dtd/chapter.dtd index a4c9e4040d..8d940b90f7 100644 --- a/lib/erl_docgen/priv/dtd/chapter.dtd +++ b/lib/erl_docgen/priv/dtd/chapter.dtd @@ -31,7 +31,7 @@ <!-- Structure --> <!ELEMENT chapter (header,(%block;|quote|warning|note|dont|do|br| - image|marker|table)*,section+) > + image|marker|table)*,section*) > <!ELEMENT section (marker*,title, (%block;|quote|warning|note|dont|do|br|image|marker| table|section)*) > diff --git a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl index 7cdbb502d9..67e6e33c93 100644 --- a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl +++ b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl @@ -11,7 +11,7 @@ %% limitations under the License. %% %% Copyright (c) 2001-2016 Richard Carlsson. Parts written by Ericsson -%% are Copyright (c) Ericsson AB 2001-2012. All Rights Reserved. +%% are Copyright (c) Ericsson AB 2001-2017. All Rights Reserved. %% -module(docgen_edoc_xml_cb). @@ -113,7 +113,7 @@ root_attributes(Element, Opts) -> %% epp:default_encoding/0 returns 'utf8' reformat_encoding(utf8) -> "UTF-8"; reformat_encoding(List) when is_list(List) -> - case string:to_lower(List) of + case string:lowercase(List) of "utf8" -> "UTF-8"; _ -> List end; diff --git a/lib/erl_docgen/src/docgen_otp_specs.erl b/lib/erl_docgen/src/docgen_otp_specs.erl index 126229ecc9..9f2b401f93 100644 --- a/lib/erl_docgen/src/docgen_otp_specs.erl +++ b/lib/erl_docgen/src/docgen_otp_specs.erl @@ -297,7 +297,7 @@ indent(L) -> app_fix(L) -> try {"//" ++ R1,L2} = app_fix(L, 1), - [App, Mod] = string:tokens(R1, "/"), + [App, Mod] = string:lexemes(R1, "/"), "//" ++ atom(App) ++ "/" ++ atom(Mod) ++ L2 catch _:_ -> L end. @@ -585,13 +585,13 @@ ot_integer(E) -> {integer,0,list_to_integer(get_attrval(value, E))}. ot_range(E) -> - [I1, I2] = string:tokens(get_attrval(value, E), "."), + [I1, I2] = string:lexemes(get_attrval(value, E), "."), {type,0,range,[{integer,0,list_to_integer(I1)}, {integer,0,list_to_integer(I2)}]}. ot_binary(E) -> {Base, Unit} = - case string:tokens(get_attrval(value, E), ",:*><") of + case string:lexemes(get_attrval(value, E), ",:*><") of [] -> {0, 0}; ["_",B] -> diff --git a/lib/erl_docgen/src/erl_docgen.app.src b/lib/erl_docgen/src/erl_docgen.app.src index d63d880d89..171c697585 100644 --- a/lib/erl_docgen/src/erl_docgen.app.src +++ b/lib/erl_docgen/src/erl_docgen.app.src @@ -9,6 +9,6 @@ {registered,[]}, {applications, [kernel,stdlib]}, {env, []}, - {runtime_dependencies, ["xmerl-1.3.7","stdlib-2.5","edoc-0.7.13","erts-6.0"]} + {runtime_dependencies, ["xmerl-1.3.7","stdlib-3.4","edoc-0.7.13","erts-9.0"]} ] }. diff --git a/lib/erl_docgen/vsn.mk b/lib/erl_docgen/vsn.mk index 8fad061b26..17a7c483f4 100644 --- a/lib/erl_docgen/vsn.mk +++ b/lib/erl_docgen/vsn.mk @@ -1 +1 @@ -ERL_DOCGEN_VSN = 0.7 +ERL_DOCGEN_VSN = 0.7.1 diff --git a/lib/et/doc/src/notes.xml b/lib/et/doc/src/notes.xml index 5300d2e4ef..f0995b7c19 100644 --- a/lib/et/doc/src/notes.xml +++ b/lib/et/doc/src/notes.xml @@ -37,6 +37,21 @@ one section in this document. The title of each section is the version number of <c>Event Tracer (ET)</c>.</p> +<section><title>ET 1.6.1</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Tools are updated to show Unicode atoms correctly.</p> + <p> + Own Id: OTP-14464</p> + </item> + </list> + </section> + +</section> + <section><title>ET 1.6</title> <section><title>Improvements and New Features</title> diff --git a/lib/et/src/et.app.src b/lib/et/src/et.app.src index 7a5928d6ab..f4e32f734d 100644 --- a/lib/et/src/et.app.src +++ b/lib/et/src/et.app.src @@ -33,6 +33,6 @@ {registered, [et_collector]}, {applications, [stdlib, kernel]}, {env, []}, - {runtime_dependencies, ["wx-1.2","stdlib-2.0","runtime_tools-1.10", - "kernel-3.0","erts-8.0"]} + {runtime_dependencies, ["wx-1.2","stdlib-3.4","runtime_tools-1.10", + "kernel-5.3","erts-9.0"]} ]}. diff --git a/lib/et/src/et_collector.erl b/lib/et/src/et_collector.erl index b0f016a8ea..ffe244324c 100644 --- a/lib/et/src/et_collector.erl +++ b/lib/et/src/et_collector.erl @@ -1135,7 +1135,7 @@ handle_info(Info, S) -> noreply(S). listen_on_trace_port(Node, Port, S) -> - [_Name, Host] = string:tokens(atom_to_list(Node), [$@]), + [_Name, Host] = string:lexemes(atom_to_list(Node), [$@]), case catch start_trace_client(self(), ip, {Host, Port}) of {trace_client_pid, RemotePid} -> rpc:call(Node, et_selector, change_pattern, [S#state.trace_pattern]), diff --git a/lib/et/test/et_test_lib.erl b/lib/et/test/et_test_lib.erl index df2c308b28..fc469f646a 100644 --- a/lib/et/test/et_test_lib.erl +++ b/lib/et/test/et_test_lib.erl @@ -18,7 +18,7 @@ %% %CopyrightEnd% -module(et_test_lib). --compile(export_all). +-compile([export_all, nowarn_export_all]). -include("et_test_lib.hrl"). diff --git a/lib/et/test/ett.erl b/lib/et/test/ett.erl index b1b769b7ac..2b276eab1a 100644 --- a/lib/et/test/ett.erl +++ b/lib/et/test/ett.erl @@ -18,7 +18,7 @@ %% %CopyrightEnd% -module(ett). --compile(export_all). +-compile([export_all, nowarn_export_all]). %% Modules or suites can be shortcuts, for example wx expands to et_wx_SUITE. %% diff --git a/lib/et/vsn.mk b/lib/et/vsn.mk index a37fec083b..aab63a402e 100644 --- a/lib/et/vsn.mk +++ b/lib/et/vsn.mk @@ -1 +1 @@ -ET_VSN = 1.6 +ET_VSN = 1.6.1 diff --git a/lib/eunit/doc/src/notes.xml b/lib/eunit/doc/src/notes.xml index 2a4ca6d12c..7133befe37 100644 --- a/lib/eunit/doc/src/notes.xml +++ b/lib/eunit/doc/src/notes.xml @@ -33,6 +33,21 @@ </header> <p>This document describes the changes made to the EUnit application.</p> +<section><title>Eunit 2.3.4</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Tools are updated to show Unicode atoms correctly.</p> + <p> + Own Id: OTP-14464</p> + </item> + </list> + </section> + +</section> + <section><title>Eunit 2.3.3</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/eunit/src/eunit.app.src b/lib/eunit/src/eunit.app.src index b4ff6c9242..cc75a0f790 100644 --- a/lib/eunit/src/eunit.app.src +++ b/lib/eunit/src/eunit.app.src @@ -19,4 +19,4 @@ {registered,[]}, {applications, [kernel,stdlib]}, {env, []}, - {runtime_dependencies, ["stdlib-2.5","kernel-3.0","erts-6.0"]}]}. + {runtime_dependencies, ["stdlib-3.4","kernel-5.3","erts-9.0"]}]}. diff --git a/lib/eunit/src/eunit_lib.erl b/lib/eunit/src/eunit_lib.erl index e340f50a3c..d1bd160ea1 100644 --- a/lib/eunit/src/eunit_lib.erl +++ b/lib/eunit/src/eunit_lib.erl @@ -391,7 +391,7 @@ fun_parent(F) -> -ifdef(TEST). fun_parent_test() -> - {?MODULE,fun_parent_test,0} = fun_parent(fun () -> ok end). + {?MODULE,fun_parent_test,0} = fun_parent(fun (A) -> {ok,A} end). -endif. %% --------------------------------------------------------------------- diff --git a/lib/eunit/vsn.mk b/lib/eunit/vsn.mk index 107ad5c101..25bb0dec17 100644 --- a/lib/eunit/vsn.mk +++ b/lib/eunit/vsn.mk @@ -1 +1 @@ -EUNIT_VSN = 2.3.3 +EUNIT_VSN = 2.3.4 diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index f4746fc9d0..d8d707c05e 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -1630,8 +1630,8 @@ lift_list_to_pos_empty(?list(Content, Termination, _)) -> %% * The keys in Pairs are singleton types. %% * The values of Pairs must not be unit, and may only be none if the %% mandatoriness tag is 'optional'. -%% * Optional must contain no pair {K,V} s.t. K is a subtype of DefaultKey and -%% V is equal to DefaultKey. +%% * There is no pair {K, 'optional', V} in Pairs s.t. +%% K is a subtype of DefaultKey and V is equal to DefaultValue. %% * DefaultKey must be the empty type iff DefaultValue is the empty type. %% * DefaultKey must not be a singleton type. %% * For every key K in Pairs, DefaultKey - K must not be representable; i.e. @@ -4249,13 +4249,13 @@ t_to_string(?identifier(Set), _RecDict) -> case Set of ?any -> "identifier()"; _ -> - string:join([flat_format("~w()", [T]) || T <- set_to_list(Set)], " | ") + flat_join([flat_format("~w()", [T]) || T <- set_to_list(Set)], " | ") end; t_to_string(?opaque(Set), RecDict) -> - string:join([opaque_type(Mod, Name, Args, S, RecDict) || - #opaque{mod = Mod, name = Name, struct = S, args = Args} - <- set_to_list(Set)], - " | "); + flat_join([opaque_type(Mod, Name, Args, S, RecDict) || + #opaque{mod = Mod, name = Name, struct = S, args = Args} + <- set_to_list(Set)], + " | "); t_to_string(?matchstate(Pres, Slots), RecDict) -> flat_format("ms(~ts,~ts)", [t_to_string(Pres, RecDict), t_to_string(Slots,RecDict)]); @@ -4346,9 +4346,9 @@ t_to_string(?map(Pairs0,DefK,DefV), RecDict) -> end end, StrMand = [{Tos(K),Tos(V)}||{K,?mand,V}<-Pairs], StrOpt = [{Tos(K),Tos(V)}||{K,?opt,V}<-Pairs], - "#{" ++ string:join([K ++ ":=" ++ V||{K,V}<-StrMand] - ++ [K ++ "=>" ++ V||{K,V}<-StrOpt] - ++ ExtraEl, ", ") ++ "}"; + "#{" ++ flat_join([K ++ ":=" ++ V||{K,V}<-StrMand] + ++ [K ++ "=>" ++ V||{K,V}<-StrOpt] + ++ ExtraEl, ", ") ++ "}"; t_to_string(?tuple(?any, ?any, ?any), _RecDict) -> "tuple()"; t_to_string(?tuple(Elements, _Arity, ?any), RecDict) -> "{" ++ comma_sequence(Elements, RecDict) ++ "}"; @@ -4371,7 +4371,7 @@ t_to_string(?var(Id), _RecDict) when is_integer(Id) -> record_to_string(Tag, [_|Fields], FieldNames, RecDict) -> FieldStrings = record_fields_to_string(Fields, FieldNames, RecDict, []), - "#" ++ atom_to_string(Tag) ++ "{" ++ string:join(FieldStrings, ",") ++ "}". + "#" ++ atom_to_string(Tag) ++ "{" ++ flat_join(FieldStrings, ",") ++ "}". record_fields_to_string([F|Fs], [{FName, _Abstr, DefType}|FDefs], RecDict, Acc) -> @@ -4397,7 +4397,7 @@ record_field_diffs_to_string(?tuple([_|Fs], Arity, Tag), RecDict) -> {ok, FieldNames} = lookup_record(TagAtom, Arity-1, RecDict), %% io:format("RecCElems = ~p\nRecTypes = ~p\n", [Fs, FieldNames]), FieldDiffs = field_diffs(Fs, FieldNames, RecDict, []), - string:join(FieldDiffs, " and "). + flat_join(FieldDiffs, " and "). field_diffs([F|Fs], [{FName, _Abstr, DefType}|FDefs], RecDict, Acc) -> %% Don't care about opacity for now. @@ -4417,11 +4417,11 @@ comma_sequence(Types, RecDict) -> true -> "_"; false -> t_to_string(T, RecDict) end || T <- Types], - string:join(List, ","). + flat_join(List, ","). union_sequence(Types, RecDict) -> List = [t_to_string(T, RecDict) || T <- Types], - string:join(List, " | "). + flat_join(List, " | "). -ifdef(DEBUG). opaque_type(Mod, Name, _Args, S, RecDict) -> @@ -4675,7 +4675,8 @@ from_form({type, _L, map, List}, S, D0, L, C) -> end end(List, L, C), try - {Pairs, DefK, DefV} = map_from_form(Pairs1, [], [], [], ?none, ?none), + Pairs2 = singleton_elements(Pairs1), + {Pairs, DefK, DefV} = map_from_form(Pairs2, [], [], [], ?none, ?none), {t_map(Pairs, DefK, DefV), L5, C5} catch none -> {t_none(), L5, C5} end; @@ -5026,6 +5027,30 @@ list_from_form([H|Tail], S, D, L, C) -> {T1, L2, C2} = list_from_form(Tail, S, D, L1, C1), {[H1|T1], L2, C2}. +%% Separates singleton types in keys (see is_singleton_type/1). +singleton_elements([]) -> + []; +singleton_elements([{K,?mand,V}=Pair|Pairs]) -> + case is_singleton_type(K) of + true -> + [Pair|singleton_elements(Pairs)]; + false -> + singleton_elements([{K,?opt,V}|Pairs]) + end; +singleton_elements([{Key0,MNess,Val}|Pairs]) -> + [{Key,MNess,Val} || Key <- separate_key(Key0)] ++ singleton_elements(Pairs). + +%% To be in sync with is_singleton_type/1. +%% Does not separate tuples and maps as doing that has potential +%% to be very expensive. +separate_key(?atom(Atoms)) when Atoms =/= ?any -> + [t_atom(A) || A <- Atoms]; +separate_key(?number(_, _) = T) -> + t_elements(T); +separate_key(?union(List)) -> + lists:append([separate_key(K) || K <- List, not t_is_none(K)]); +separate_key(Key) -> [Key]. + %% Sorts, combines non-singleton pairs, and applies precendence and %% mandatoriness rules. map_from_form([], ShdwPs, MKs, Pairs, DefK, DefV) -> @@ -5236,7 +5261,7 @@ t_form_to_string({ann_type, _L, [Var, Type]}) -> t_form_to_string({paren_type, _L, [Type]}) -> flat_format("(~ts)", [t_form_to_string(Type)]); t_form_to_string({remote_type, _L, [{atom, _, Mod}, {atom, _, Name}, Args]}) -> - ArgString = "(" ++ string:join(t_form_to_string_list(Args), ",") ++ ")", + ArgString = "(" ++ flat_join(t_form_to_string_list(Args), ",") ++ ")", flat_format("~w:~tw", [Mod, Name]) ++ ArgString; t_form_to_string({type, _L, arity, []}) -> "arity()"; t_form_to_string({type, _L, binary, []}) -> "binary()"; @@ -5259,7 +5284,7 @@ t_form_to_string({type, _L, 'fun', []}) -> "fun()"; t_form_to_string({type, _L, 'fun', [{type, _, any}, Range]}) -> "fun(...) -> " ++ t_form_to_string(Range); t_form_to_string({type, _L, 'fun', [{type, _, product, Domain}, Range]}) -> - "fun((" ++ string:join(t_form_to_string_list(Domain), ",") ++ ") -> " + "fun((" ++ flat_join(t_form_to_string_list(Domain), ",") ++ ") -> " ++ t_form_to_string(Range) ++ ")"; t_form_to_string({type, _L, iodata, []}) -> "iodata()"; t_form_to_string({type, _L, iolist, []}) -> "iolist()"; @@ -5267,7 +5292,7 @@ t_form_to_string({type, _L, list, [Type]}) -> "[" ++ t_form_to_string(Type) ++ "]"; t_form_to_string({type, _L, map, any}) -> "map()"; t_form_to_string({type, _L, map, Args}) -> - "#{" ++ string:join(t_form_to_string_list(Args), ",") ++ "}"; + "#{" ++ flat_join(t_form_to_string_list(Args), ",") ++ "}"; t_form_to_string({type, _L, map_field_assoc, [Key, Val]}) -> t_form_to_string(Key) ++ "=>" ++ t_form_to_string(Val); t_form_to_string({type, _L, map_field_exact, [Key, Val]}) -> @@ -5279,7 +5304,7 @@ t_form_to_string({type, _L, nonempty_list, [Type]}) -> "[" ++ t_form_to_string(Type) ++ ",...]"; t_form_to_string({type, _L, nonempty_string, []}) -> "nonempty_string()"; t_form_to_string({type, _L, product, Elements}) -> - "<" ++ string:join(t_form_to_string_list(Elements), ",") ++ ">"; + "<" ++ flat_join(t_form_to_string_list(Elements), ",") ++ ">"; t_form_to_string({type, _L, range, [From, To]} = Type) -> case {erl_eval:partial_eval(From), erl_eval:partial_eval(To)} of {{integer, _, FromVal}, {integer, _, ToVal}} -> @@ -5289,7 +5314,7 @@ t_form_to_string({type, _L, range, [From, To]} = Type) -> t_form_to_string({type, _L, record, [{atom, _, Name}]}) -> flat_format("#~tw{}", [Name]); t_form_to_string({type, _L, record, [{atom, _, Name}|Fields]}) -> - FieldString = string:join(t_form_to_string_list(Fields), ","), + FieldString = flat_join(t_form_to_string_list(Fields), ","), flat_format("#~tw{~ts}", [Name, FieldString]); t_form_to_string({type, _L, field_type, [{atom, _, Name}, Type]}) -> flat_format("~tw::~ts", [Name, t_form_to_string(Type)]); @@ -5297,9 +5322,9 @@ t_form_to_string({type, _L, term, []}) -> "term()"; t_form_to_string({type, _L, timeout, []}) -> "timeout()"; t_form_to_string({type, _L, tuple, any}) -> "tuple()"; t_form_to_string({type, _L, tuple, Args}) -> - "{" ++ string:join(t_form_to_string_list(Args), ",") ++ "}"; + "{" ++ flat_join(t_form_to_string_list(Args), ",") ++ "}"; t_form_to_string({type, _L, union, Args}) -> - string:join(t_form_to_string_list(Args), " | "); + flat_join(t_form_to_string_list(Args), " | "); t_form_to_string({type, _L, Name, []} = T) -> try M = mod, @@ -5317,7 +5342,7 @@ t_form_to_string({type, _L, Name, []} = T) -> end; t_form_to_string({user_type, _L, Name, List}) -> flat_format("~tw(~ts)", - [Name, string:join(t_form_to_string_list(List), ",")]); + [Name, flat_join(t_form_to_string_list(List), ",")]); t_form_to_string({type, L, Name, List}) -> %% Compatibility: modules compiled before Erlang/OTP 18.0. t_form_to_string({user_type, L, Name, List}). @@ -5475,7 +5500,8 @@ t_is_singleton(Type) -> t_is_singleton(Type, Opaques) -> do_opaque(Type, Opaques, fun is_singleton_type/1). -%% Incomplete; not all representable singleton types are included. +%% To be in sync with separate_key/1. +%% Used to also recognize maps and tuples. is_singleton_type(?nil) -> true; is_singleton_type(?atom(?any)) -> false; is_singleton_type(?atom(Set)) -> @@ -5483,13 +5509,6 @@ is_singleton_type(?atom(Set)) -> is_singleton_type(?int_range(V, V)) -> true; is_singleton_type(?int_set(Set)) -> ordsets:size(Set) =:= 1; -is_singleton_type(?tuple(Types, Arity, _)) when is_integer(Arity) -> - lists:all(fun is_singleton_type/1, Types); -is_singleton_type(?tuple_set([{Arity, [OnlyTuple]}])) when is_integer(Arity) -> - is_singleton_type(OnlyTuple); -is_singleton_type(?map(Pairs, ?none, ?none)) -> - lists:all(fun({_,MNess,V}) -> MNess =:= ?mand andalso is_singleton_type(V) - end, Pairs); is_singleton_type(_) -> false. @@ -5584,7 +5603,7 @@ set_to_string(Set) -> true -> io_lib:write_string(atom_to_list(X), $'); % stupid emacs ' false -> flat_format("~tw", [X]) end || X <- set_to_list(Set)], - string:join(L, " | "). + flat_join(L, " | "). set_min([H|_]) -> H. @@ -5594,6 +5613,9 @@ set_max(Set) -> flat_format(F, S) -> lists:flatten(io_lib:format(F, S)). +flat_join(List, Sep) -> + lists:flatten(lists:join(Sep, List)). + %%============================================================================= %% %% Utilities for the binary type diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml index 9167d0aaec..eadaee50e2 100644 --- a/lib/hipe/doc/src/notes.xml +++ b/lib/hipe/doc/src/notes.xml @@ -31,6 +31,35 @@ </header> <p>This document describes the changes made to HiPE.</p> +<section><title>Hipe 3.16.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> Fix a bug regarding map types that caused Dialyzer to + go into an infinite loop. A consequence of the fix is + that compound map keys such as maps and tuples sometimes + are handled with less precision than before. </p> + <p> + Own Id: OTP-14572 Aux Id: seq13319 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + General Unicode improvements.</p> + <p> + Own Id: OTP-14462</p> + </item> + </list> + </section> + +</section> + <section><title>Hipe 3.16</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/hipe/llvm/hipe_llvm.erl b/lib/hipe/llvm/hipe_llvm.erl index 641d3fda0a..ccd40162cb 100644 --- a/lib/hipe/llvm/hipe_llvm.erl +++ b/lib/hipe/llvm/hipe_llvm.erl @@ -1005,11 +1005,12 @@ pp_ins(Dev, Ver, I) -> write(Dev, [" ", adj_stack_offset(I),")\n"]); #llvm_meta{} -> write(Dev, ["!", meta_id(I), " = !{ "]), - write(Dev, string:join([if is_list(Op) -> ["!\"", Op, "\""]; - is_integer(Op) -> ["i32 ", integer_to_list(Op)]; - is_record(Op, llvm_meta) -> - ["!", meta_id(Op)] - end || Op <- meta_operands(I)], ", ")), + write(Dev, lists:join(", ", + [if is_list(Op) -> ["!\"", Op, "\""]; + is_integer(Op) -> ["i32 ", integer_to_list(Op)]; + is_record(Op, llvm_meta) -> + ["!", meta_id(Op)] + end || Op <- meta_operands(I)])), write(Dev, " }\n"); Other -> exit({?MODULE, pp_ins, {"Unknown LLVM instruction", Other}}) diff --git a/lib/hipe/llvm/hipe_llvm_main.erl b/lib/hipe/llvm/hipe_llvm_main.erl index 4eec0c752b..54c435c127 100644 --- a/lib/hipe/llvm/hipe_llvm_main.erl +++ b/lib/hipe/llvm/hipe_llvm_main.erl @@ -154,7 +154,7 @@ compiler_target_opt() -> %% @doc Join options. fix_opts(Opts) -> - string:join(Opts, " "). + lists:flatten(lists:join(" ", Opts)). %% @doc Translate optimization-level flag (default is "O2"). trans_optlev_flag(Tool, Options) -> diff --git a/lib/hipe/llvm/hipe_rtl_to_llvm.erl b/lib/hipe/llvm/hipe_rtl_to_llvm.erl index 79e1bfd381..934717efc1 100644 --- a/lib/hipe/llvm/hipe_rtl_to_llvm.erl +++ b/lib/hipe/llvm/hipe_rtl_to_llvm.erl @@ -1537,7 +1537,7 @@ declare_switch_table({Name, {switch, {TableType, Labels, _, _}, _}}, FunName) -> LabelList = [mk_jump_label(L) || L <- Labels], Fun1 = fun(X) -> "i8* blockaddress(@" ++ FunName ++ ", " ++ X ++ ")" end, List2 = lists:map(Fun1, LabelList), - List3 = string:join(List2, ",\n"), + List3 = lists:flatten(lists:join(",\n", List2)), List4 = "[\n" ++ List3 ++ "\n]\n", hipe_llvm:mk_const_decl("@" ++ Name, "constant", TableType, List4). @@ -1553,7 +1553,7 @@ declare_closure_labels(ClosureLabels, Relocs, Fun) -> Relocs1 = relocs_store("table_closures", {table_closures, ArityList}, Relocs), List2 = ["i8* blockaddress(@" ++ FunName ++ ", " ++ L ++ ")" || L <- LabelList], - List3 = string:join(List2, ",\n"), + List3 = lists:flatten(lists:join(",\n", List2)), List4 = "[\n" ++ List3 ++ "\n]\n", NrLabels = length(LabelList), ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(?BITS_IN_BYTE)), diff --git a/lib/hipe/main/hipe.app.src b/lib/hipe/main/hipe.app.src index 3c3a1004f1..5b2280594f 100644 --- a/lib/hipe/main/hipe.app.src +++ b/lib/hipe/main/hipe.app.src @@ -235,5 +235,5 @@ {registered,[]}, {applications, [kernel,stdlib]}, {env, []}, - {runtime_dependencies, ["syntax_tools-1.6.14","stdlib-2.5","kernel-3.0", + {runtime_dependencies, ["syntax_tools-1.6.14","stdlib-3.4","kernel-5.3", "erts-9.0","compiler-5.0"]}]}. diff --git a/lib/hipe/main/hipe.erl b/lib/hipe/main/hipe.erl index 19b4e8bfe2..f5f5bf5830 100644 --- a/lib/hipe/main/hipe.erl +++ b/lib/hipe/main/hipe.erl @@ -1616,11 +1616,11 @@ llvm_support_available() -> get_llvm_version() -> OptStr = os:cmd("opt -version"), SubStr = "LLVM version ", N = length(SubStr), - case string:str(OptStr, SubStr) of - 0 -> % No opt available + case string:find(OptStr, SubStr) of + nomatch -> % No opt available {0, 0}; S -> - case string:tokens(string:sub_string(OptStr, S + N), ".") of + case string:lexemes(string:slice(S, N), ".") of [MajorS, MinorS | _] -> case {string:to_integer(MajorS), string:to_integer(MinorS)} of {{Major, ""}, {Minor, _}} diff --git a/lib/hipe/test/hipe_testsuite_driver.erl b/lib/hipe/test/hipe_testsuite_driver.erl index 88576775ca..ee9c57a908 100644 --- a/lib/hipe/test/hipe_testsuite_driver.erl +++ b/lib/hipe/test/hipe_testsuite_driver.erl @@ -29,13 +29,9 @@ get_suites(SuitesWithSuiteSuffix) -> [S || {yes, S} <- Prefixes]. suffix(String, Suffix) -> - case string:rstr(String, Suffix) of - 0 -> no; - Index -> - case string:substr(String, Index) =:= Suffix of - true -> {yes, string:sub_string(String, 1, Index-1)}; - false -> no - end + case string:split(String, Suffix, trailing) of + [Prefix,[]] -> {yes, Prefix}; + _ -> no end. -spec file_type(file:filename()) -> {ok, file_type()} | {error, ext_posix()}. diff --git a/lib/hipe/test/opt_verify_SUITE.erl b/lib/hipe/test/opt_verify_SUITE.erl index 86083fa02b..24f43af275 100644 --- a/lib/hipe/test/opt_verify_SUITE.erl +++ b/lib/hipe/test/opt_verify_SUITE.erl @@ -44,7 +44,7 @@ call_elim(Config) -> Icode5 = call_elim_test_file(Config, F3, icode_call_elim), 0 = substring_count(binary:bin_to_list(Icode5), "is_key"), Icode6 = call_elim_test_file(Config, F3, no_icode_call_elim), - 3 = substring_count(binary:bin_to_list(Icode6), "is_key"), + 2 = substring_count(binary:bin_to_list(Icode6), "is_key"), ok. call_elim_test_file(Config, FileName, Option) -> @@ -59,7 +59,7 @@ call_elim_test_file(Config, FileName, Option) -> substring_count(Icode, Substring) -> substring_count(Icode, Substring, 0). substring_count(Icode, Substring, N) -> - case string:str(Icode, Substring) of - 0 -> N; - I -> substring_count(lists:nthtail(I, Icode), Substring, N+1) + case string:find(Icode, Substring) of + nomatch -> N; + Prefix -> substring_count(string:prefix(Prefix, Substring), Substring, N+1) end. diff --git a/lib/hipe/test/opt_verify_SUITE_data/call_elim_test_branches_opt_poss.erl b/lib/hipe/test/opt_verify_SUITE_data/call_elim_test_branches_opt_poss.erl index c8ddfa1e75..12875f41af 100644 --- a/lib/hipe/test/opt_verify_SUITE_data/call_elim_test_branches_opt_poss.erl +++ b/lib/hipe/test/opt_verify_SUITE_data/call_elim_test_branches_opt_poss.erl @@ -6,17 +6,11 @@ test(A) -> if A > 0 -> true = has_a_field(#{a=>true}), true = has_a_field(#{b=>1, a=>"2"}), - true = has_a_field(#{a=>5, c=>4}), - true = has_tuple_field(#{{ab, 1}=><<"qq">>, 1 =>0}), - true = has_tuple_field(#{up =>down, {ab, 1}=>[]}), - true = has_tuple_field(#{{ab, 1}=>42}); + true = has_a_field(#{a=>5, c=>4}); A =< 0 -> true = has_a_field(#{a=>q, 'A' =>nej}), true = has_a_field(#{a=>"hej", false=>true}), - true = has_a_field(#{a=>3}), - true = has_tuple_field(#{{ab, 1}=>q, 'A' =>nej}), - true = has_tuple_field(#{{ab, 1}=>"hej", false=>true}), - true = has_tuple_field(#{{ab, 1}=>3}) + true = has_a_field(#{a=>3}) end, true = has_nil_field(#{[] =>3, b =>"seven"}), true = has_nil_field(#{"seventeen"=>17, []=>nil}), diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk index 0ef4aa7f09..f88d9147b1 100644 --- a/lib/hipe/vsn.mk +++ b/lib/hipe/vsn.mk @@ -1 +1 @@ -HIPE_VSN = 3.16 +HIPE_VSN = 3.16.1 diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index c85600d0be..10ef84d7cf 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -33,7 +33,29 @@ <file>notes.xml</file> </header> - <section><title>Inets 6.4.1</title> + <section><title>Inets 6.4.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Make sure mod_log uses the correct status code</p> + <p> + Own Id: OTP-14510</p> + </item> + <item> + <p> + Correct behaviour of mod_disk_log to proparly handle + repair options</p> + <p> + Own Id: OTP-14530</p> + </item> + </list> + </section> + +</section> + +<section><title>Inets 6.4.1</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk index c4314f1ab5..34b6902747 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -19,6 +19,6 @@ # %CopyrightEnd% APPLICATION = inets -INETS_VSN = 6.4.1 +INETS_VSN = 6.4.2 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index 9cd03ffcad..a5316dd476 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,6 +31,50 @@ </header> <p>This document describes the changes made to the Kernel application.</p> +<section><title>Kernel 5.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Processes which did output after switching jobs (Ctrl+G) + could be left forever stuck in the io request.</p> + <p> + Own Id: OTP-14571 Aux Id: ERL-472 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>Lock counting can now be fully toggled at runtime in + the lock counting emulator (<c>-emu_type lcnt</c>). + Everything is enabled by default to match the old + behavior, but specific categories can be toggled at will + with minimal runtime overhead when disabled. Refer to the + documentation on <c>lcnt:rt_mask/1</c> for details.</p> + <p> + Own Id: OTP-13170</p> + </item> + <item> + <p><c>lcnt:collect</c> and <c>lcnt:clear</c> will no + longer block all other threads in the runtime system.</p> + <p> + Own Id: OTP-14412</p> + </item> + <item> + <p> + General Unicode improvements.</p> + <p> + Own Id: OTP-14462</p> + </item> + </list> + </section> + +</section> + <section><title>Kernel 5.3.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/kernel/src/erl_boot_server.erl b/lib/kernel/src/erl_boot_server.erl index ac81cc9689..2a38266579 100644 --- a/lib/kernel/src/erl_boot_server.erl +++ b/lib/kernel/src/erl_boot_server.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2016. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -253,9 +253,9 @@ handle_info({udp, U, IP, Port, Data}, S0) -> "~w is not a valid address ** ~n", [IP]), {noreply,S0}; {true,_,_} -> - case catch string:substr(Data, 1, length(?EBOOT_REQUEST)) of + case catch string:slice(Data, 0, length(?EBOOT_REQUEST)) of ?EBOOT_REQUEST -> - Vsn = string:substr(Data, length(?EBOOT_REQUEST)+1, length(Data)), + Vsn = string:slice(Data, length(?EBOOT_REQUEST), length(Data)), error_logger:error_msg("** Illegal boot server connection attempt: " "client version is ~s ** ~n", [Vsn]); _ -> diff --git a/lib/kernel/src/erl_reply.erl b/lib/kernel/src/erl_reply.erl index e1e046cbb4..e1c4ffe839 100644 --- a/lib/kernel/src/erl_reply.erl +++ b/lib/kernel/src/erl_reply.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -42,7 +42,7 @@ reply(_) -> %% convert ip number to tuple ip_string_to_tuple(Ip) -> - [Ip1,Ip2,Ip3,Ip4] = string:tokens(Ip,"."), + [Ip1,Ip2,Ip3,Ip4] = string:lexemes(Ip,"."), {list_to_integer(Ip1), list_to_integer(Ip2), list_to_integer(Ip3), diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl index f07ec52cfa..585507c545 100644 --- a/lib/kernel/src/error_logger.erl +++ b/lib/kernel/src/error_logger.erl @@ -499,16 +499,31 @@ display4(A = [_|_]) -> display4(A) -> erlang:display(A). - -string_p(Term) when is_list(Term) -> - string_p1(lists:flatten(Term)); -string_p(_Term) -> - false. - -string_p1([]) -> +string_p([]) -> false; -string_p1(FlatList) -> - io_lib:printable_list(FlatList). +string_p(Term) -> + string_p1(Term). + +string_p1([H|T]) when is_integer(H), H >= $\040, H =< $\176 -> + string_p1(T); +string_p1([H|T]) when is_integer(H), H >= 16#A0, H < 16#D800; + is_integer(H), H > 16#DFFF, H < 16#FFFE; + is_integer(H), H > 16#FFFF, H =< 16#10FFFF -> + string_p1(T); +string_p1([$\n|T]) -> string_p1(T); +string_p1([$\r|T]) -> string_p1(T); +string_p1([$\t|T]) -> string_p1(T); +string_p1([$\v|T]) -> string_p1(T); +string_p1([$\b|T]) -> string_p1(T); +string_p1([$\f|T]) -> string_p1(T); +string_p1([$\e|T]) -> string_p1(T); +string_p1([H|T]) when is_list(H) -> + case string_p1(H) of + true -> string_p1(T); + _ -> false + end; +string_p1([]) -> true; +string_p1(_) -> false. -spec limit_term(term()) -> term(). diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl index 480db6814e..2887014c1c 100644 --- a/lib/kernel/src/erts_debug.erl +++ b/lib/kernel/src/erts_debug.erl @@ -378,16 +378,11 @@ df(Mod, Func, Arity) when is_atom(Mod), is_atom(Func) -> catch _:_ -> {undef,Mod} end. -dff(File, Fs) when is_pid(File), is_list(Fs) -> - lists:foreach(fun(Mfa) -> - disassemble_function(File, Mfa), - io:nl(File) - end, Fs); -dff(Name, Fs) when is_list(Name) -> - case file:open(Name, [write]) of +dff(Name, Fs) -> + case file:open(Name, [write,raw,delayed_write]) of {ok,F} -> try - dff(F, Fs) + dff_1(F, Fs) after _ = file:close(F) end; @@ -395,12 +390,18 @@ dff(Name, Fs) when is_list(Name) -> {error,{badopen,Reason}} end. +dff_1(File, Fs) -> + lists:foreach(fun(Mfa) -> + disassemble_function(File, Mfa), + file:write(File, "\n") + end, Fs). + disassemble_function(File, {_,_,_}=MFA) -> cont_dis(File, erts_debug:disassemble(MFA), MFA). cont_dis(_, false, _) -> ok; cont_dis(File, {Addr,Str,MFA}, MFA) -> - io:put_chars(File, binary_to_list(Str)), + ok = file:write(File, Str), cont_dis(File, erts_debug:disassemble(Addr), MFA); cont_dis(_, {_,_,_}, _) -> ok. diff --git a/lib/kernel/src/group.erl b/lib/kernel/src/group.erl index bf785959ff..a5210901f2 100644 --- a/lib/kernel/src/group.erl +++ b/lib/kernel/src/group.erl @@ -793,9 +793,9 @@ search_up_stack(Stack, Substr) -> case up_stack(Stack) of {none,NewStack} -> {none,NewStack}; {L, NewStack} -> - case string:str(L, Substr) of - 0 -> search_up_stack(NewStack, Substr); - _ -> {string:strip(L,right,$\n), NewStack} + case string:find(L, Substr) of + nomatch -> search_up_stack(NewStack, Substr); + _ -> {string:trim(L, trailing, "$\n"), NewStack} end end. @@ -803,9 +803,9 @@ search_down_stack(Stack, Substr) -> case down_stack(Stack) of {none,NewStack} -> {none,NewStack}; {L, NewStack} -> - case string:str(L, Substr) of - 0 -> search_down_stack(NewStack, Substr); - _ -> {string:strip(L,right,$\n), NewStack} + case string:find(L, Substr) of + nomatch -> search_down_stack(NewStack, Substr); + _ -> {string:trim(L, trailing, "$\n"), NewStack} end end. diff --git a/lib/kernel/src/inet_config.erl b/lib/kernel/src/inet_config.erl index 4bbc520449..9f76360b8b 100644 --- a/lib/kernel/src/inet_config.erl +++ b/lib/kernel/src/inet_config.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -369,7 +369,7 @@ win32_load1(Reg,Type,HFileKey) -> end. win32_split_line(Line,nt) -> inet_parse:split_line(Line); -win32_split_line(Line,windows) -> string:tokens(Line, ","). +win32_split_line(Line,windows) -> string:lexemes(Line, ","). win32_get_strings(Reg, Names) -> win32_get_strings(Reg, Names, []). diff --git a/lib/kernel/src/inet_dns.erl b/lib/kernel/src/inet_dns.erl index d5f982cc51..f1f58bc872 100644 --- a/lib/kernel/src/inet_dns.erl +++ b/lib/kernel/src/inet_dns.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ -export([decode/1, encode/1]). --import(lists, [reverse/1, reverse/2, nthtail/2]). +-import(lists, [reverse/1]). -include("inet_int.hrl"). -include("inet_dns.hrl"). @@ -473,7 +473,7 @@ decode_data(<<Order:16,Preference:16,Data0/binary>>, _, ?S_NAPTR, Buffer) -> {Data2,Services} = decode_string(Data1), {Data,Regexp} = decode_characters(Data2, utf8), Replacement = decode_domain(Data, Buffer), - {Order,Preference,string:to_lower(Flags),string:to_lower(Services), + {Order,Preference,string:lowercase(Flags),string:lowercase(Services), Regexp,Replacement}; %% ?S_OPT falls through to default decode_data(Data, _, ?S_TXT, _) -> diff --git a/lib/kernel/src/inet_parse.erl b/lib/kernel/src/inet_parse.erl index 29804dc50b..e9685c6554 100644 --- a/lib/kernel/src/inet_parse.erl +++ b/lib/kernel/src/inet_parse.erl @@ -95,7 +95,7 @@ hosts(Fname,File) -> %% interface with a %if suffix. These kind of %% addresses maybe need to be gracefully handled %% throughout inet* and inet_drv. - case string:tokens(Address, "%") of + case string:lexemes(Address, "%") of [Addr,_] -> {ok,_} = address(Addr), skip; @@ -407,7 +407,7 @@ is_dom1([C | Cs]) when C >= $a, C =< $z -> is_dom_ldh(Cs); is_dom1([C | Cs]) when C >= $A, C =< $Z -> is_dom_ldh(Cs); is_dom1([C | Cs]) when C >= $0, C =< $9 -> case is_dom_ldh(Cs) of - true -> is_dom2(string:tokens([C | Cs],".")); + true -> is_dom2(string:lexemes([C | Cs],".")); false -> false end; is_dom1(_) -> false. diff --git a/lib/kernel/src/inet_res.erl b/lib/kernel/src/inet_res.erl index 90e49ddfdf..49aa5f8bda 100644 --- a/lib/kernel/src/inet_res.erl +++ b/lib/kernel/src/inet_res.erl @@ -859,15 +859,17 @@ query_ns(S0, Id, Buffer, IP, Port, Timer, Retry, I, {ok,S} -> Timeout = inet:timeout( (Tm * (1 bsl I)) div Retry, Timer), - {S, case query_udp( S, Id, Buffer, IP, Port, Timeout, Verbose) of {ok,#dns_rec{header=H}} when H#dns_header.tc -> TcpTimeout = inet:timeout(Tm*5, Timer), - query_tcp( - TcpTimeout, Id, Buffer, IP, Port, Verbose); - Reply -> Reply - end}; + {S, query_tcp( + TcpTimeout, Id, Buffer, IP, Port, Verbose)}; + {error, econnrefused} = Err -> + ok = udp_close(S), + {#sock{}, Err}; + Reply -> {S, Reply} + end; Error -> {S0,Error} end diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src index 2a11b04310..2a88cc7e26 100644 --- a/lib/kernel/src/kernel.app.src +++ b/lib/kernel/src/kernel.app.src @@ -120,6 +120,6 @@ {applications, []}, {env, [{error_logger, tty}]}, {mod, {kernel, []}}, - {runtime_dependencies, ["erts-9.1", "stdlib-3.0", "sasl-3.0"]} + {runtime_dependencies, ["erts-9.1", "stdlib-3.4", "sasl-3.0"]} ] }. diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl index 0250783632..209899d587 100644 --- a/lib/kernel/src/os.erl +++ b/lib/kernel/src/os.erl @@ -178,7 +178,7 @@ verify_executable(Name0, [Ext|Rest], OrigExtensions) -> end; verify_executable(Name, [], OrigExtensions) when OrigExtensions =/= [""] -> %% Windows %% Will only happen on windows, hence case insensitivity - case can_be_full_name(string:to_lower(Name),OrigExtensions) of + case can_be_full_name(string:lowercase(Name),OrigExtensions) of true -> verify_executable(Name,[""],[""]); _ -> diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl index 6f8e949aac..612f77149d 100644 --- a/lib/kernel/test/code_SUITE.erl +++ b/lib/kernel/test/code_SUITE.erl @@ -35,6 +35,7 @@ purge_stacktrace/1, mult_lib_roots/1, bad_erl_libs/1, code_archive/1, code_archive2/1, on_load/1, on_load_binary/1, on_load_embedded/1, on_load_errors/1, on_load_update/1, + on_load_trace_on_load/1, on_load_purge/1, on_load_self_call/1, on_load_pending/1, on_load_deleted/1, big_boot_embedded/1, @@ -66,14 +67,16 @@ all() -> ext_mod_dep, clash, where_is_file, purge_stacktrace, mult_lib_roots, bad_erl_libs, code_archive, code_archive2, on_load, - on_load_binary, on_load_embedded, on_load_errors, on_load_update, + on_load_binary, on_load_embedded, on_load_errors, + {group, sequence}, on_load_purge, on_load_self_call, on_load_pending, on_load_deleted, module_status, big_boot_embedded, native_early_modules, get_mode, normalized_paths]. -groups() -> - []. +%% These need to run in order +groups() -> [{sequence, [sequence], [on_load_update, + on_load_trace_on_load]}]. init_per_group(_GroupName, Config) -> Config. @@ -1493,7 +1496,7 @@ do_on_load_error(ReturnValue) -> {undef,[{on_load_error,main,[],_}|_]} = Exit end. -on_load_update(_Config) -> +on_load_update(Config) -> {Mod,Code1} = on_load_update_code(1), {module,Mod} = code:load_binary(Mod, "", Code1), 42 = Mod:a(), @@ -1503,7 +1506,7 @@ on_load_update(_Config) -> {Mod,Code2} = on_load_update_code(2), {error,on_load_failure} = code:load_binary(Mod, "", Code2), 42 = Mod:a(), - 100 = Mod:b(99), + 78 = Mod:b(77), {'EXIT',{undef,_}} = (catch Mod:never()), 4 = erlang:trace_pattern({Mod,'_','_'}, false), @@ -1514,6 +1517,9 @@ on_load_update(_Config) -> {'EXIT',{undef,_}} = (catch Mod:b(10)), {'EXIT',{undef,_}} = (catch Mod:never()), + code:purge(Mod), + code:delete(Mod), + code:purge(Mod), ok. on_load_update_code(Version) -> @@ -1545,6 +1551,40 @@ on_load_update_code_1(3, Mod) -> "f() -> ok.\n", "c() -> 100.\n"]). +%% Test -on_load while trace feature 'on_load' is enabled (OTP-14612) +on_load_trace_on_load(Config) -> + Papa = self(), + Tracer = spawn_link(fun F() -> receive M -> Papa ! M end, F() end), + {tracer,[]} = erlang:trace_info(self(),tracer), + erlang:trace(self(), true, [call, {tracer, Tracer}]), + erlang:trace_pattern(on_load, true, []), + on_load_update(Config), + erlang:trace_pattern(on_load, false, []), + erlang:trace(self(), false, [call]), + + %% WE GET TRACES FOR CALLS TO UNDEFINED FUNCTIONS ??? + %% Remove filter when that is fixed. + Ms = lists:filter(fun({trace,Papa,call, + {error_handler,undefined_function, + [on_load_update_code,_,_]}}) + -> false; + (_) -> true + end, + flush()), + + [{trace, Papa, call, {on_load_update_code, a, []}}, + {trace, Papa, call, {on_load_update_code, b, [99]}}, + {trace, Papa, call, {on_load_update_code, c, []}}] = Ms, + + exit(Tracer, normal), + ok. + +flush() -> + receive M -> [M | flush()] + after 100 -> [] + end. + + on_load_purge(_Config) -> Mod = ?FUNCTION_NAME, register(Mod, self()), diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index c9463241d1..cef54dd41a 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 5.3.1 +KERNEL_VSN = 5.4 diff --git a/lib/mnesia/doc/src/Mnesia_chap5.xmlsrc b/lib/mnesia/doc/src/Mnesia_chap5.xmlsrc index 62759c624b..0265e0efa0 100644 --- a/lib/mnesia/doc/src/Mnesia_chap5.xmlsrc +++ b/lib/mnesia/doc/src/Mnesia_chap5.xmlsrc @@ -226,8 +226,10 @@ not known beforehand, all fragments are searched for matching records.</p> <p>Notice that in <c>ordered_set</c> tables, the records - are ordered per fragment, and the the order is undefined in - results returned by <c>select</c> and <c>match_object</c>.</p> + are ordered per fragment, and the order is undefined in + results returned by <c>select</c> and <c>match_object</c>, + as well as <c>first</c>, <c>next</c>, <c>prev</c> and + <c>last</c>.</p> <p>The following code illustrates how a <c>Mnesia</c> table is converted to be a fragmented table and how more fragments are added later:</p> diff --git a/lib/mnesia/doc/src/company.erl b/lib/mnesia/doc/src/company.erl index 20e3235347..5a3b122394 100644 --- a/lib/mnesia/doc/src/company.erl +++ b/lib/mnesia/doc/src/company.erl @@ -19,7 +19,12 @@ %% -module(company). --compile(export_all). +-export([init/0,insert_emp/3,mk_projs/2,females/0,all_females/0, + g/0,female_bosses/0, raise_females/1, over_write/2, raise/2, + bad_raise/2, get_emps/2, get_emps2/2, filter/2, filter_deps/3, + search_deps/3, bench1/0, dotimes/2, dist_init/0, remove_proj/1, + del_in_projs/1, sync/0, tabs/0, find_male_on_second_floor/0, + panic/1, fill_tables/0]). %0 diff --git a/lib/mnesia/doc/src/company_o.erl b/lib/mnesia/doc/src/company_o.erl index 7300e9d4bb..650b6cdeca 100644 --- a/lib/mnesia/doc/src/company_o.erl +++ b/lib/mnesia/doc/src/company_o.erl @@ -19,7 +19,11 @@ %% -module(company_o). --compile(export_all). + +-export([sinit/0, init/0,insert_emp/3,females/0, + female_bosses/0, raise_females/1, over_write/2, raise/2, + bad_raise/2, get_emps/2, get_emps2/2]). + -import(mnesia, [transaction/1]). diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml index 3ca4026190..e9243f7fc9 100644 --- a/lib/mnesia/doc/src/notes.xml +++ b/lib/mnesia/doc/src/notes.xml @@ -39,7 +39,22 @@ thus constitutes one section in this document. The title of each section is the version number of Mnesia.</p> - <section><title>Mnesia 4.15</title> + <section><title>Mnesia 4.15.1</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + General Unicode improvements.</p> + <p> + Own Id: OTP-14462</p> + </item> + </list> + </section> + +</section> + +<section><title>Mnesia 4.15</title> <section><title>Improvements and New Features</title> <list> diff --git a/lib/mnesia/src/mnesia.app.src b/lib/mnesia/src/mnesia.app.src index 6b49fc6c88..c755b4d4b9 100644 --- a/lib/mnesia/src/mnesia.app.src +++ b/lib/mnesia/src/mnesia.app.src @@ -49,4 +49,4 @@ ]}, {applications, [kernel, stdlib]}, {mod, {mnesia_app, []}}, - {runtime_dependencies, ["stdlib-2.0","kernel-3.0","erts-7.0"]}]}. + {runtime_dependencies, ["stdlib-3.4","kernel-5.3","erts-9.0"]}]}. diff --git a/lib/mnesia/test/mnesia_SUITE.erl b/lib/mnesia/test/mnesia_SUITE.erl index 3ec4847c5d..279744dbb0 100644 --- a/lib/mnesia/test/mnesia_SUITE.erl +++ b/lib/mnesia/test/mnesia_SUITE.erl @@ -21,7 +21,12 @@ %% -module(mnesia_SUITE). -author('[email protected]'). --compile([export_all]). +-export([init_per_testcase/2, end_per_testcase/2, + init_per_suite/1, end_per_suite/1, + init_per_group/2, end_per_group/2, + suite/0, all/0, groups/0]). +-export([app/1, appup/1, clean_up_suite/1, silly/0]). + -include_lib("common_test/include/ct.hrl"). -include("mnesia_test_lib.hrl"). @@ -92,16 +97,8 @@ groups() -> %% benchmarks {heavy, [], [{group, measure}]}, {measure, [], [{mnesia_measure_test, all}]}, - {prediction, [], - [{group, mnesia_measure_test, prediction}]}, - {fairness, [], - [{group, mnesia_measure_test, fairness}]}, {benchmarks, [], [{group, mnesia_measure_test, benchmarks}]}, - {consumption, [], - [{group, mnesia_measure_test, consumption}]}, - {scalability, [], - [{group, mnesia_measure_test, scalability}]}, %% This test suite is an extract of the grand Mnesia suite %% it contains OTP R4B specific test cases {otp_r4b, [], diff --git a/lib/mnesia/test/mnesia_atomicity_test.erl b/lib/mnesia/test/mnesia_atomicity_test.erl index cc32ba3826..58a5dc1d40 100644 --- a/lib/mnesia/test/mnesia_atomicity_test.erl +++ b/lib/mnesia/test/mnesia_atomicity_test.erl @@ -22,9 +22,37 @@ -module(mnesia_atomicity_test). -author('[email protected]'). -author('[email protected]'). --compile([export_all]). -include("mnesia_test_lib.hrl"). +-export([init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2, + all/0, groups/0]). +-export([explicit_abort_in_middle_of_trans/1, + runtime_error_in_middle_of_trans/1, + mnesia_down_during_infinite_trans/1, + kill_self_in_middle_of_trans/1, throw_in_middle_of_trans/1, + lock_waiter_sw_r/1, lock_waiter_sw_rt/1, lock_waiter_sw_wt/1, + lock_waiter_wr_r/1, lock_waiter_srw_r/1, lock_waiter_sw_sw/1, + lock_waiter_sw_w/1, lock_waiter_sw_wr/1, lock_waiter_sw_srw/1, + lock_waiter_wr_wt/1, lock_waiter_srw_wt/1, + lock_waiter_wr_sw/1, lock_waiter_srw_sw/1, lock_waiter_wr_w/1, + lock_waiter_srw_w/1, lock_waiter_r_sw/1, lock_waiter_r_w/1, + lock_waiter_r_wt/1, lock_waiter_rt_sw/1, lock_waiter_rt_w/1, + lock_waiter_rt_wt/1, lock_waiter_wr_wr/1, + lock_waiter_srw_srw/1, lock_waiter_wt_r/1, lock_waiter_wt_w/1, + lock_waiter_wt_rt/1, lock_waiter_wt_wt/1, lock_waiter_wt_wr/1, + lock_waiter_wt_srw/1, lock_waiter_wt_sw/1, lock_waiter_w_wr/1, + lock_waiter_w_srw/1, lock_waiter_w_sw/1, lock_waiter_w_r/1, + lock_waiter_w_w/1, lock_waiter_w_rt/1, lock_waiter_w_wt/1, + restart_r_one/1, restart_w_one/1, restart_rt_one/1, + restart_wt_one/1, restart_wr_one/1, restart_sw_one/1, + restart_r_two/1, restart_w_two/1, restart_rt_two/1, + restart_wt_two/1, restart_wr_two/1, restart_sw_two/1 + ] + ). + +-export([perform_restarted_transaction/1, sync_tid_release/0]). + init_per_testcase(Func, Conf) -> mnesia_test_lib:init_per_testcase(Func, Conf). diff --git a/lib/mnesia/test/mnesia_bench_SUITE.erl b/lib/mnesia/test/mnesia_bench_SUITE.erl index 7c86db383d..5cc01867c4 100644 --- a/lib/mnesia/test/mnesia_bench_SUITE.erl +++ b/lib/mnesia/test/mnesia_bench_SUITE.erl @@ -21,7 +21,13 @@ %% -module(mnesia_bench_SUITE). -author('[email protected]'). --compile(export_all). + +-export([init_per_testcase/2, end_per_testcase/2, + init_per_suite/1, end_per_suite/1, + init_per_group/2, end_per_group/2, + suite/0, all/0, groups/0]). + +-export([tpcb_conflict_ramcopies/1, tpcb_conflict_disk_only_copies/1]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% suite() -> [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}]. diff --git a/lib/mnesia/test/mnesia_consistency_test.erl b/lib/mnesia/test/mnesia_consistency_test.erl index 2fe1bd34e6..7a2678cee3 100644 --- a/lib/mnesia/test/mnesia_consistency_test.erl +++ b/lib/mnesia/test/mnesia_consistency_test.erl @@ -21,7 +21,78 @@ %% -module(mnesia_consistency_test). -author('[email protected]'). --compile([export_all]). + +-export([init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2, + all/0, groups/0]). + +-export([consistency_after_change_table_copy_type/1, + consistency_after_rename_of_node/1, + consistency_after_restart_1_ram/1, + consistency_after_restart_1_disc/1, + consistency_after_restart_1_disc_only/1, + consistency_after_restart_2_ram/1, + consistency_after_restart_2_disc/1, + consistency_after_restart_2_disc_only/1, + consistency_after_dump_tables_1_ram/1, + consistency_after_dump_tables_2_ram/1, + consistency_after_add_replica_2_ram/1, + consistency_after_add_replica_2_disc/1, + consistency_after_add_replica_2_disc_only/1, + consistency_after_add_replica_3_ram/1, + consistency_after_add_replica_3_disc/1, + consistency_after_add_replica_3_disc_only/1, + consistency_after_del_replica_2_ram/1, + consistency_after_del_replica_2_disc/1, + consistency_after_del_replica_2_disc_only/1, + consistency_after_del_replica_3_ram/1, + consistency_after_del_replica_3_disc/1, + consistency_after_del_replica_3_disc_only/1, + consistency_after_move_replica_2_ram/1, + consistency_after_move_replica_2_disc/1, + consistency_after_move_replica_2_disc_only/1, + consistency_after_move_replica_3_ram/1, + consistency_after_move_replica_3_disc/1, + consistency_after_move_replica_3_disc_only/1, + consistency_after_transform_table_ram/1, + consistency_after_transform_table_disc/1, + consistency_after_transform_table_disc_only/1, + consistency_after_fallback_2_ram/1, + consistency_after_fallback_2_disc/1, + consistency_after_fallback_2_disc_only/1, + consistency_after_fallback_3_ram/1, + consistency_after_fallback_3_disc/1, + consistency_after_fallback_3_disc_only/1, + consistency_after_restore_clear_ram/1, + consistency_after_restore_clear_disc/1, + consistency_after_restore_clear_disc_only/1, + consistency_after_restore_recreate_ram/1, + consistency_after_restore_recreate_disc/1, + consistency_after_restore_recreate_disc_only/1, + updates_during_checkpoint_activation_1_ram/1, + updates_during_checkpoint_activation_1_disc/1, + updates_during_checkpoint_activation_1_disc_only/1, + updates_during_checkpoint_activation_2_ram/1, + updates_during_checkpoint_activation_2_disc/1, + updates_during_checkpoint_activation_2_disc_only/1, + updates_during_checkpoint_activation_3_ram/1, + updates_during_checkpoint_activation_3_disc/1, + updates_during_checkpoint_activation_3_disc_only/1, + updates_during_checkpoint_iteration_2_ram/1, + updates_during_checkpoint_iteration_2_disc/1, + updates_during_checkpoint_iteration_2_disc_only/1, + load_table_with_activated_checkpoint_ram/1, + load_table_with_activated_checkpoint_disc/1, + load_table_with_activated_checkpoint_disc_only/1, + add_table_copy_to_table_checkpoint_ram/1, + add_table_copy_to_table_checkpoint_disc/1, + add_table_copy_to_table_checkpoint_disc_only/1, + inst_fallback_process_dies/1, fatal_when_inconsistency/1, + after_delete/1,cause_switch_before/1, cause_switch_after/1, + cause_abort_before/1, cause_abort_after/1, + change_schema_before/1, change_schema_after/1]). + +-export([change_tab/3]). -include("mnesia_test_lib.hrl"). diff --git a/lib/mnesia/test/mnesia_cost.erl b/lib/mnesia/test/mnesia_cost.erl index a3fc8dfe20..4d0dd7b0ee 100644 --- a/lib/mnesia/test/mnesia_cost.erl +++ b/lib/mnesia/test/mnesia_cost.erl @@ -20,7 +20,7 @@ %% -module(mnesia_cost). --compile(export_all). +-export([go/0, go/1]). %% This code exercises the mnesia system and produces a bunch %% of measurements on what various things cost @@ -156,64 +156,3 @@ do_dirty(I, F) when I /= 0 -> F(), do_dirty(I-1, F); do_dirty(_,_) -> ok. - - - -table_load([N1,N2| _ ] = Ns) -> - Nodes = [N1,N2], - rpc:multicall(Ns, mnesia, lkill, []), - ok = mnesia:delete_schema(Ns), - ok = mnesia:create_schema(Nodes), - rpc:multicall(Nodes, mnesia, start, []), - TabDef = [{disc_copies,[N1]},{ram_copies,[N2]}, - {attributes,record_info(fields,item)},{record_name,item}], - Tabs = [list_to_atom("tab" ++ integer_to_list(I)) || I <- lists:seq(1,400)], - - [mnesia:create_table(Tab,TabDef) || Tab <- Tabs], - -%% InitTab = fun(Tab) -> -%% mnesia:write_lock_table(Tab), -%% InitRec = fun(Key) -> mnesia:write(Tab,#item{a=Key},write) end, -%% lists:foreach(InitRec, lists:seq(1,100)) -%% end, -%% -%% {Time,{atomic,ok}} = timer:tc(mnesia,transaction, [fun() ->lists:foreach(InitTab, Tabs) end]), - mnesia:dump_log(), -%% io:format("Init took ~p msec ~n", [Time/1000]), - rpc:call(N2, mnesia, stop, []), timer:sleep(1000), - mnesia:stop(), timer:sleep(500), - %% Warmup - ok = mnesia:start([{no_table_loaders, 1}]), - timer:tc(mnesia, wait_for_tables, [Tabs, infinity]), - mnesia:dump_log(), - rpc:call(N2, mnesia, dump_log, []), - io:format("Initialized ~n",[]), - - mnesia:stop(), timer:sleep(1000), - ok = mnesia:start([{no_table_loaders, 1}]), - {T1, ok} = timer:tc(mnesia, wait_for_tables, [Tabs, infinity]), - io:format("Loading from disc with 1 loader ~p msec~n",[T1/1000]), - mnesia:stop(), timer:sleep(1000), - ok = mnesia:start([{no_table_loaders, 4}]), - {T2, ok} = timer:tc(mnesia, wait_for_tables, [Tabs, infinity]), - io:format("Loading from disc with 4 loader ~p msec~n",[T2/1000]), - - %% Warmup - rpc:call(N2, ?MODULE, remote_load, [Tabs,4]), - io:format("Initialized ~n",[]), - - - T3 = rpc:call(N2, ?MODULE, remote_load, [Tabs,1]), - io:format("Loading from net with 1 loader ~p msec~n",[T3/1000]), - - T4 = rpc:call(N2, ?MODULE, remote_load, [Tabs,4]), - io:format("Loading from net with 4 loader ~p msec~n",[T4/1000]), - - ok. - -remote_load(Tabs,Loaders) -> - ok = mnesia:start([{no_table_loaders, Loaders}]), -%% io:format("~p ~n", [mnesia_controller:get_info(500)]), - {Time, ok} = timer:tc(mnesia, wait_for_tables, [Tabs, infinity]), - timer:sleep(1000), mnesia:stop(), timer:sleep(1000), - Time. diff --git a/lib/mnesia/test/mnesia_dirty_access_test.erl b/lib/mnesia/test/mnesia_dirty_access_test.erl index 6d970ac990..92124ebc65 100644 --- a/lib/mnesia/test/mnesia_dirty_access_test.erl +++ b/lib/mnesia/test/mnesia_dirty_access_test.erl @@ -21,9 +21,37 @@ %% -module(mnesia_dirty_access_test). -author('[email protected]'). --compile([export_all]). -include("mnesia_test_lib.hrl"). +-export([init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2, + all/0, groups/0]). + +-export([dirty_write_ram/1, dirty_write_disc/1, dirty_write_disc_only/1, dirty_write_xets/1, + dirty_read_ram/1, dirty_read_disc/1, dirty_read_disc_only/1, dirty_read_xets/1, + dirty_update_counter_ram/1, dirty_update_counter_disc/1, + dirty_update_counter_disc_only/1, dirty_update_counter_xets/1, + dirty_delete_ram/1, dirty_delete_disc/1, dirty_delete_disc_only/1, dirty_delete_xets/1, + dirty_delete_object_ram/1, dirty_delete_object_disc/1, + dirty_delete_object_disc_only/1, dirty_delete_object_xets/1, + dirty_match_object_ram/1, dirty_match_object_disc/1, + dirty_match_object_disc_only/1, dirty_match_object_xets/1, + dirty_index_match_object_ram/1, dirty_index_match_object_disc/1, + dirty_index_match_object_disc_only/1, dirty_index_match_object_xets/1, + dirty_index_read_ram/1, dirty_index_read_disc/1, + dirty_index_read_disc_only/1, dirty_index_read_xets/1, + dirty_index_update_set_ram/1, dirty_index_update_set_disc/1, + dirty_index_update_set_disc_only/1, dirty_index_update_set_xets/1, + dirty_index_update_bag_ram/1, dirty_index_update_bag_disc/1, + dirty_index_update_bag_disc_only/1, dirty_index_update_bag_xets/1, + dirty_iter_ram/1, dirty_iter_disc/1, dirty_iter_disc_only/1,dirty_iter_xets/1, + del_table_copy_1/1, del_table_copy_2/1, del_table_copy_3/1, + add_table_copy_1/1, add_table_copy_2/1, add_table_copy_3/1, + add_table_copy_4/1, move_table_copy_1/1, move_table_copy_2/1, + move_table_copy_3/1, move_table_copy_4/1]). + +-export([update_trans/3]). + init_per_testcase(Func, Conf) -> mnesia_test_lib:init_per_testcase(Func, Conf). diff --git a/lib/mnesia/test/mnesia_durability_test.erl b/lib/mnesia/test/mnesia_durability_test.erl index 97bc84a2d8..2fac5cac82 100644 --- a/lib/mnesia/test/mnesia_durability_test.erl +++ b/lib/mnesia/test/mnesia_durability_test.erl @@ -21,7 +21,33 @@ %% -module(mnesia_durability_test). -author('[email protected]'). --compile([export_all]). + +-export([init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2, + all/0, groups/0]). + +-export([durability_of_disc_copies/1, + durability_of_disc_only_copies/1, + load_latest_data/1, load_local_contents_directly/1, + load_directly_when_all_are_ram_copiesA/1, + load_directly_when_all_are_ram_copiesB/1, + load_when_last_replica_becomes_available/1, + load_when_down_from_all_other_replica_nodes/1, + late_load_transforms_into_disc_load/1, + late_load_leads_to_hanging/1, + force_load_when_nobody_intents_to_load/1, + force_load_when_someone_has_decided_to_load/1, + force_load_when_someone_else_has_loaded/1, + force_load_when_we_has_loaded/1, + force_load_on_a_non_local_table/1, + force_load_when_the_table_does_not_exist/1, + late_load_all_ram_cs_ram_nodes1/1, + late_load_all_ram_cs_ram_nodes2/1, + master_nodes/1, starting_master_nodes/1, + master_on_non_local_tables/1, + remote_force_load_with_local_master_node/1, + dump_ram_copies/1, dump_disc_copies/1, dump_disc_only/1]). + -include("mnesia_test_lib.hrl"). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/mnesia/test/mnesia_evil_backup.erl b/lib/mnesia/test/mnesia_evil_backup.erl index 0fa72c4305..45b11f2f3f 100644 --- a/lib/mnesia/test/mnesia_evil_backup.erl +++ b/lib/mnesia/test/mnesia_evil_backup.erl @@ -28,10 +28,23 @@ -module(mnesia_evil_backup). -author('[email protected]'). --compile(export_all). -include("mnesia_test_lib.hrl"). -%%-export([Function/Arity, ...]). +-export([init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2, + all/0, groups/0]). + +-export([backup/1, bad_backup/1, global_backup_checkpoint/1, + traverse_backup/1, + selective_backup_checkpoint/1, + incremental_backup_checkpoint/1, install_fallback/1, + uninstall_fallback/1, local_fallback/1, + sops_with_checkpoint/1, + restore_errors/1, restore_clear/1, restore_keep/1, + restore_recreate/1, restore_clear_ram/1 + ]). + +-export([check_tab/2]). init_per_testcase(Func, Conf) -> mnesia_test_lib:init_per_testcase(Func, Conf). diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl index 6e34040bc4..074967469b 100644 --- a/lib/mnesia/test/mnesia_evil_coverage_test.erl +++ b/lib/mnesia/test/mnesia_evil_coverage_test.erl @@ -23,7 +23,32 @@ -author('[email protected]'). -include("mnesia_test_lib.hrl"). --compile([export_all]). +-export([init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2, + all/0, groups/0]). + +-export([system_info/1, table_info/1, error_description/1, + db_node_lifecycle/1, evil_delete_db_node/1, start_and_stop/1, + checkpoint/1, table_lifecycle/1, storage_options/1, + add_copy_conflict/1, add_copy_when_going_down/1, + replica_management/1, clear_table_during_load/1, + schema_availability/1, local_content/1, + replica_location/1, user_properties/1, unsupp_user_props/1, + sorted_ets/1, + change_table_access_mode/1, change_table_load_order/1, + set_master_nodes/1, offline_set_master_nodes/1, + dump_tables/1, dump_log/1, wait_for_tables/1, force_load_table/1, + snmp_open_table/1, snmp_close_table/1, snmp_get_next_index/1, + snmp_get_row/1, snmp_get_mnesia_key/1, snmp_update_counter/1, + snmp_order/1, subscribe_standard/1, subscribe_extended/1, + foldl/1, info/1, schema_0/1, schema_1/1, view_0/1, view_1/1, view_2/1, + lkill/1, kill/1, + record_name_dirty_access_ram/1, + record_name_dirty_access_disc/1, + record_name_dirty_access_disc_only/1, + record_name_dirty_access_xets/1]). + +-export([info_check/8]). -define(cleanup(N, Config), mnesia_test_lib:prepare_test_case([{reload_appls, [mnesia]}], diff --git a/lib/mnesia/test/mnesia_examples_test.erl b/lib/mnesia/test/mnesia_examples_test.erl index 808e62d9c2..f1259abf90 100644 --- a/lib/mnesia/test/mnesia_examples_test.erl +++ b/lib/mnesia/test/mnesia_examples_test.erl @@ -21,7 +21,14 @@ %% -module(mnesia_examples_test). -author('[email protected]'). --compile([export_all]). +-export([init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2, + all/0, groups/0]). +-export([bup/1, company/1, meter/1, + replica_test/1, sticky_replica_test/1, dist_test/1, + conflict_test/1, frag_test/1, frag2_test/1, remote_test/1, + remote_frag2_test/1, opt_load/1]). + -include("mnesia_test_lib.hrl"). init_per_testcase(Func, Conf) -> diff --git a/lib/mnesia/test/mnesia_frag_test.erl b/lib/mnesia/test/mnesia_frag_test.erl index 9f2102beb2..7371792fda 100644 --- a/lib/mnesia/test/mnesia_frag_test.erl +++ b/lib/mnesia/test/mnesia_frag_test.erl @@ -23,7 +23,17 @@ -author('[email protected]'). -include("mnesia_test_lib.hrl"). --compile([export_all]). +-export([init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2, + all/0, groups/0]). + + +-export([nice_single/1, nice_multi/1, nice_access/1, iter_access/1, + consistency/1, evil_create/1, evil_delete/1, evil_change/1, evil_combine/1, + evil_loop/1, evil_delete_db_node/1]). + + +-export([frag_dist/1]). init_per_testcase(Func, Conf) -> mnesia_test_lib:init_per_testcase(Func, Conf). @@ -845,16 +855,7 @@ frag_rec_dist(Tab) -> Fun = fun() -> mnesia:table_info(Tab, frag_size) end, [Size || {_, Size} <- mnesia:activity(sync_dirty, Fun, mnesia_frag)]. -table_size(Tab) -> - Node = mnesia:table_info(Tab, where_to_read), - rpc:call(Node, mnesia, table_info, [Tab, size]). - sort_res(List) when is_list(List) -> lists:sort(List); sort_res(Else) -> Else. - -rev_res(List) when is_list(List) -> - lists:reverse(List); -rev_res(Else) -> - Else. diff --git a/lib/mnesia/test/mnesia_install_test.erl b/lib/mnesia/test/mnesia_install_test.erl index 103f85b3d6..3f67396eb0 100644 --- a/lib/mnesia/test/mnesia_install_test.erl +++ b/lib/mnesia/test/mnesia_install_test.erl @@ -21,8 +21,13 @@ %% -module(mnesia_install_test). -author('[email protected]'). +-export([init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2, + all/0, groups/0]). + +-export([silly_durability/1, silly_move/1, silly_upgrade/1, conflict/1, dist/1, + silly/0, silly2/1]). --compile([export_all]). -include("mnesia_test_lib.hrl"). init_per_testcase(Func, Conf) -> diff --git a/lib/mnesia/test/mnesia_isolation_test.erl b/lib/mnesia/test/mnesia_isolation_test.erl index 63940ec05c..1c3ea5ec92 100644 --- a/lib/mnesia/test/mnesia_isolation_test.erl +++ b/lib/mnesia/test/mnesia_isolation_test.erl @@ -22,7 +22,36 @@ -module(mnesia_isolation_test). -author('[email protected]'). --compile([export_all]). +-export([init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2, + all/0, groups/0]). + +-export([no_conflict/1, simple_queue_conflict/1, + advanced_queue_conflict/1, simple_deadlock_conflict/1, + advanced_deadlock_conflict/1, schema_deadlock/1, lock_burst/1, + nasty/1, basic_sticky_functionality/1, + unbound1/1, unbound2/1, + create_table/1, delete_table/1, move_table_copy/1, + add_table_index/1, del_table_index/1, transform_table/1, + snmp_open_table/1, snmp_close_table/1, + change_table_copy_type/1, change_table_access/1, + add_table_copy/1, del_table_copy/1, dump_tables/1, + del_table_copy_1/1, del_table_copy_2/1, del_table_copy_3/1, + add_table_copy_1/1, add_table_copy_2/1, add_table_copy_3/1, + add_table_copy_4/1, move_table_copy_1/1, move_table_copy_2/1, + move_table_copy_3/1, move_table_copy_4/1, + dirty_updates_visible_direct/1, + dirty_reads_regardless_of_trans/1, + trans_update_invisibible_outside_trans/1, + trans_update_visible_inside_trans/1, write_shadows/1, + delete_shadows/1, write_delete_shadows_bag/1, + write_delete_shadows_bag2/1, + shadow_search/1, snmp_shadows/1, + rr_kill_copy/1, foldl/1, first_next/1]). + +-export([do_fun/4, burst_counter/3, burst_incr/2, get_held/0, get_info/1, + get_sticky/0, op/4, update_own/3, update_shared/3]). + -include("mnesia_test_lib.hrl"). init_per_testcase(Func, Conf) -> @@ -668,16 +697,6 @@ unbound2(Config) when is_list(Config) -> {B, {atomic, [{ul,{key,{17,42}},val}]}}]), ok. -receiver() -> - receive - {_Pid, begin_trans} -> - receiver(); - Else -> - Else - after - 10000 -> - timeout - end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/mnesia/test/mnesia_majority_test.erl b/lib/mnesia/test/mnesia_majority_test.erl index 9811de6ae7..eb82617b60 100644 --- a/lib/mnesia/test/mnesia_majority_test.erl +++ b/lib/mnesia/test/mnesia_majority_test.erl @@ -21,7 +21,13 @@ %% -module(mnesia_majority_test). -author('[email protected]'). --compile(export_all). +-export([init_per_testcase/2, end_per_testcase/2, + all/0]). + +-export([write/1, wread/1, delete/1, clear_table/1, frag/1, + change_majority/1, frag_change_majority/1 + ]). + -include("mnesia_test_lib.hrl"). init_per_testcase(Func, Conf) -> diff --git a/lib/mnesia/test/mnesia_measure_test.erl b/lib/mnesia/test/mnesia_measure_test.erl index ad71fafecb..4e63eaee22 100644 --- a/lib/mnesia/test/mnesia_measure_test.erl +++ b/lib/mnesia/test/mnesia_measure_test.erl @@ -21,7 +21,15 @@ %% -module(mnesia_measure_test). -author('[email protected]'). --compile([export_all]). + +-export([init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2, + all/0, groups/0]). + +-export([cost/1, dbn_meters/1, + ram_tpcb/1, disc_tpcb/1, disc_only_tpcb/1, + ram_meter/1, disc_meter/1, disc_only_meter/1]). + -include("mnesia_test_lib.hrl"). @@ -39,41 +47,12 @@ end_per_testcase(Func, Conf) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% all() -> - [{group, prediction}, {group, consumption}, - {group, scalability}, {group, benchmarks}]. + [{group, benchmarks}]. groups() -> - [{prediction, [], - [reader_disturbed_by_node_down, - writer_disturbed_by_node_down, - reader_disturbed_by_node_up, - writer_disturbed_by_node_up, - reader_disturbed_by_schema_ops, - writer_disturbed_by_schema_ops, - reader_disturbed_by_checkpoint, - writer_disturbed_by_checkpoint, - reader_disturbed_by_dump_log, - writer_disturbed_by_dump_log, - reader_disturbed_by_backup, writer_disturbed_by_backup, - reader_disturbed_by_restore, - writer_disturbed_by_restore, {group, fairness}]}, - {fairness, [], - [reader_competing_with_reader, - reader_competing_with_writer, - writer_competing_with_reader, - writer_competing_with_writer]}, - {consumption, [], - [measure_resource_consumption, - determine_resource_leakage]}, - {scalability, [], - [determine_system_limits, performance_at_min_config, - performance_at_max_config, performance_at_full_load, - resource_consumption_at_min_config, - resource_consumption_at_max_config, - resource_consumption_at_full_load]}, - {benchmarks, [], + [{benchmarks, [], [{group, meter}, cost, dbn_meters, - measure_all_api_functions, {group, tpcb}]}, + {group, tpcb}]}, {tpcb, [], [ram_tpcb, disc_tpcb, disc_only_tpcb]}, {meter, [], [ram_meter, disc_meter, disc_only_meter]}]. diff --git a/lib/mnesia/test/mnesia_nice_coverage_test.erl b/lib/mnesia/test/mnesia_nice_coverage_test.erl index ffbe36e48d..7c96d6e6a0 100644 --- a/lib/mnesia/test/mnesia_nice_coverage_test.erl +++ b/lib/mnesia/test/mnesia_nice_coverage_test.erl @@ -21,7 +21,13 @@ %% -module(mnesia_nice_coverage_test). -author('[email protected]'). --compile([export_all]). + +-export([init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2, + all/0, groups/0]). + +-export([nice/1]). + -include("mnesia_test_lib.hrl"). -record(nice_tab, {key, val}). diff --git a/lib/mnesia/test/mnesia_qlc_test.erl b/lib/mnesia/test/mnesia_qlc_test.erl index 5067e86521..262a6b4abc 100644 --- a/lib/mnesia/test/mnesia_qlc_test.erl +++ b/lib/mnesia/test/mnesia_qlc_test.erl @@ -21,9 +21,18 @@ %% -module(mnesia_qlc_test). --compile(export_all). +-export([init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2, + all/0, groups/0]). + +-export([frag/1, info/1, mnesia_down/1, + dirty_nice_ram_copies/1, dirty_nice_disc_copies/1, + dirty_nice_disc_only_copies/1, + trans_nice_ram_copies/1, trans_nice_disc_copies/1, + trans_nice_disc_only_copies/1, atomic_eval/1, + nested_qlc/1 + ]). --export([all/0,groups/0,init_per_group/2,end_per_group/2]). -include("mnesia_test_lib.hrl"). -include_lib("stdlib/include/qlc.hrl"). diff --git a/lib/mnesia/test/mnesia_recovery_test.erl b/lib/mnesia/test/mnesia_recovery_test.erl index 130b87346f..82d6e6ac6a 100644 --- a/lib/mnesia/test/mnesia_recovery_test.erl +++ b/lib/mnesia/test/mnesia_recovery_test.erl @@ -21,7 +21,80 @@ %% -module(mnesia_recovery_test). -author('[email protected]'). --compile([export_all]). + +-export([init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2, + all/0, groups/0]). + +-export([coord_dies/1, after_full_disc_partition/1, + disc_less/1, garb_decision/1, + system_upgrade/1, + delete_during_start/1, + no_master_2/1, no_master_3/1, one_master_2/1, one_master_3/1, + two_master_2/1, two_master_3/1, all_master_2/1, + all_master_3/1, + dirty_read_during_down/1, trans_read_during_down/1, + mnesia_down_during_startup_disk_ram/1, + mnesia_down_during_startup_init_ram/1, + mnesia_down_during_startup_init_disc/1, + mnesia_down_during_startup_init_disc_only/1, + mnesia_down_during_startup_tm_ram/1, + mnesia_down_during_startup_tm_disc/1, + mnesia_down_during_startup_tm_disc_only/1, + with_checkpoint_same/1, with_checkpoint_other/1, + explicit_stop_during_snmp/1, + sym_trans_before_commit_kill_coord_node/1, + sym_trans_before_commit_kill_coord_pid/1, + sym_trans_before_commit_kill_part_after_ask/1, + sym_trans_before_commit_kill_part_before_ask/1, + sym_trans_after_commit_kill_coord_node/1, + sym_trans_after_commit_kill_coord_pid/1, + sym_trans_after_commit_kill_part_after_ask/1, + sym_trans_after_commit_kill_part_do_commit_pre/1, + sym_trans_after_commit_kill_part_do_commit_post/1, + sync_dirty_pre_kill_part/1, + sync_dirty_pre_kill_coord_node/1, + sync_dirty_pre_kill_coord_pid/1, + sync_dirty_post_kill_part/1, + sync_dirty_post_kill_coord_node/1, + sync_dirty_post_kill_coord_pid/1, + async_dirty_pre_kill_part/1, + async_dirty_pre_kill_coord_node/1, + async_dirty_pre_kill_coord_pid/1, + async_dirty_post_kill_part/1, + async_dirty_post_kill_coord_node/1, + async_dirty_post_kill_coord_pid/1, + asymtrans_part_ask/1, + asymtrans_part_commit_vote/1, + asymtrans_part_pre_commit/1, + asymtrans_part_log_commit/1, + asymtrans_part_do_commit/1, + asymtrans_coord_got_votes/1, + asymtrans_coord_pid_got_votes/1, + asymtrans_coord_log_commit_rec/1, + asymtrans_coord_pid_log_commit_rec/1, + asymtrans_coord_log_commit_dec/1, + asymtrans_coord_pid_log_commit_dec/1, + asymtrans_coord_rec_acc_pre_commit_log_commit/1, + asymtrans_coord_pid_rec_acc_pre_commit_log_commit/1, + asymtrans_coord_rec_acc_pre_commit_done_commit/1, + asymtrans_coord_pid_rec_acc_pre_commit_done_commit/1, + after_corrupt_files_decision_log_head/1, + after_corrupt_files_decision_log_tail/1, + after_corrupt_files_latest_log_head/1, + after_corrupt_files_latest_log_tail/1, + after_corrupt_files_table_dat_head/1, + after_corrupt_files_table_dat_tail/1, + after_corrupt_files_schema_dat_head/1, + after_corrupt_files_schema_dat_tail/1]). + +-export([reader/2, check/0, get_all_retainers/1, + verify_data/2, verify_where2read/1, + do_trans_loop/2, + start_stop/3, do_sym_trans/2, do_sync_dirty/2, do_async_dirty/2, + do_asym_trans/2, garb_handler/1, mymnesia_start/1 + ]). + -include("mnesia_test_lib.hrl"). -include_lib("kernel/include/file.hrl"). diff --git a/lib/mnesia/test/mnesia_registry_test.erl b/lib/mnesia/test/mnesia_registry_test.erl index 3df37a2c8c..08157f1be3 100644 --- a/lib/mnesia/test/mnesia_registry_test.erl +++ b/lib/mnesia/test/mnesia_registry_test.erl @@ -21,7 +21,12 @@ %% -module(mnesia_registry_test). -author('[email protected]'). --compile([export_all]). +-export([init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2, + all/0, groups/0]). + +-export([good_dump/1, bad_dump/1, dump_registry/2, restore_registry/2]). + -include("mnesia_test_lib.hrl"). init_per_testcase(Func, Conf) -> diff --git a/lib/mnesia/test/mnesia_schema_recovery_test.erl b/lib/mnesia/test/mnesia_schema_recovery_test.erl index ca2dd74b34..5e7627ca47 100644 --- a/lib/mnesia/test/mnesia_schema_recovery_test.erl +++ b/lib/mnesia/test/mnesia_schema_recovery_test.erl @@ -21,7 +21,79 @@ %% -module(mnesia_schema_recovery_test). -author('[email protected]'). --compile([export_all]). + +-export([init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2, + all/0, groups/0]). + +-export([interrupted_before_create_ram/1, + interrupted_before_create_disc/1, + interrupted_before_create_do/1, + interrupted_before_create_nostore/1, + interrupted_before_delete_ram/1, + interrupted_before_delete_disc/1, + interrupted_before_delete_do/1, + interrupted_before_add_ram/1, + interrupted_before_add_disc/1, + interrupted_before_add_do/1, + interrupted_before_add_kill_copier/1, + interrupted_before_move_ram/1, + interrupted_before_move_disc/1, + interrupted_before_move_do/1, + interrupted_before_move_kill_copier/1, + interrupted_before_delcopy_ram/1, + interrupted_before_delcopy_disc/1, + interrupted_before_delcopy_do/1, + interrupted_before_delcopy_kill_copier/1, + interrupted_before_addindex_ram/1, + interrupted_before_addindex_disc/1, + interrupted_before_addindex_do/1, + interrupted_before_delindex_ram/1, + interrupted_before_delindex_disc/1, + interrupted_before_delindex_do/1, + interrupted_before_change_type_ram2disc/1, + interrupted_before_change_type_ram2do/1, + interrupted_before_change_type_disc2ram/1, + interrupted_before_change_type_disc2do/1, + interrupted_before_change_type_do2ram/1, + interrupted_before_change_type_do2disc/1, + interrupted_before_change_type_other_node/1, + interrupted_before_change_schema_type/1, + interrupted_after_create_ram/1, + interrupted_after_create_disc/1, + interrupted_after_create_do/1, + interrupted_after_create_nostore/1, + interrupted_after_delete_ram/1, + interrupted_after_delete_disc/1, + interrupted_after_delete_do/1, + interrupted_after_add_ram/1, + interrupted_after_add_disc/1, + interrupted_after_add_do/1, + interrupted_after_add_kill_copier/1, + interrupted_after_move_ram/1, + interrupted_after_move_disc/1, + interrupted_after_move_do/1, + interrupted_after_move_kill_copier/1, + interrupted_after_delcopy_ram/1, + interrupted_after_delcopy_disc/1, + interrupted_after_delcopy_do/1, + interrupted_after_delcopy_kill_copier/1, + interrupted_after_addindex_ram/1, + interrupted_after_addindex_disc/1, + interrupted_after_addindex_do/1, + interrupted_after_delindex_ram/1, + interrupted_after_delindex_disc/1, + interrupted_after_delindex_do/1, + interrupted_after_change_type_ram2disc/1, + interrupted_after_change_type_ram2do/1, + interrupted_after_change_type_disc2ram/1, + interrupted_after_change_type_disc2do/1, + interrupted_after_change_type_do2ram/1, + interrupted_after_change_type_do2disc/1, + interrupted_after_change_type_other_node/1, + interrupted_after_change_schema_type/1]). + + -include("mnesia_test_lib.hrl"). init_per_testcase(Func, Conf) -> diff --git a/lib/mnesia/test/mnesia_test_lib.erl b/lib/mnesia/test/mnesia_test_lib.erl index 0fabdc7929..78dbe7ffde 100644 --- a/lib/mnesia/test/mnesia_test_lib.erl +++ b/lib/mnesia/test/mnesia_test_lib.erl @@ -774,7 +774,7 @@ init_nodes([], _File, _Line) -> %% Returns [Name, Host] node_to_name_and_host(Node) -> - string:tokens(atom_to_list(Node), [$@]). + string:lexemes(atom_to_list(Node), [$@]). lookup_config(Key,Config) -> case lists:keysearch(Key,1,Config) of diff --git a/lib/mnesia/test/mnesia_trans_access_test.erl b/lib/mnesia/test/mnesia_trans_access_test.erl index 4ed73ea859..c00a1ed51f 100644 --- a/lib/mnesia/test/mnesia_trans_access_test.erl +++ b/lib/mnesia/test/mnesia_trans_access_test.erl @@ -21,7 +21,28 @@ %% -module(mnesia_trans_access_test). -author('[email protected]'). --compile([export_all]). + +-export([init_per_testcase/2, end_per_testcase/2, + init_per_group/2, end_per_group/2, + all/0, groups/0]). + +-export([write/1, read/1, wread/1, delete/1, delete_object/1, + match_object/1, select/1, select14/1, all_keys/1, transaction/1, + basic_nested/1, mix_of_nested_activities/1, + nested_trans_both_ok/1, nested_trans_child_dies/1, + nested_trans_parent_dies/1, nested_trans_both_dies/1, + index_match_object/1, index_read/1,index_write/1, + index_update_set/1, index_update_bag/1, + add_table_index_ram/1, add_table_index_disc/1, + add_table_index_disc_only/1, create_live_table_index_ram/1, + create_live_table_index_disc/1, + create_live_table_index_disc_only/1, del_table_index_ram/1, + del_table_index_disc/1, del_table_index_disc_only/1, + idx_schema_changes_ram/1, idx_schema_changes_disc/1, + idx_schema_changes_disc_only/1]). + +-export([do_nested/1]). + -include("mnesia_test_lib.hrl"). init_per_testcase(Func, Conf) -> diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk index 81b15d65db..a95f468ba2 100644 --- a/lib/mnesia/vsn.mk +++ b/lib/mnesia/vsn.mk @@ -1 +1 @@ -MNESIA_VSN = 4.15 +MNESIA_VSN = 4.15.1 diff --git a/lib/observer/doc/src/notes.xml b/lib/observer/doc/src/notes.xml index d329be5d5a..05ea550964 100644 --- a/lib/observer/doc/src/notes.xml +++ b/lib/observer/doc/src/notes.xml @@ -32,6 +32,57 @@ <p>This document describes the changes made to the Observer application.</p> +<section><title>Observer 2.5</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>The following improvements are done to Crashdump + Viewer:</p> <list> <item>Reading of crash dumps with many + binaries is optimized.</item> <item>A progress bar is + shown when the detail view for a process is + opened.</item> <item>The <c>cdv</c> script now sets + <c>ERL_CRASH_DUMP_SECONDS=0</c> to avoid generating a new + crash dump from the node running the Crashdump + Viewer.</item> <item>A warning dialog is shown if the + node running the Crashdump Viewer could potentially + overwrite the crash dump under inspection.</item> + <item>Bugfix: In some situations, Crashdump Viewer could + not find the end of the 'Last calls' section in a crash + dump, and would erroneously mark the crash dump as + truncated. This is now corrected.</item> <item>Bugfix: In + some situations, process info for a specific process + would be marked as truncated by Crashdump Viewer, even if + the crash dump was truncated in the binary section - and + not related to the process in question. This is now + corrected.</item> </list> + <p> + Own Id: OTP-14386</p> + </item> + <item> + <p> + General Unicode improvements.</p> + <p> + Own Id: OTP-14462</p> + </item> + <item> + <p> + Tools are updated to show Unicode atoms correctly.</p> + <p> + Own Id: OTP-14464</p> + </item> + <item> + <p> + Add system statistics and limits to frontpage in + observer.</p> + <p> + Own Id: OTP-14536</p> + </item> + </list> + </section> + +</section> + <section><title>Observer 2.4</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/observer/priv/bin/cdv b/lib/observer/priv/bin/cdv index d14fd47e41..2a509c16af 100755 --- a/lib/observer/priv/bin/cdv +++ b/lib/observer/priv/bin/cdv @@ -1,4 +1,4 @@ #!/bin/sh -erl -noinput -s crashdump_viewer script_start $@ +erl -env ERL_CRASH_DUMP_SECONDS 0 -noinput -s crashdump_viewer script_start $@ diff --git a/lib/observer/priv/bin/cdv.bat b/lib/observer/priv/bin/cdv.bat index 18136a30d6..fa87c08adf 100644 --- a/lib/observer/priv/bin/cdv.bat +++ b/lib/observer/priv/bin/cdv.bat @@ -1,2 +1,2 @@ @ECHO OFF -CALL werl -s crashdump_viewer script_start %* +CALL werl -env ERL_CRASH_DUMP_SECONDS 0 -s crashdump_viewer script_start %* diff --git a/lib/observer/src/cdv_detail_wx.erl b/lib/observer/src/cdv_detail_wx.erl index 4c26e447a6..f6d282638a 100644 --- a/lib/observer/src/cdv_detail_wx.erl +++ b/lib/observer/src/cdv_detail_wx.erl @@ -20,7 +20,7 @@ -behaviour(wx_object). --export([start_link/4]). +-export([start_link/5]). -export([init/1, handle_event/2, handle_cast/2, terminate/2, code_change/3, handle_call/3, handle_info/2]). @@ -39,27 +39,42 @@ -define(ID_NOTEBOOK, 604). %% Detail view -start_link(Id, Data, ParentFrame, Callback) -> - wx_object:start_link(?MODULE, [Id, Data, ParentFrame, Callback, self()], []). +start_link(Id, Data, ParentFrame, Callback, App) -> + wx_object:start_link(?MODULE,[Id,Data,ParentFrame,Callback,App,self()],[]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -init([Id, Data, ParentFrame, Callback, Parent]) -> +init([Id, Data, ParentFrame, Callback, App, Parent]) -> + display_progress(ParentFrame,App), case Callback:get_details(Id, Data) of {ok,Details} -> - init(Id,ParentFrame,Callback,Parent,Details); + init(Id,ParentFrame,Callback,App,Parent,Details); {yes_no, Info, Fun} -> + destroy_progress(App), case observer_lib:display_yes_no_dialog(Info) of ?wxID_YES -> Fun(); ?wxID_NO -> ok end, {stop,normal}; {info,Info} -> + destroy_progress(App), observer_lib:display_info_dialog(ParentFrame,Info), {stop,normal} end. -init(Id,ParentFrame,Callback,Parent,{Title,Info,TW}) -> +%% Display progress bar only if the calling app is crashdump_viewer +display_progress(ParentFrame,cdv) -> + observer_lib:display_progress_dialog(ParentFrame, + "Crashdump Viewer", + "Reading data"); +display_progress(_,_) -> + ok. +destroy_progress(cdv) -> + observer_lib:destroy_progress_dialog(); +destroy_progress(_) -> + ok. + +init(Id,ParentFrame,Callback,App,Parent,{Title,Info,TW}) -> Frame=wxFrame:new(ParentFrame, ?wxID_ANY, [Title], [{style, ?wxDEFAULT_FRAME_STYLE}, {size, {850,600}}]), MenuBar = wxMenuBar:new(), @@ -88,6 +103,7 @@ init(Id,ParentFrame,Callback,Parent,{Title,Info,TW}) -> wxFrame:connect(Frame, close_window), wxMenu:connect(Frame, command_menu_selected), wxFrame:show(Frame), + destroy_progress(App), {Frame, #state{parent=Parent, id=Id, frame=Frame, diff --git a/lib/observer/src/cdv_dist_cb.erl b/lib/observer/src/cdv_dist_cb.erl index 2b4c9f56d1..aeb34e5baf 100644 --- a/lib/observer/src/cdv_dist_cb.erl +++ b/lib/observer/src/cdv_dist_cb.erl @@ -78,7 +78,7 @@ init_gen_page(Parent, Info) -> cdv_info_wx:start_link(Parent,{Fields,Info,[]}). format({creations,Creations}) -> - string:join([integer_to_list(C) || C <- Creations],","); + lists:flatten(lists:join(",",[integer_to_list(C) || C <- Creations])); format(D) -> D. diff --git a/lib/observer/src/cdv_html_wx.erl b/lib/observer/src/cdv_html_wx.erl index 5158e95a65..4b43b6a840 100644 --- a/lib/observer/src/cdv_html_wx.erl +++ b/lib/observer/src/cdv_html_wx.erl @@ -52,8 +52,12 @@ init([ParentWin, HtmlText]) -> init(ParentWin, HtmlText, undefined, cdv). init(ParentWin, HtmlText, Tab, App) -> + %% If progress dialog is shown, remove it now - and sett cursor busy instead + observer_lib:destroy_progress_dialog(), + wx_misc:beginBusyCursor(), HtmlWin = observer_lib:html_window(ParentWin), wxHtmlWindow:setPage(HtmlWin,HtmlText), + wx_misc:endBusyCursor(), {HtmlWin, #state{panel=HtmlWin,expand_table=Tab,app=App}}. %%%%%%%%%%%%%%%%%%%%%%% Callbacks %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -123,11 +127,12 @@ handle_event(Event, State) -> %%%----------------------------------------------------------------- %%% Internal -expand(Id,Callback,#state{expand_wins=Opened0}=State) -> +expand(Id,Callback,#state{expand_wins=Opened0, app=App}=State) -> Opened = case lists:keyfind(Id,1,Opened0) of false -> - EW = cdv_detail_wx:start_link(Id,[],State#state.panel,Callback), + EW = cdv_detail_wx:start_link(Id,[],State#state.panel, + Callback,App), wx_object:get_pid(EW) ! active, [{Id,EW}|Opened0]; {_,EW} -> diff --git a/lib/observer/src/cdv_mem_cb.erl b/lib/observer/src/cdv_mem_cb.erl index abeddc7335..925487786c 100644 --- a/lib/observer/src/cdv_mem_cb.erl +++ b/lib/observer/src/cdv_mem_cb.erl @@ -49,9 +49,7 @@ gen_mem_info_fields([]) -> []. upper(Key) -> - string:join([string:to_upper([H]) ++ T || - [H|T] <- string:tokens(Key,"_")]," "). - + lists:join(" ", [string:titlecase(Word) || Word <- string:split(Key, "_", all)]). %%%----------------------------------------------------------------- %%% Allocated areas page diff --git a/lib/observer/src/cdv_term_cb.erl b/lib/observer/src/cdv_term_cb.erl index f206d7e4c9..bdcb13f22d 100644 --- a/lib/observer/src/cdv_term_cb.erl +++ b/lib/observer/src/cdv_term_cb.erl @@ -30,23 +30,31 @@ detail_pages() -> [{"Term", fun init_term_page/2}]. init_term_page(ParentWin, {Type, [Term, Tab]}) -> + observer_lib:report_progress({ok,"Expanding term"}), + observer_lib:report_progress({ok,start_pulse}), Expanded = expand(Term, true), BinSaved = expand(Term, Tab), + observer_lib:report_progress({ok,stop_pulse}), cdv_multi_wx:start_link( ParentWin, [{"Format \~p",cdv_html_wx,{Type, format_term_fun("~p",BinSaved,Tab)}}, {"Format \~tp",cdv_html_wx,{Type,format_term_fun("~tp",BinSaved,Tab)}}, {"Format \~w",cdv_html_wx,{Type,format_term_fun("~w",BinSaved,Tab)}}, + {"Format \~tw",cdv_html_wx,{Type,format_term_fun("~tw",BinSaved,Tab)}}, {"Format \~s",cdv_html_wx,{Type,format_term_fun("~s",Expanded,Tab)}}, {"Format \~ts",cdv_html_wx,{Type,format_term_fun("~ts",Expanded,Tab)}}]). format_term_fun(Format,Term,Tab) -> fun() -> + observer_lib:report_progress({ok,"Formatting term"}), + observer_lib:report_progress({ok,start_pulse}), try io_lib:format(Format,[Term]) of Str -> {expand, plain_html(Str), Tab} catch error:badarg -> Warning = "This term can not be formatted with " ++ Format, observer_html_lib:warning(Warning) + after + observer_lib:report_progress({ok,stop_pulse}) end end. diff --git a/lib/observer/src/cdv_virtual_list_wx.erl b/lib/observer/src/cdv_virtual_list_wx.erl index f3daae8e4d..33c0c880b1 100644 --- a/lib/observer/src/cdv_virtual_list_wx.erl +++ b/lib/observer/src/cdv_virtual_list_wx.erl @@ -174,7 +174,7 @@ do_start_detail_win(Id, #state{panel=Panel,detail_wins=Opened, case lists:keyfind(Id, 1, Opened) of false -> Data = call(Holder, {get_data, self(), Id}), - case cdv_detail_wx:start_link(Id, Data, Panel, Callback) of + case cdv_detail_wx:start_link(Id, Data, Panel, Callback, cdv) of {error, _} -> Opened; IW -> [{Id, IW} | Opened] end; diff --git a/lib/observer/src/cdv_wx.erl b/lib/observer/src/cdv_wx.erl index 898f39ded2..0e33c9e618 100644 --- a/lib/observer/src/cdv_wx.erl +++ b/lib/observer/src/cdv_wx.erl @@ -130,8 +130,9 @@ init(File0) -> {ok,File} -> %% Set window title T1 = "Crashdump Viewer: ", + FileLength = string:length(File), Title = - if length(File) > 70 -> + if FileLength > 70 -> T1 ++ filename:basename(File); true -> T1 ++ File @@ -412,15 +413,25 @@ load_dump(Frame,undefined) -> error end; load_dump(Frame,FileName) -> - ok = observer_lib:display_progress_dialog("Crashdump Viewer", + case maybe_warn_filename(FileName) of + continue -> + do_load_dump(Frame,FileName); + stop -> + error + end. + +do_load_dump(Frame,FileName) -> + ok = observer_lib:display_progress_dialog(wx:null(), + "Crashdump Viewer", "Loading crashdump"), crashdump_viewer:read_file(FileName), case observer_lib:wait_for_progress() of ok -> %% Set window title T1 = "Crashdump Viewer: ", + FileLength = string:length(FileName), Title = - if length(FileName) > 70 -> + if FileLength > 70 -> T1 ++ filename:basename(FileName); true -> T1 ++ FileName @@ -431,6 +442,33 @@ load_dump(Frame,FileName) -> error end. +maybe_warn_filename(FileName) -> + case os:getenv("ERL_CRASH_DUMP_SECONDS")=="0" orelse + os:getenv("ERL_CRASH_DUMP_BYTES")=="0" of + true -> + continue; + false -> + DumpName = case os:getenv("ERL_CRASH_DUMP") of + false -> filename:absname("erl_crash.dump"); + Name -> filename:absname(Name) + end, + case filename:absname(FileName) of + DumpName -> + Warning = + "WARNING: the current crashdump might be overwritten " + "if the crashdump_viewer node crashes.\n\n" + "Renaming the file before inspecting it will " + "remove the problem.\n\n" + "Do you want to continue?", + case observer_lib:display_yes_no_dialog(Warning) of + ?wxID_YES -> continue; + ?wxID_NO -> stop + end; + _ -> + continue + end + end. + %%%----------------------------------------------------------------- %%% Find help document (HTML files) get_help_doc(HelpId) -> diff --git a/lib/observer/src/crashdump_viewer.erl b/lib/observer/src/crashdump_viewer.erl index fd8b3b9e67..51ff69fd69 100644 --- a/lib/observer/src/crashdump_viewer.erl +++ b/lib/observer/src/crashdump_viewer.erl @@ -36,7 +36,6 @@ %% file: The name of the crashdump currently viewed. %% dump_vsn: The version number of the crashdump %% wordsize: 4 | 8, the number of bytes in a word. -%% binaries: a gb_tree containing binaries or links to binaries in the dump %% %% User API @@ -87,6 +86,7 @@ -define(max_line_size,100). % max number of bytes (i.e. characters) the % line_head/1 function can return -define(not_available,"N/A"). +-define(binary_size_progress_limit,10000). %% All possible tags - use macros in order to avoid misspelling in the code @@ -106,6 +106,8 @@ -define(internal_ets,internal_ets). -define(loaded_modules,loaded_modules). -define(memory,memory). +-define(memory_map,memory_map). +-define(memory_status,memory_status). -define(mod,mod). -define(no_distribution,no_distribution). -define(node,node). @@ -122,7 +124,7 @@ -define(visible_node,visible_node). --record(state,{file,dump_vsn,wordsize=4,num_atoms="unknown",binaries}). +-record(state,{file,dump_vsn,wordsize=4,num_atoms="unknown"}). %%%----------------------------------------------------------------- %%% Debugging @@ -203,7 +205,8 @@ do_script_start(StartFun) -> io:format("\ncdv crash: ~tp\n",[Reason]) end; _ -> - io:format("\ncdv crash: ~p\n",[unknown_reason]) + %io:format("\ncdv crash: ~p\n",[unknown_reason]) + ok end; Error -> io:format("\ncdv start failed: ~tp\n",[Error]) @@ -305,6 +308,8 @@ expand_binary(Pos) -> init([]) -> ets:new(cdv_dump_index_table,[ordered_set,named_table,public]), ets:new(cdv_reg_proc_table,[ordered_set,named_table,public]), + ets:new(cdv_binary_index_table,[ordered_set,named_table,public]), + ets:new(cdv_heap_file_chars,[ordered_set,named_table,public]), {ok, #state{}}. %%-------------------------------------------------------------------- @@ -348,9 +353,9 @@ handle_call(procs_summary,_From,State=#state{file=File,wordsize=WS}) -> Procs = procs_summary(File,WS), {reply,{ok,Procs,TW},State}; handle_call({proc_details,Pid},_From, - State=#state{file=File,wordsize=WS,dump_vsn=DumpVsn,binaries=B})-> + State=#state{file=File,wordsize=WS,dump_vsn=DumpVsn})-> Reply = - case get_proc_details(File,Pid,WS,DumpVsn,B) of + case get_proc_details(File,Pid,WS,DumpVsn) of {ok,Proc,TW} -> {ok,Proc,TW}; Other -> @@ -462,9 +467,9 @@ handle_call(schedulers,_From,State=#state{file=File}) -> %%-------------------------------------------------------------------- handle_cast({read_file,File}, _State) -> case do_read_file(File) of - {ok,Binaries,DumpVsn} -> + {ok,DumpVsn} -> observer_lib:report_progress({ok,done}), - {noreply, #state{file=File,binaries=Binaries,dump_vsn=DumpVsn}}; + {noreply, #state{file=File,dump_vsn=DumpVsn}}; Error -> end_progress(Error), {noreply, #state{}} @@ -746,32 +751,6 @@ get_rest_of_line_1(Fd, <<>>, Acc) -> eof -> {eof,lists:reverse(Acc)} end. -get_lines_to_empty(Fd) -> - case get_chunk(Fd) of - {ok,Bin} -> - get_lines_to_empty(Fd,Bin,[],[]); - eof -> - [] - end. -get_lines_to_empty(Fd,<<$\n:8,Bin/binary>>,[],Lines) -> - put_chunk(Fd,Bin), - lists:reverse(Lines); -get_lines_to_empty(Fd,<<$\n:8,Bin/binary>>,Acc,Lines) -> - get_lines_to_empty(Fd,Bin,[],[byte_list_to_string(lists:reverse(Acc))|Lines]); -get_lines_to_empty(Fd,<<$\r:8,Bin/binary>>,Acc,Lines) -> - get_lines_to_empty(Fd,Bin,Acc,Lines); -get_lines_to_empty(Fd,<<$\s:8,Bin/binary>>,[],Lines) -> - get_lines_to_empty(Fd,Bin,[],Lines); -get_lines_to_empty(Fd,<<Char:8,Bin/binary>>,Acc,Lines) -> - get_lines_to_empty(Fd,Bin,[Char|Acc],Lines); -get_lines_to_empty(Fd,<<>>,Acc,Lines) -> - case get_chunk(Fd) of - {ok,Bin} -> - get_lines_to_empty(Fd,Bin,Acc,Lines); - eof -> - lists:reverse(Lines,[byte_list_to_string(lists:reverse(Acc))]) - end. - split(Str) -> split($ ,Str,[]). split(Char,Str) -> @@ -817,18 +796,17 @@ do_read_file(File) -> {Tag,Id,Rest,N1} = tag(Fd,TagAndRest,1), case Tag of ?erl_crash_dump -> - reset_index_table(), + reset_tables(), insert_index(Tag,Id,N1+1), put_last_tag(Tag,""), - indexify(Fd,Rest,N1), + DumpVsn = [list_to_integer(L) || + L<-string:lexemes(Id,".")], + AddrAdj = get_bin_addr_adj(DumpVsn), + indexify(Fd,AddrAdj,Rest,N1), end_progress(), check_if_truncated(), - [{DumpVsn0,_}] = lookup_index(?erl_crash_dump), - DumpVsn = [list_to_integer(L) || - L<-string:tokens(DumpVsn0,".")], - Binaries = read_binaries(Fd,DumpVsn), close(Fd), - {ok,Binaries,DumpVsn}; + {ok,DumpVsn}; _Other -> R = io_lib:format( "~ts is not an Erlang crash dump~n", @@ -856,15 +834,31 @@ do_read_file(File) -> {error,R} end. -indexify(Fd,Bin,N) -> +indexify(Fd,AddrAdj,Bin,N) -> case binary:match(Bin,<<"\n=">>) of {Start,Len} -> Pos = Start+Len, <<_:Pos/binary,TagAndRest/binary>> = Bin, {Tag,Id,Rest,N1} = tag(Fd,TagAndRest,N+Pos), - insert_index(Tag,Id,N1+1), % +1 to get past newline - put_last_tag(Tag,Id), - indexify(Fd,Rest,N1); + NewPos = N1+1, % +1 to get past newline + case Tag of + ?binary -> + %% Binaries are stored in a separate table in + %% order to minimize lookup time. Key is the + %% translated address. + {HexAddr,_} = get_hex(Id), + Addr = HexAddr bor AddrAdj, + insert_binary_index(Addr,NewPos); + _ -> + insert_index(Tag,Id,NewPos) + end, + case put_last_tag(Tag,Id) of + {?proc_heap,LastId} -> + [{_,LastPos}] = lookup_index(?proc_heap,LastId), + ets:insert(cdv_heap_file_chars,{LastId,N+Start+1-LastPos}); + _ -> ok + end, + indexify(Fd,AddrAdj,Rest,N1); nomatch -> case progress_read(Fd) of {ok,Chunk0} when is_binary(Chunk0) -> @@ -875,7 +869,7 @@ indexify(Fd,Bin,N) -> _ -> {Chunk0,N+byte_size(Bin)} end, - indexify(Fd,Chunk,N1); + indexify(Fd,AddrAdj,Chunk,N1); eof -> eof end @@ -911,7 +905,11 @@ check_if_truncated() -> find_truncated_proc(TruncatedTag) end. -find_truncated_proc({?atoms,_Id}) -> +find_truncated_proc({Tag,_Id}) when Tag==?atoms; + Tag==?binary; + Tag==?instr_data; + Tag==?memory_status; + Tag==?memory_map -> put(truncated_proc,false); find_truncated_proc({Tag,Pid}) -> case is_proc_tag(Tag) of @@ -1060,14 +1058,14 @@ procs_summary(File,WS) -> %%----------------------------------------------------------------- %% Page with one process -get_proc_details(File,Pid,WS,DumpVsn,Binaries) -> +get_proc_details(File,Pid,WS,DumpVsn) -> case lookup_index(?proc,Pid) of [{_,Start}] -> Fd = open(File), {{Stack,MsgQ,Dict},TW} = case truncated_warning([{?proc,Pid}]) of [] -> - {expand_memory(Fd,Pid,DumpVsn,Binaries),[]}; + {expand_memory(Fd,Pid,DumpVsn),[]}; TW0 -> {{[],[],[]},TW0} end, @@ -1176,7 +1174,7 @@ all_procinfo(Fd,Fun,Proc,WS,LineHead) -> get_procinfo(Fd,Fun,Proc#proc{old_heap_end=bytes(Fd)},WS); %% - END - moved from get_procinfo - "Last calls" -> - get_procinfo(Fd,Fun,Proc#proc{last_calls=get_lines_to_empty(Fd)},WS); + get_procinfo(Fd,Fun,Proc#proc{last_calls=get_last_calls(Fd)},WS); "Link list" -> {Links,Monitors,MonitoredBy} = parse_link_list(bytes(Fd),[],[],[]), get_procinfo(Fd,Fun,Proc#proc{links=Links, @@ -1200,6 +1198,66 @@ all_procinfo(Fd,Fun,Proc,WS,LineHead) -> get_procinfo(Fd,Fun,Proc,WS) end. +%% The end of the 'Last calls' section is meant to be an empty line, +%% but in some cases this is not the case, so we also need to look for +%% the next heading which currently (OTP-20.1) can be "Link list: ", +%% "Dictionary: " or "Reductions: ". We do this by looking for ": " +%% and when found, pushing the heading back into the saved chunk. +%% +%% Note that the 'Last calls' section is only present if the +%% 'save_calls' process flag is set. +get_last_calls(Fd) -> + case get_chunk(Fd) of + {ok,Bin} -> + get_last_calls(Fd,Bin,[],[]); + eof -> + [] + end. +get_last_calls(Fd,<<$\n:8,Bin/binary>>,[],Lines) -> + %% Empty line - we're done + put_chunk(Fd,Bin), + lists:reverse(Lines); +get_last_calls(Fd,<<$::8>>,Acc,Lines) -> + case get_chunk(Fd) of + {ok,Bin} -> + %% Could be a colon followed by a space - see next function clause + get_last_calls(Fd,<<$::8,Bin/binary>>,Acc,Lines); + eof -> + %% Truncated here - either we've got the next heading, or + %% it was truncated in a last call function, in which case + %% we note that it was truncated + case byte_list_to_string(lists:reverse(Acc)) of + NextHeading when NextHeading=="Link list"; + NextHeading=="Dictionary"; + NextHeading=="Reductions" -> + put_chunk(Fd,list_to_binary(NextHeading++":")), + lists:reverse(Lines); + LastCallFunction-> + lists:reverse(Lines,[LastCallFunction++":...(truncated)"]) + end + end; +get_last_calls(Fd,<<$\::8,$\s:8,Bin/binary>>,Acc,Lines) -> + %% ": " - means we have the next heading in Acc - save it back + %% into the chunk and return the lines we've found + HeadingBin = list_to_binary(lists:reverse(Acc,[$:])), + put_chunk(Fd,<<HeadingBin/binary,Bin/binary>>), + lists:reverse(Lines); +get_last_calls(Fd,<<$\n:8,Bin/binary>>,Acc,Lines) -> + get_last_calls(Fd,Bin,[],[byte_list_to_string(lists:reverse(Acc))|Lines]); +get_last_calls(Fd,<<$\r:8,Bin/binary>>,Acc,Lines) -> + get_last_calls(Fd,Bin,Acc,Lines); +get_last_calls(Fd,<<$\s:8,Bin/binary>>,[],Lines) -> + get_last_calls(Fd,Bin,[],Lines); +get_last_calls(Fd,<<Char:8,Bin/binary>>,Acc,Lines) -> + get_last_calls(Fd,Bin,[Char|Acc],Lines); +get_last_calls(Fd,<<>>,Acc,Lines) -> + case get_chunk(Fd) of + {ok,Bin} -> + get_last_calls(Fd,Bin,Acc,Lines); + eof -> + lists:reverse(Lines,[byte_list_to_string(lists:reverse(Acc))]) + end. + parse_link_list([SB|Str],Links,Monitors,MonitoredBy) when SB==$[; SB==$] -> parse_link_list(Str,Links,Monitors,MonitoredBy); parse_link_list("#Port"++_=Str,Links,Monitors,MonitoredBy) -> @@ -1235,12 +1293,12 @@ parse_monitor("{"++Str) -> %% Named process {Name,Node,Rest1} = parse_name_node(Str,[]), Pid = get_pid_from_name(Name,Node), - case parse_link(string:strip(Rest1,left,$,),[]) of + case parse_link(string:trim(Rest1,leading,","),[]) of {Ref,"}"++Rest2} -> %% Bug in break.c - prints an extra "}" for remote %% nodes... thus the strip {{Pid,"{"++Name++","++Node++"} ("++Ref++")"}, - string:strip(Rest2,left,$})}; + string:trim(Rest2,leading,"}")}; {Ref,[]} -> {{Pid,"{"++Name++","++Node++"} ("++Ref++")"},[]} end; @@ -1325,10 +1383,10 @@ maybe_other_node2(Channel) -> end. -expand_memory(Fd,Pid,DumpVsn,Binaries) -> +expand_memory(Fd,Pid,DumpVsn) -> BinAddrAdj = get_bin_addr_adj(DumpVsn), put(fd,Fd), - Dict = read_heap(Fd,Pid,BinAddrAdj,Binaries), + Dict = read_heap(Fd,Pid,BinAddrAdj,gb_trees:empty()), Expanded = {read_stack_dump(Fd,Pid,BinAddrAdj,Dict), read_messages(Fd,Pid,BinAddrAdj,Dict), read_dictionary(Fd,Pid,BinAddrAdj,Dict)}, @@ -1346,25 +1404,6 @@ get_bin_addr_adj(_) -> 0. %%% -%%% Read binaries. -%%% -read_binaries(Fd,DumpVsn) -> - AllBinaries = lookup_index(?binary), - AddrAdj = get_bin_addr_adj(DumpVsn), - Fun = fun({Addr0,Pos},Dict0) -> - pos_bof(Fd,Pos), - {HexAddr,_} = get_hex(Addr0), - Addr = HexAddr bor AddrAdj, - Bin = - case line_head(Fd) of - {eof,_} -> '#CDVTruncatedBinary'; - _Size -> {'#CDVBin',Pos} - end, - gb_trees:enter(Addr,Bin,Dict0) - end, - progress_foldl("Processing binaries",Fun,gb_trees:empty(),AllBinaries). - -%%% %%% Read top level section. %%% @@ -1454,6 +1493,8 @@ parse_dictionary(Line0, BinAddrAdj, D) -> read_heap(Fd,Pid,BinAddrAdj,Dict0) -> case lookup_index(?proc_heap,Pid) of [{_,Pos}] -> + [{_,Chars}] = ets:lookup(cdv_heap_file_chars,Pid), + init_progress("Reading process heap",Chars), pos_bof(Fd,Pos), read_heap(BinAddrAdj,Dict0); [] -> @@ -1464,13 +1505,16 @@ read_heap(BinAddrAdj,Dict0) -> %% This function is never called if the dump is truncated in {?proc_heap,Pid} case get(fd) of end_of_heap -> + end_progress(), Dict0; Fd -> case bytes(Fd) of "=" ++ _next_tag -> + end_progress(), put(fd, end_of_heap), Dict0; Line -> + update_progress(length(Line)+1), Dict = parse(Line,BinAddrAdj,Dict0), read_heap(BinAddrAdj,Dict) end @@ -1506,7 +1550,7 @@ get_ports(File) -> %% Converting port string to tuple to secure correct sorting. This is %% converted back in cdv_port_cb:format/1. port_to_tuple("#Port<"++Port) -> - [I1,I2] = string:tokens(Port,".>"), + [I1,I2] = string:lexemes(Port,".>"), {list_to_integer(I1),list_to_integer(I2)}. get_portinfo(Fd,Port) -> @@ -1529,9 +1573,9 @@ get_portinfo(Fd,Port) -> "Registered as" -> get_portinfo(Fd,Port#port{name=string(Fd)}); "Monitors" -> - Monitors0 = string:tokens(bytes(Fd),"()"), + Monitors0 = string:lexemes(bytes(Fd),"()"), Monitors = [begin - [Pid,Ref] = string:tokens(Mon,","), + [Pid,Ref] = string:lexemes(Mon,","), {Pid,Pid++" ("++Ref++")"} end || Mon <- Monitors0], get_portinfo(Fd,Port#port{monitors=Monitors}); @@ -1592,7 +1636,7 @@ get_etsinfo(Fd,EtsTable = #ets_table{details=Ds},WS) -> "Buckets" -> %% A bug in erl_db_hash.c prints a space after the buckets %% - need to strip the string to make list_to_integer/1 happy. - Buckets = list_to_integer(string:strip(bytes(Fd))), + Buckets = list_to_integer(string:trim(bytes(Fd),both,"\s")), get_etsinfo(Fd,EtsTable#ets_table{buckets=Buckets},WS); "Objects" -> get_etsinfo(Fd,EtsTable#ets_table{size=list_to_integer(bytes(Fd))},WS); @@ -1610,7 +1654,9 @@ get_etsinfo(Fd,EtsTable = #ets_table{details=Ds},WS) -> Val = bytes(Fd), get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{chain_min=>Val}},WS); "Chain Length Avg" -> - Val = try list_to_float(string:strip(bytes(Fd))) catch _:_ -> "-" end, + Val = try list_to_float(string:trim(bytes(Fd),both,"\s")) + catch _:_ -> "-" + end, get_etsinfo(Fd,EtsTable#ets_table{details=Ds#{chain_avg=>Val}},WS); "Chain Length Max" -> Val = bytes(Fd), @@ -1767,7 +1813,7 @@ get_nodeinfo(Fd,Nod) -> Creations = lists:flatmap(fun(C) -> try [list_to_integer(C)] catch error:badarg -> [] end - end, string:tokens(bytes(Fd)," ")), + end, string:lexemes(bytes(Fd)," ")), get_nodeinfo(Fd,Nod#nod{creation={creations,Creations}}); "Remote link" -> Procs = bytes(Fd), % e.g. "<0.31.0> <4322.54.0>" @@ -2213,7 +2259,7 @@ get_size_value(Key,Data) -> %% and Value is the sum over all allocator instances of each type. sort_allocator_types([{Name,Data}|Allocators],Acc,DoTotal) -> Type = - case string:tokens(Name,"[]") of + case string:lexemes(Name,"[]") of [T,_Id] -> T; [Name] -> Name; Other -> Other @@ -2524,9 +2570,9 @@ parse_heap_term("Yc"++Line0, Addr, BinAddrAdj, D0) -> %Reference-counted binary. {Offset,":"++Line2} = get_hex(Line1), {Sz,Line} = get_hex(Line2), Binp = Binp0 bor BinAddrAdj, - Term = case gb_trees:lookup(Binp, D0) of - {value,Bin} -> cdvbin(Offset,Sz,Bin); - none -> '#CDVNonexistingBinary' + Term = case lookup_binary_index(Binp) of + [{_,Start}] -> cdvbin(Offset,Sz,{'#CDVBin',Start}); + [] -> '#CDVNonexistingBinary' end, D = gb_trees:insert(Addr, Term, D0), {Term,Line,D}; @@ -2535,15 +2581,14 @@ parse_heap_term("Ys"++Line0, Addr, BinAddrAdj, D0) -> %Sub binary. {Offset,":"++Line2} = get_hex(Line1), {Sz,Line} = get_hex(Line2), Binp = Binp0 bor BinAddrAdj, - Term = case gb_trees:lookup(Binp, D0) of - {value,Bin} -> cdvbin(Offset,Sz,Bin); - none when Binp0=/=Binp -> + Term = case lookup_binary_index(Binp) of + [{_,Start}] -> cdvbin(Offset,Sz,{'#CDVBin',Start}); + [] -> %% Might it be on the heap? - case gb_trees:lookup(Binp0, D0) of + case gb_trees:lookup(Binp, D0) of {value,Bin} -> cdvbin(Offset,Sz,Bin); none -> '#CDVNonexistingBinary' - end; - none -> '#CDVNonexistingBinary' + end end, D = gb_trees:insert(Addr, Term, D0), {Term,Line,D}. @@ -2634,6 +2679,7 @@ deref_ptr(Ptr, Line, BinAddrAdj, D0) -> put(fd, end_of_heap), deref_ptr(Ptr, Line, BinAddrAdj, D0); L -> + update_progress(length(L)+1), D = parse(L, BinAddrAdj, D0), deref_ptr(Ptr, Line, BinAddrAdj, D) end @@ -2699,19 +2745,33 @@ get_label([H|T], Acc) -> get_label(T, [H|Acc]). get_binary(Line0) -> - {N,":"++Line} = get_hex(Line0), - do_get_binary(N, Line, []). + case get_hex(Line0) of + {N,":"++Line} -> + do_get_binary(N, Line, [], false); + _ -> + {'#CDVTruncatedBinary',[]} + end. get_binary(Offset,Size,Line0) -> - {_N,":"++Line} = get_hex(Line0), - do_get_binary(Size, lists:sublist(Line,(Offset*2)+1,Size*2), []). - -do_get_binary(0, Line, Acc) -> + case get_hex(Line0) of + {_N,":"++Line} -> + Progress = Size>?binary_size_progress_limit, + Progress andalso init_progress("Reading binary",Size), + do_get_binary(Size, lists:sublist(Line,(Offset*2)+1,Size*2), [], + Progress); + _ -> + {'#CDVTruncatedBinary',[]} + end. + +do_get_binary(0, Line, Acc, Progress) -> + Progress andalso end_progress(), {list_to_binary(lists:reverse(Acc)),Line}; -do_get_binary(N, [A,B|Line], Acc) -> +do_get_binary(N, [A,B|Line], Acc, Progress) -> Byte = (get_hex_digit(A) bsl 4) bor get_hex_digit(B), - do_get_binary(N-1, Line, [Byte|Acc]); -do_get_binary(_N, [], _Acc) -> + Progress andalso update_progress(), + do_get_binary(N-1, Line, [Byte|Acc], Progress); +do_get_binary(_N, [], _Acc, Progress) -> + Progress andalso end_progress(), {'#CDVTruncatedBinary',[]}. cdvbin(Offset,Size,{'#CDVBin',Pos}) -> @@ -2719,12 +2779,17 @@ cdvbin(Offset,Size,{'#CDVBin',Pos}) -> cdvbin(Offset,Size,['#CDVBin',_,_,Pos]) -> ['#CDVBin',Offset,Size,Pos]; cdvbin(_,_,'#CDVTruncatedBinary') -> - '#CDVTruncatedBinary'. + '#CDVTruncatedBinary'; +cdvbin(_,_,'#CDVNonexistingBinary') -> + '#CDVNonexistingBinary'. %%----------------------------------------------------------------- -%% Functions for accessing the cdv_dump_index_table -reset_index_table() -> - ets:delete_all_objects(cdv_dump_index_table). +%% Functions for accessing tables +reset_tables() -> + ets:delete_all_objects(cdv_dump_index_table), + ets:delete_all_objects(cdv_reg_proc_table), + ets:delete_all_objects(cdv_binary_index_table), + ets:delete_all_objects(cdv_heap_file_chars). insert_index(Tag,Id,Pos) -> ets:insert(cdv_dump_index_table,{{Tag,Pos},Id}). @@ -2739,6 +2804,11 @@ lookup_index(Tag,Id) -> count_index(Tag) -> ets:select_count(cdv_dump_index_table,[{{{Tag,'_'},'_'},[],[true]}]). +insert_binary_index(Addr,Pos) -> + ets:insert(cdv_binary_index_table,{Addr,Pos}). + +lookup_binary_index(Addr) -> + ets:lookup(cdv_binary_index_table,Addr). %%----------------------------------------------------------------- %% Convert tags read from crashdump to atoms used as first part of key @@ -2809,23 +2879,6 @@ to_value_list(Record) -> Values. %%%----------------------------------------------------------------- -%%% Fold over List and report progress in percent. -%%% Report is the text to be presented in the progress dialog. -%%% Acc0 is the initial accumulator and will be passed to Fun as the -%%% second arguement, i.e. Fun = fun(Item,Acc) -> NewAcc end. -progress_foldl(Report,Fun,Acc0,List) -> - init_progress(Report, length(List)), - progress_foldl1(Fun,Acc0,List). - -progress_foldl1(Fun,Acc,[H|T]) -> - update_progress(), - progress_foldl1(Fun,Fun(H,Acc),T); -progress_foldl1(_Fun,Acc,[]) -> - end_progress(), - Acc. - - -%%%----------------------------------------------------------------- %%% Map over List and report progress in percent. %%% Report is the text to be presented in the progress dialog. %%% Distribute the load over a number of processes, and File is opened diff --git a/lib/observer/src/observer.app.src b/lib/observer/src/observer.app.src index 3a5bd172e7..f682e3dc7b 100644 --- a/lib/observer/src/observer.app.src +++ b/lib/observer/src/observer.app.src @@ -65,7 +65,7 @@ {registered, []}, {applications, [kernel, stdlib]}, {env, []}, - {runtime_dependencies, ["wx-1.2","stdlib-2.0","runtime_tools-1.8.14", + {runtime_dependencies, ["wx-1.2","stdlib-3.4","runtime_tools-1.8.14", "kernel-3.0","inets-5.10","et-1.5", "erts-7.0"]}]}. diff --git a/lib/observer/src/observer_html_lib.erl b/lib/observer/src/observer_html_lib.erl index 3dfcc42ada..68381bcc7b 100644 --- a/lib/observer/src/observer_html_lib.erl +++ b/lib/observer/src/observer_html_lib.erl @@ -278,24 +278,24 @@ href_proc_port("['#CDVPort'"++T,Acc,LTB) -> %% Port written by crashdump_viewer:parse_term(...) {Port0,Rest} = split($],T), PortStr= - case string:tokens(Port0,",.|") of + case string:lexemes(Port0,",.|") of [X,Y] -> Port = "#Port<"++X++"."++Y++">", href(Port,Port); Ns -> - "#Port<" ++ string:join(Ns,".") ++"...>" + "#Port<" ++ lists:join($.,Ns) ++"...>" end, href_proc_port(Rest,[PortStr|Acc],LTB); href_proc_port("['#CDVPid'"++T,Acc,LTB) -> %% Pid written by crashdump_viewer:parse_term(...) {Pid0,Rest} = split($],T), PidStr = - case string:tokens(Pid0,",.|") of + case string:lexemes(Pid0,",.|") of [X,Y,Z] -> Pid = "<"++X++"."++Y++"."++Z++">", href(Pid,Pid); Ns -> - "<" ++ string:join(Ns,".") ++ "...>" + "<" ++ lists:join($.,Ns) ++ "...>" end, href_proc_port(Rest,[PidStr|Acc],LTB); href_proc_port("'#CDVIncompleteHeap'"++T,Acc,LTB)-> @@ -332,22 +332,29 @@ href_proc_port([],Acc,_) -> href_proc_bin(From, T, Acc, LTB) -> {OffsetSizePos,Rest} = split($],T), BinStr = - case string:tokens(OffsetSizePos,",.| \n") of + case string:lexemes(OffsetSizePos,",.| \n") of [Offset,SizeStr,Pos] when From =:= cdv -> Size = list_to_integer(SizeStr), PreviewSize = min(Size,10), Id = {list_to_integer(Offset),PreviewSize,list_to_integer(Pos)}, - {ok,PreviewBin} = crashdump_viewer:expand_binary(Id), - PreviewStr = preview_string(Size, PreviewBin), - if LTB -> - href("TARGET=\"expanded\"", - ["#Binary?offset="++Offset++ - "&size="++SizeStr++ - "&pos="++Pos], - PreviewStr); - true -> - PreviewStr - end; + case crashdump_viewer:expand_binary(Id) of + {ok, '#CDVTruncatedBinary'} -> + lists:flatten( + "<FONT COLOR=\"#FF0000\">" + "<<...(Truncated Binary)>>" + "</FONT>"); + {ok, PreviewBin} -> + PreviewStr = preview_string(Size, PreviewBin), + if LTB -> + href("TARGET=\"expanded\"", + ["#Binary?offset="++Offset++ + "&size="++SizeStr++ + "&pos="++Pos], + PreviewStr); + true -> + PreviewStr + end + end; [PreviewIntStr,SizeStr,Md5] when From =:= obs -> Size = list_to_integer(SizeStr), PreviewInt = list_to_integer(PreviewIntStr), diff --git a/lib/observer/src/observer_lib.erl b/lib/observer/src/observer_lib.erl index 463fb5b8ef..e5ffe61d25 100644 --- a/lib/observer/src/observer_lib.erl +++ b/lib/observer/src/observer_lib.erl @@ -21,7 +21,7 @@ -export([get_wx_parent/1, display_info_dialog/2, display_yes_no_dialog/1, - display_progress_dialog/2, destroy_progress_dialog/0, + display_progress_dialog/3, destroy_progress_dialog/0, wait_for_progress/0, report_progress/1, user_term/3, user_term_multiline/3, interval_dialog/4, start_timer/1, start_timer/2, stop_timer/1, timer_config/1, @@ -40,6 +40,7 @@ -define(SINGLE_LINE_STYLE, ?wxBORDER_NONE bor ?wxTE_READONLY bor ?wxTE_RICH2). -define(MULTI_LINE_STYLE, ?SINGLE_LINE_STYLE bor ?wxTE_MULTILINE). +-define(pulse_timeout,50). get_wx_parent(Window) -> Parent = wxWindow:getParent(Window), @@ -477,7 +478,7 @@ create_box(Parent, Data) -> link_entry(Panel,Value); _ -> Value = to_str(Value0), - case string:sub_word(lists:sublist(Value, 80),1,$\n) of + case string:nth_lexeme(lists:sublist(Value, 80),1, [$\n]) of Value -> %% Short string, no newlines - show all wxStaticText:new(Panel, ?wxID_ANY, Value); @@ -688,11 +689,11 @@ create_status_bar(Panel) -> %%%----------------------------------------------------------------- %%% Progress dialog -define(progress_handler,cdv_progress_handler). -display_progress_dialog(Title,Str) -> +display_progress_dialog(Parent,Title,Str) -> Caller = self(), Env = wx:get_env(), spawn_link(fun() -> - progress_handler(Caller,Env,Title,Str) + progress_handler(Caller,Env,Parent,Title,Str) end), ok. @@ -716,31 +717,38 @@ report_progress(Progress) -> ok end. -progress_handler(Caller,Env,Title,Str) -> +progress_handler(Caller,Env,Parent,Title,Str) -> register(?progress_handler,self()), wx:set_env(Env), - PD = progress_dialog(Env,Title,Str), - try progress_loop(Title,PD,Caller) + PD = progress_dialog(Env,Parent,Title,Str), + try progress_loop(Title,PD,Caller,infinity) catch closed -> normal end. -progress_loop(Title,PD,Caller) -> +progress_loop(Title,PD,Caller,Pulse) -> receive {progress,{ok,done}} -> % to make wait_for_progress/0 return Caller ! continue, - progress_loop(Title,PD,Caller); + progress_loop(Title,PD,Caller,Pulse); + {progress,{ok,start_pulse}} -> + update_progress_pulse(PD), + progress_loop(Title,PD,Caller,?pulse_timeout); + {progress,{ok,stop_pulse}} -> + progress_loop(Title,PD,Caller,infinity); {progress,{ok,Percent}} when is_integer(Percent) -> update_progress(PD,Percent), - progress_loop(Title,PD,Caller); + progress_loop(Title,PD,Caller,Pulse); {progress,{ok,Msg}} -> update_progress_text(PD,Msg), - progress_loop(Title,PD,Caller); + progress_loop(Title,PD,Caller,Pulse); {progress,{error, Reason}} -> + {Dialog,_,_} = PD, + Parent = wxWindow:getParent(Dialog), finish_progress(PD), FailMsg = if is_list(Reason) -> Reason; true -> file:format_error(Reason) end, - display_info_dialog(PD,"Crashdump Viewer Error",FailMsg), + display_info_dialog(Parent,"Crashdump Viewer Error",FailMsg), Caller ! error, unregister(?progress_handler), unlink(Caller); @@ -748,28 +756,57 @@ progress_loop(Title,PD,Caller) -> finish_progress(PD), unregister(?progress_handler), unlink(Caller) + after Pulse -> + update_progress_pulse(PD), + progress_loop(Title,PD,Caller,?pulse_timeout) end. -progress_dialog(_Env,Title,Str) -> - PD = wxProgressDialog:new(Title,Str, - [{maximum,101}, - {style, - ?wxPD_APP_MODAL bor - ?wxPD_SMOOTH bor - ?wxPD_AUTO_HIDE}]), - wxProgressDialog:setMinSize(PD,{200,-1}), - PD. +progress_dialog(_Env,Parent,Title,Str) -> + progress_dialog_new(Parent,Title,Str). update_progress(PD,Value) -> - try wxProgressDialog:update(PD,Value) + try progress_dialog_update(PD,Value) catch _:_ -> throw(closed) %% Port or window have died end. update_progress_text(PD,Text) -> - try wxProgressDialog:update(PD,0,[{newmsg,Text}]) + try progress_dialog_update(PD,Text) + catch _:_ -> throw(closed) %% Port or window have died + end. +update_progress_pulse(PD) -> + try progress_dialog_pulse(PD) catch _:_ -> throw(closed) %% Port or window have died end. finish_progress(PD) -> - wxProgressDialog:destroy(PD). + try progress_dialog_update(PD,100) + catch _:_ -> ok + after progress_dialog_destroy(PD) + end. + +progress_dialog_new(Parent,Title,Str) -> + Dialog = wxDialog:new(Parent, ?wxID_ANY, Title, + [{style,?wxDEFAULT_DIALOG_STYLE}]), + Panel = wxPanel:new(Dialog), + Sizer = wxBoxSizer:new(?wxVERTICAL), + Message = wxStaticText:new(Panel, 1, Str), + Gauge = wxGauge:new(Panel, 2, 100, [{size, {170, -1}}, + {style, ?wxGA_HORIZONTAL}]), + SizerFlags = ?wxEXPAND bor ?wxLEFT bor ?wxRIGHT bor ?wxTOP, + wxSizer:add(Sizer, Message, [{flag,SizerFlags},{border,15}]), + wxSizer:add(Sizer, Gauge, [{flag, SizerFlags bor ?wxBOTTOM},{border,15}]), + wxPanel:setSizer(Panel, Sizer), + wxSizer:setSizeHints(Sizer, Dialog), + wxDialog:show(Dialog), + {Dialog,Message,Gauge}. + +progress_dialog_update({_,_,Gauge},Value) when is_integer(Value) -> + wxGauge:setValue(Gauge,Value); +progress_dialog_update({_,Message,Gauge},Text) when is_list(Text) -> + wxGauge:setValue(Gauge,0), + wxStaticText:setLabel(Message,Text). +progress_dialog_pulse({_,_,Gauge}) -> + wxGauge:pulse(Gauge). +progress_dialog_destroy({Dialog,_,_}) -> + wxDialog:destroy(Dialog). make_obsbin(Bin,Tab) -> Size = byte_size(Bin), diff --git a/lib/observer/src/observer_procinfo.erl b/lib/observer/src/observer_procinfo.erl index 963def958b..4ce38e439d 100644 --- a/lib/observer/src/observer_procinfo.erl +++ b/lib/observer/src/observer_procinfo.erl @@ -151,7 +151,7 @@ handle_event(#wx{event=#wxHtmlLink{linkInfo=#wxHtmlLinkInfo{href=Href}}}, Opened = case lists:keyfind(Id,1,Opened0) of false -> - Win = cdv_detail_wx:start_link(Id,[],Frame,Callback), + Win = cdv_detail_wx:start_link(Id,[],Frame,Callback,obs), [{Id,Win}|Opened0]; {_,Win} -> wxFrame:raise(Win), @@ -454,7 +454,8 @@ local_pid_str(Pid) -> global_pid_node_pref(Pid) -> %% Global PID node prefix : X of <X.Y.Z> - string:strip(string:sub_word(pid_to_list(Pid),1,$.),left,$<). + [NodePrefix|_] = string:lexemes(pid_to_list(Pid),"<."), + NodePrefix. io_get_data(Pid) -> Pid ! {self(), get_data_and_close}, diff --git a/lib/observer/src/observer_wx.erl b/lib/observer/src/observer_wx.erl index be93b1d5f1..453e3bdc2d 100644 --- a/lib/observer/src/observer_wx.erl +++ b/lib/observer/src/observer_wx.erl @@ -732,7 +732,7 @@ get_nodes() -> {Nodes, lists:reverse(Menues)}. epmd_nodes(Names) -> - [_, Host] = string:tokens(atom_to_list(node()),"@"), + [_, Host] = string:lexemes(atom_to_list(node()),"@"), [list_to_atom(Name ++ [$@|Host]) || {Name, _} <- Names]. update_node_list(State = #state{menubar=MenuBar}) -> diff --git a/lib/observer/src/ttb.erl b/lib/observer/src/ttb.erl index 940fdc9818..29a572d7fe 100644 --- a/lib/observer/src/ttb.erl +++ b/lib/observer/src/ttb.erl @@ -100,7 +100,7 @@ do_tracer(Clients,PI,Traci) -> {ok, H} = inet:gethostname(), H; _ -> - [_,H] = string:tokens(atom_to_list(N),"@"), + [_,H] = string:lexemes(atom_to_list(N),"@"), H end, case catch dbg:tracer(N,port,dbg:trace_port(ip,IpPortSpec)) of @@ -976,7 +976,7 @@ decode_filename(3,Bin,latin1) -> File. host(Node) -> - [_name,Host] = string:tokens(atom_to_list(Node),"@"), + [_name,Host] = string:lexemes(atom_to_list(Node),"@"), Host. wait_for_fetch([]) -> @@ -1064,7 +1064,7 @@ collect_files(Dirs) -> lists:map(fun(Dir) -> MetaFiles = filelib:wildcard(filename:join(Dir,"*.ti")), lists:map(fun(M) -> - Sub = string:left(M,length(M)-3), + Sub = filename:rootname(M,".ti"), case filelib:is_file(Sub) of true -> Sub; false -> Sub++".*.wrp" diff --git a/lib/observer/test/Makefile b/lib/observer/test/Makefile index fcb1b73911..a44e54fc52 100644 --- a/lib/observer/test/Makefile +++ b/lib/observer/test/Makefile @@ -47,7 +47,7 @@ RELSYSDIR = $(RELEASE_PATH)/observer_test # FLAGS # ---------------------------------------------------- ERL_MAKE_FLAGS += -ERL_COMPILE_FLAGS += +nowarn_export_all +ERL_COMPILE_FLAGS += +warnings_as_errors +nowarn_export_all EBIN = . diff --git a/lib/observer/test/crashdump_viewer_SUITE.erl b/lib/observer/test/crashdump_viewer_SUITE.erl index 77cf086d4b..f9ac884743 100644 --- a/lib/observer/test/crashdump_viewer_SUITE.erl +++ b/lib/observer/test/crashdump_viewer_SUITE.erl @@ -76,7 +76,7 @@ end_per_testcase(Case, Config) -> end, ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> []. all() -> [start_stop, @@ -364,6 +364,9 @@ special(File,Procs) -> crashdump_viewer:expand_binary({SOffset,SSize,SPos}), io:format(" expand binary ok",[]), + #proc{last_calls=LastCalls} = ProcDetails, + true = length(LastCalls) =< 4, + ['#CDVPid',X1,Y1,Z1] = proplists:get_value(ext_pid,Dict), ChannelStr1 = integer_to_list(X1), ExtPid = @@ -413,19 +416,90 @@ special(File,Procs) -> old_attrib=undefined, old_comp_info=undefined}=Mod2, ok; - %% ".strangemodname" -> - %% {ok,Mods,[]} = crashdump_viewer:loaded_modules(), - %% lookat_all_mods(Mods), - %% ok; - %% ".sort" -> - %% %% sort ports, atoms and modules ???? - %% ok; - %% ".trunc" -> - %% %% ???? - %% ok; - ".trunc.bytes" -> + ".trunc_bin1" -> + %% This is 'full_dist' truncated after the first + %% "=binary:" + %% i.e. no binary exist in the dump + [#proc{pid=Pid0}|_Rest] = lists:keysort(#proc.name,Procs), + Pid = pid_to_list(Pid0), + {ok,ProcDetails=#proc{},[]} = crashdump_viewer:proc_details(Pid), + io:format(" process details ok",[]), + + #proc{dict=Dict} = ProcDetails, + + '#CDVNonexistingBinary' = proplists:get_value(bin,Dict), + '#CDVNonexistingBinary' = proplists:get_value(sub_bin,Dict), + + io:format(" nonexisting binaries ok",[]), + ok; + ".trunc_bin2" -> + %% This is 'full_dist' truncated after the first + %% "=binary:Addr\n + %% Size" + %% i.e. binaries are truncated + [#proc{pid=Pid0}|_Rest] = lists:keysort(#proc.name,Procs), + Pid = pid_to_list(Pid0), + {ok,ProcDetails=#proc{},[]} = crashdump_viewer:proc_details(Pid), + io:format(" process details ok",[]), + + #proc{dict=Dict} = ProcDetails, + + ['#CDVBin',Offset,Size,Pos] = proplists:get_value(bin,Dict), + {ok,'#CDVTruncatedBinary'} = + crashdump_viewer:expand_binary({Offset,Size,Pos}), + ['#CDVBin',SOffset,SSize,SPos] = proplists:get_value(sub_bin,Dict), + {ok,'#CDVTruncatedBinary'} = + crashdump_viewer:expand_binary({SOffset,SSize,SPos}), + + io:format(" expand truncated binary ok",[]), + ok; + ".trunc_bin3" -> + %% This is 'full_dist' truncated after the first + %% "=binary:Addr\n + %% Size:" + %% i.e. same as 'trunc_bin2', except the colon exists also + [#proc{pid=Pid0}|_Rest] = lists:keysort(#proc.name,Procs), + Pid = pid_to_list(Pid0), + {ok,ProcDetails=#proc{},[]} = crashdump_viewer:proc_details(Pid), + io:format(" process details ok",[]), + + #proc{dict=Dict} = ProcDetails, + + ['#CDVBin',Offset,Size,Pos] = proplists:get_value(bin,Dict), + {ok,'#CDVTruncatedBinary'} = + crashdump_viewer:expand_binary({Offset,Size,Pos}), + ['#CDVBin',SOffset,SSize,SPos] = proplists:get_value(sub_bin,Dict), + {ok,'#CDVTruncatedBinary'} = + crashdump_viewer:expand_binary({SOffset,SSize,SPos}), + + io:format(" expand truncated binary ok",[]), + ok; + ".trunc_bin4" -> + %% This is 'full_dist' truncated after the first + %% "=binary:Addr\n + %% Size:BinaryMissinOneByte" + %% i.e. the full binary is truncated, but the sub binary is complete + [#proc{pid=Pid0}|_Rest] = lists:keysort(#proc.name,Procs), + Pid = pid_to_list(Pid0), + {ok,ProcDetails=#proc{},[]} = crashdump_viewer:proc_details(Pid), + io:format(" process details ok",[]), + + #proc{dict=Dict} = ProcDetails, + + ['#CDVBin',Offset,Size,Pos] = proplists:get_value(bin,Dict), + {ok,'#CDVTruncatedBinary'} = + crashdump_viewer:expand_binary({Offset,Size,Pos}), + io:format(" expand truncated binary ok",[]), + ['#CDVBin',SOffset,SSize,SPos] = proplists:get_value(sub_bin,Dict), + {ok,<<_:SSize/binary>>} = + crashdump_viewer:expand_binary({SOffset,SSize,SPos}), + io:format(" expand complete sub binary ok",[]), + + ok; + ".trunc_bytes" -> {ok,_,[TW]} = crashdump_viewer:general_info(), {match,_} = re:run(TW,"CRASH DUMP SIZE LIMIT REACHED"), + io:format(" size limit information ok",[]), ok; ".unicode" -> #proc{pid=Pid0} = @@ -500,16 +574,45 @@ do_create_dumps(DataDir,Rel) -> current -> CD3 = dump_with_args(DataDir,Rel,"instr","+Mim true"), CD4 = dump_with_strange_module_name(DataDir,Rel,"strangemodname"), - Bytes = rand:uniform(300000) + 100, - CD5 = dump_with_args(DataDir,Rel,"trunc.bytes", + Tmp = dump_with_args(DataDir,Rel,"trunc_bytes",""), + {ok,#file_info{size=Max}} = file:read_file_info(Tmp), + ok = file:delete(Tmp), + Bytes = max(15,rand:uniform(Max)), + CD5 = dump_with_args(DataDir,Rel,"trunc_bytes", "-env ERL_CRASH_DUMP_BYTES " ++ integer_to_list(Bytes)), CD6 = dump_with_unicode_atoms(DataDir,Rel,"unicode"), - {[CD1,CD2,CD3,CD4,CD5,CD6], DosDump}; + TruncatedDumps = truncate_dump(CD1), + {[CD1,CD2,CD3,CD4,CD5,CD6|TruncatedDumps], DosDump}; _ -> {[CD1,CD2], DosDump} end. +truncate_dump(File) -> + {ok,Bin} = file:read_file(File), + BinTag = <<"\n=binary:">>, + Colon = <<":">>, + NewLine = case os:type() of + {win32,_} -> <<"\r\n">>; + _ -> <<"\n">> + end, + [StartBin,AfterTag] = binary:split(Bin,BinTag), + [AddrAndSize,BinaryAndRest] = binary:split(AfterTag,Colon), + [Binary,_Rest] = binary:split(BinaryAndRest,NewLine), + TruncSize = byte_size(Binary) - 2, + <<TruncBinary:TruncSize/binary,_/binary>> = Binary, + TruncName = filename:rootname(File) ++ ".trunc_bin", + write_trunc_files(TruncName,StartBin, + [BinTag,AddrAndSize,Colon,TruncBinary],1). + +write_trunc_files(TruncName0,Bin,[Part|Parts],N) -> + TruncName = TruncName0++integer_to_list(N), + Bin1 = <<Bin/binary,Part/binary>>, + ok = file:write_file(TruncName,Bin1), + [TruncName|write_trunc_files(TruncName0,Bin1,Parts,N+1)]; +write_trunc_files(_,_,[],_) -> + []. + %% Create a dump which has three visible nodes, one hidden and one %% not connected node, and with monitors and links between nodes. diff --git a/lib/observer/test/observer_SUITE.erl b/lib/observer/test/observer_SUITE.erl index 41726b1521..0db2c1ea77 100644 --- a/lib/observer/test/observer_SUITE.erl +++ b/lib/observer/test/observer_SUITE.erl @@ -115,6 +115,7 @@ basic(doc) -> [""]; basic(Config) when is_list(Config) -> timer:send_after(100, "foobar"), %% Otherwise the timer server gets added to procs ProcsBefore = processes(), + ProcInfoBefore = [{P,process_info(P)} || P <- ProcsBefore], NumProcsBefore = length(ProcsBefore), ok = observer:start(), @@ -145,8 +146,10 @@ basic(Config) when is_list(Config) -> ProcsAfter = processes(), NumProcsAfter = length(ProcsAfter), if NumProcsAfter=/=NumProcsBefore -> + BeforeNotAfter = ProcsBefore -- ProcsAfter, ct:log("Before but not after:~n~p~n", - [[{P,process_info(P)} || P <- ProcsBefore -- ProcsAfter]]), + [[{P,I} || {P,I} <- ProcInfoBefore, + lists:member(P,BeforeNotAfter)]]), ct:log("After but not before:~n~p~n", [[{P,process_info(P)} || P <- ProcsAfter -- ProcsBefore]]), ct:fail("leaking processes"); @@ -304,10 +307,10 @@ table_win(Config) when is_list(Config) -> %% Test PR-1296/OTP-14151 %% Clicking a link to a port before the port tab has been activated the %% first time crashes observer. -port_win_when_tab_not_initiated(Config) -> +port_win_when_tab_not_initiated(_Config) -> {ok,Port} = gen_tcp:listen(0,[]), ok = observer:start(), - Notebook = setup_whitebox_testing(), + _Notebook = setup_whitebox_testing(), observer ! {open_link,erlang:port_to_list(Port)}, timer:sleep(1000), observer:stop(), diff --git a/lib/observer/test/ttb_SUITE.erl b/lib/observer/test/ttb_SUITE.erl index c06ec21f36..ed62efbb58 100644 --- a/lib/observer/test/ttb_SUITE.erl +++ b/lib/observer/test/ttb_SUITE.erl @@ -222,7 +222,7 @@ file_fetch(Config) when is_list(Config) -> ?line ?t:capture_stop(), ?line [StoreString] = ?t:capture_get(), ?line UploadDir = - lists:last(string:tokens(lists:flatten(StoreString),"$ \n")), + lists:last(string:lexemes(lists:flatten(StoreString),"$ \n")), %% check that files are no longer in original directories... ?line ok = check_gone(ThisDir,atom_to_list(Node)++"-file_fetch"), @@ -778,37 +778,37 @@ otp_4967_2(suite) -> otp_4967_2(doc) -> ["OTP-4967: Trace message sent to {Name, Node}"]; otp_4967_2(Config) when is_list(Config) -> - io:format("1: ~p",[now()]), + io:format("1: ~p",[erlang:timestamp()]), ?line Privdir = priv_dir(Config), - io:format("2: ~p",[now()]), + io:format("2: ~p",[erlang:timestamp()]), ?line File = filename:join(Privdir,"otp_4967"), - io:format("3: ~p",[now()]), + io:format("3: ~p",[erlang:timestamp()]), ?line S = self(), - io:format("4: ~p",[now()]), + io:format("4: ~p",[erlang:timestamp()]), ?line {ok,[Node]} = ttb:tracer(node(),[{file, File}, {handler,{fun myhandler/4, S}}]), - io:format("5: ~p",[now()]), + io:format("5: ~p",[erlang:timestamp()]), %% Test that delayed registration of a process works. receive after 200 -> ok end, ?line register(otp_4967,self()), - io:format("6: ~p",[now()]), + io:format("6: ~p",[erlang:timestamp()]), ?line {ok,[{S,[{matched,Node,1}]}]} = ttb:p(self(),s), - io:format("7: ~p",[now()]), + io:format("7: ~p",[erlang:timestamp()]), ?line {otp_4967,node()} ! heihopp, - io:format("8: ~p",[now()]), + io:format("8: ~p",[erlang:timestamp()]), ?line stopped = ttb:stop([format]), - io:format("9: ~p",[now()]), + io:format("9: ~p",[erlang:timestamp()]), ?line Msgs = flush(), - io:format("10: ~p",[now()]), + io:format("10: ~p",[erlang:timestamp()]), ?line io:format("Messages received: \n~p\n",[Msgs]), - io:format("11: ~p",[now()]), + io:format("11: ~p",[erlang:timestamp()]), ?line true = lists:member(heihopp,Msgs), % the heihopp message itself - io:format("13: ~p",[now()]), + io:format("13: ~p",[erlang:timestamp()]), ?line {value,{trace_ts,_,send,heihopp,{_,otp_4967,Node},{_,_,_}}} = lists:keysearch(heihopp,4,Msgs), % trace trace of the heihopp message - io:format("14: ~p",[now()]), + io:format("14: ~p",[erlang:timestamp()]), ?line end_of_trace = lists:last(Msgs), % end of the trace ok. @@ -1035,8 +1035,8 @@ logfile_name_in_fetch_dir(Config) when is_list(Config) -> ?line {ServerNode, ClientNode} = start_client_and_server(), ?line begin_trace(ServerNode, ClientNode, {local, ?FNAME}), ?line {_,Dir} = ttb:stop([return_fetch_dir]), - ?line P1 = lists:nth(3, string:tokens(filename:basename(Dir), "_")), - ?line P2 = hd(string:tokens(P1, "-")), + ?line P1 = lists:nth(3, string:lexemes(filename:basename(Dir), "_")), + ?line P2 = hd(string:lexemes(P1, "-")), ?line _File = P2. logfile_name_in_fetch_dir(cleanup,_Config) -> ?line stop_client_and_server(). diff --git a/lib/observer/vsn.mk b/lib/observer/vsn.mk index 21edfcd184..5f43198f85 100644 --- a/lib/observer/vsn.mk +++ b/lib/observer/vsn.mk @@ -1 +1 @@ -OBSERVER_VSN = 2.4 +OBSERVER_VSN = 2.5 diff --git a/lib/os_mon/doc/src/notes.xml b/lib/os_mon/doc/src/notes.xml index df4151147c..b29a64155e 100644 --- a/lib/os_mon/doc/src/notes.xml +++ b/lib/os_mon/doc/src/notes.xml @@ -31,6 +31,23 @@ </header> <p>This document describes the changes made to the OS_Mon application.</p> +<section><title>Os_Mon 2.4.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + On macOS 10.13 (High Sierra), disksup could not grab + information for any disks that used the new APFS file + system. That has been corrected.</p> + <p> + Own Id: OTP-14560 Aux Id: ERL-461 </p> + </item> + </list> + </section> + +</section> + <section><title>Os_Mon 2.4.2</title> <section><title>Improvements and New Features</title> diff --git a/lib/os_mon/src/cpu_sup.erl b/lib/os_mon/src/cpu_sup.erl index e758b63d19..c1c972b5b1 100644 --- a/lib/os_mon/src/cpu_sup.erl +++ b/lib/os_mon/src/cpu_sup.erl @@ -244,7 +244,7 @@ get_uint32_measurement(Request, #internal{os_type = {unix, Sys}}) when Sys == ir %% Get the load average using uptime. %% "8:01pm up 2 days, 22:12, 4 users, load average: 0.70, 0.58, 0.43" D = os:cmd("uptime") -- "\n", - Avg = lists:reverse(hd(string:tokens(lists:reverse(D), ":"))), + Avg = lists:reverse(hd(string:lexemes(lists:reverse(D), ":"))), {ok, [L1, L5, L15], _} = io_lib:fread("~f, ~f, ~f", Avg), case Request of ?avg1 -> sunify(L1); diff --git a/lib/os_mon/src/memsup.erl b/lib/os_mon/src/memsup.erl index 0a9a883390..95cb798ba5 100644 --- a/lib/os_mon/src/memsup.erl +++ b/lib/os_mon/src/memsup.erl @@ -705,7 +705,7 @@ get_os_wordsize_with_uname() -> _ -> 32 end. -clean_string(String) -> lists:flatten(string:tokens(String,"\r\n\t ")). +clean_string(String) -> lists:flatten(string:lexemes(String,"\r\n\t ")). %%--Replying to pending clients----------------------------------------- diff --git a/lib/os_mon/vsn.mk b/lib/os_mon/vsn.mk index 59a3d9dee4..e4250f577b 100644 --- a/lib/os_mon/vsn.mk +++ b/lib/os_mon/vsn.mk @@ -1 +1 @@ -OS_MON_VSN = 2.4.2 +OS_MON_VSN = 2.4.3 diff --git a/lib/parsetools/src/leex.erl b/lib/parsetools/src/leex.erl index e2e7d7359f..8a4a5e8d86 100644 --- a/lib/parsetools/src/leex.erl +++ b/lib/parsetools/src/leex.erl @@ -37,7 +37,6 @@ -import(lists, [member/2,reverse/1,sort/1,delete/2, keysort/2,keydelete/3, map/2,foldl/3,foreach/2,flatmap/2]). --import(string, [substr/2,substr/3,span/2]). -import(ordsets, [is_element/2,add_element/2,union/2]). -import(orddict, [store/3]). @@ -251,10 +250,10 @@ is_filename(T) -> shorten_filename(Name0) -> {ok,Cwd} = file:get_cwd(), - case lists:prefix(Cwd, Name0) of - false -> Name0; - true -> - case lists:nthtail(length(Cwd), Name0) of + case string:prefix(Name0, Cwd) of + nomatch -> Name0; + Rest -> + case unicode:characters_to_list(Rest) of "/"++N -> N; N -> N end @@ -490,12 +489,9 @@ parse_rules_end(_, NextLine, REAs, As, St) -> %% action has been read. Keep track of line number. collect_rule(Ifile, Chars, L0) -> - %% Erlang strings are 1 based, but re 0 :-( - {match,[{St0,Len}|_]} = re:run(Chars, "[^ \t\r\n]+", [unicode]), - St = St0 + 1, - %%io:fwrite("RE = ~p~n", [substr(Chars, St, Len)]), - case collect_action(Ifile, substr(Chars, St+Len), L0, []) of - {ok,[{':',_}|Toks],L1} -> {ok,substr(Chars, St, Len),Toks,L1}; + {RegExp,Rest} = string:take(Chars, " \t\r\n", true), + case collect_action(Ifile, Rest, L0, []) of + {ok,[{':',_}|Toks],L1} -> {ok,RegExp,Toks,L1}; {ok,_,_} -> {error,{L0,leex,bad_rule}}; {eof,L1} -> {error,{L1,leex,bad_rule}}; {error,E,_} -> {error,E} @@ -549,7 +545,7 @@ var_used(Name, Toks) -> parse_rule_regexp(RE0, [{M,Exp}|Ms], St) -> Split= re:split(RE0, "\\{" ++ M ++ "\\}", [{return,list},unicode]), - RE1 = string:join(Split, Exp), + RE1 = lists:append(lists:join(Exp, Split)), parse_rule_regexp(RE1, Ms, St); parse_rule_regexp(RE, [], St) -> %%io:fwrite("RE = ~p~n", [RE]), @@ -589,9 +585,9 @@ nextline(Ifile, L, St) -> eof -> {eof,L}; {error, _} -> add_error({L+1, leex, cannot_parse}, St); Chars -> - case substr(Chars, span(Chars, " \t\n")+1) of - [$%|_Rest] -> nextline(Ifile, L+1, St); - [] -> nextline(Ifile, L+1, St); + case string:take(Chars, " \t\n") of + {_, [$%|_Rest]} -> nextline(Ifile, L+1, St); + {_, []} -> nextline(Ifile, L+1, St); _Other -> {ok,Chars,L+1} end end. @@ -824,7 +820,7 @@ re_char_class(Cs, Cc, _) -> {reverse(Cc),Cs}. % Preserve order %% posix_cc("space" ++ Cs) -> {space,Cs}; %% posix_cc("upper" ++ Cs) -> {upper,Cs}; %% posix_cc("xdigit" ++ Cs) -> {xdigit,Cs}; -%% posix_cc(Cs) -> parse_error({posix_cc,substr(Cs, 1, 5)}). +%% posix_cc(Cs) -> parse_error({posix_cc,string:slice(Cs, 0, 5)}). escape_char($n) -> $\n; % \n = LF escape_char($r) -> $\r; % \r = CR @@ -863,7 +859,7 @@ escape_char(C) -> C. % Pass it straight through %% re_number(Cs, Acc) -> {Acc,Cs}. string_between(Cs1, Cs2) -> - substr(Cs1, 1, length(Cs1)-length(Cs2)). + string:slice(Cs1, 0, string:length(Cs1)-string:length(Cs2)). %% We use standard methods, Thompson's construction and subset %% construction, to create first an NFA and then a DFA from the @@ -1343,7 +1339,7 @@ out_file(Ifile, Ofile, St, DFA, DF, Actions, Code, L) -> eof -> output_file_directive(Ofile, St#leex.ifile, L); {error, _} -> add_error(St#leex.ifile, {L, leex, cannot_parse}, St); Line -> - case substr(Line, 1, 5) of + case string:slice(Line, 0, 5) of "##mod" -> out_module(Ofile, St); "##cod" -> out_erlang_code(Ofile, St, Code, L); "##dfa" -> out_dfa(Ofile, St, DFA, Code, DF, L); @@ -1523,7 +1519,7 @@ prep_out_actions(As) -> Name = list_to_atom(lists:concat([yyaction_,A])), [Chars,Len,Line,_,_] = Vars, Args = [V || V <- [Chars,Len,Line], V =/= "_"], - ArgsChars = string:join(Args, ", "), + ArgsChars = lists:join(", ", Args), {A,Code,Vars,Name,Args,ArgsChars} end, As). diff --git a/lib/parsetools/src/yecc.erl b/lib/parsetools/src/yecc.erl index 36e33b52a4..b4e1cfe5e3 100644 --- a/lib/parsetools/src/yecc.erl +++ b/lib/parsetools/src/yecc.erl @@ -365,10 +365,10 @@ is_filename(T) -> shorten_filename(Name0) -> {ok,Cwd} = file:get_cwd(), - case lists:prefix(Cwd, Name0) of - false -> Name0; - true -> - case lists:nthtail(length(Cwd), Name0) of + case string:prefix(Name0, Cwd) of + nomatch -> Name0; + Rest -> + case unicode:characters_to_list(Rest) of "/"++N -> N; N -> N end @@ -2196,8 +2196,8 @@ output_reduce(St0, State, Terminal, St20; true -> Ns = "Nss", - Tmp = string:join(lists:duplicate(NmbrOfDaughters - 1, "_"), - ","), + Tmp = lists:join(",", + lists:duplicate(NmbrOfDaughters - 1, "_")), fwrite(St20, <<" [~s|Nss] = Ss,\n">>, [Tmp]) end, St40 = case tokens(RuleNmbr, St30) of diff --git a/lib/public_key/doc/src/notes.xml b/lib/public_key/doc/src/notes.xml index 64592a6d87..7a7c828760 100644 --- a/lib/public_key/doc/src/notes.xml +++ b/lib/public_key/doc/src/notes.xml @@ -35,6 +35,76 @@ <file>notes.xml</file> </header> +<section><title>Public_Key 1.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + public_key now handles elliptic curve parameters in a + consistent way so that decoded ECDSA keys can be + correctly re-encoded.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14621 Aux Id: ERL-480, ERL-481 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Extend crypto:sign, crypto:verify, public_key:sign and + public_key:verify with:</p> + <p> + * support for RSASSA-PS padding for signatures and for + saltlength setting<br/> * X9.31 RSA padding.<br/> * sha, + sha224, sha256, sha384, and sha512 for dss signatures as + mentioned in NIST SP 800-57 Part 1.<br/> * ripemd160 to + be used for rsa signatures.</p> + <p> + This is a manual merge of half of the pull request 838 by + potatosalad from Sept 2015.</p> + <p> + Own Id: OTP-13704 Aux Id: PR838 </p> + </item> + <item> + <p> + Add API function pkix_test_data/1 for facilitating + automated testing. This is useful for applications that + preform X509-certifcate path validation of so called + certificate chains, such as TLS.</p> + <p> + Own Id: OTP-14181</p> + </item> + <item> + <p> + Improved error propagation and reports</p> + <p> + Own Id: OTP-14236</p> + </item> + <item> + <p> + RSAPrivateKey version is set to 'two-prime' instead of + using the underlying enumeration value directly.</p> + <p> + Own Id: OTP-14534</p> + </item> + <item> + <p> + Deprecated function <c>crypto:rand_uniform/2</c> is + replaced by <c>rand:uniform/1</c>.</p> + <p> + Own Id: OTP-14608</p> + </item> + </list> + </section> + +</section> + <section><title>Public_Key 1.4.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml index 942203bd12..fcf37a7a4d 100644 --- a/lib/public_key/doc/src/public_key.xml +++ b/lib/public_key/doc/src/public_key.xml @@ -119,6 +119,10 @@ <tag><c>ec_private_key() =</c></tag> <item><p><c>#'ECPrivateKey'{}</c></p></item> + <tag><c>key_params() =</c></tag> + <item><p> #'DHParameter'{} | {namedCurve, oid()} | #'ECParameters'{} + | {rsa, Size::integer(), PubExp::integer()} </p></item> + <tag><c>public_crypt_options() =</c></tag> <item><p><c>[{rsa_pad, rsa_padding()}]</c></p></item> @@ -347,8 +351,7 @@ <name>generate_key(Params) -> {Public::binary(), Private::binary()} | #'ECPrivateKey'{} | #'RSAPrivateKey'{}</name> <fsummary>Generates a new keypair.</fsummary> <type> - <v>Params = #'DHParameter'{} | {namedCurve, oid()} | #'ECParameters'{} - | {rsa, Size::integer(), PubExp::integer} </v> + <v>Params = key_params()</v> </type> <desc> <p>Generates a new keypair. Note that except for Diffie-Hellman @@ -769,6 +772,85 @@ fun(#'DistributionPoint'{}, #'CertificateList'{}, </desc> </func> + <func> + <name>pkix_test_data(Options) -> Config </name> + <fsummary>Creates certificate test data.</fsummary> + <type> + <v>Options = #{chain_type() := chain_opts()} </v> + <d>Options for ROOT, Intermediate and Peer certs</d> + + <v>chain_type() = server_chain | client_chain </v> + + <v>chain_opts() = #{chain_end() := [cert_opt()], + intermediates => [[cert_opt()]]}</v> + <d>A valid chain must have at least a ROOT and a peer cert</d> + + <v>chain_end() = root | peer </v> + + <v>cert_opt() = {Key, Value}</v> + <d>For available options see <seealso marker="#cert_opt"> cert_opt()</seealso> below.</d> + + <v>Config = #{server_config := [conf_opt()], + client_config := [conf_opt()]}</v> + + <v>conf_opt() = {cert, der_encoded()} | {key, der_encoded()} |{cacerts, [der_encoded()]}</v> + <d>This is a subset of the type <seealso marker="ssl:ssl#type-ssloption"> ssl:ssl_option()</seealso> </d> + </type> + + <desc> + <p>Creates certificate test data to facilitate automated testing + of applications using X509-certificates often through + SSL/TLS. The test data can be used when you have control + over both the client and the server in a test scenario. + </p> + + <p> The <marker id="cert_opt"/> cert_opt() type consists of the following options: </p> + <taglist> + <tag> {digest, digest_type()}</tag> + <item><p>Hash algorithm to be used for + signing the certificate together with the key option. Defaults to sha that is sha1. + </p></item> + <tag> {key, key_params() | private_key()}</tag> + <item><p>Parameters to be used to call public_key:generate_key/1, to generate a key, or an existing + key. Defaults to generating an ECDSA key. Note this could fail if Erlang/OTP is compiled with a very old + cryptolib.</p></item> + <tag> {validity, {From::erlang:timestamp(), To::erlang:timestamp()}} </tag> + <item><p>The validity period of the certificate.</p></item> + <tag> {extensions, [#'Extension'{}]}</tag> + <item><p> Extensions to include in the certificate.</p> + + <p>Default extensions included in CA certificates if not + otherwise specified are: </p> + <code>[#'Extension'{extnID = ?'id-ce-keyUsage', + extnValue = [keyCertSign, cRLSign], + critical = false}, +#'Extension'{extnID = ?'id-ce-basicConstraints', + extnValue = #'BasicConstraints'{cA = true}, + critical = true}] + </code> + + <p>Default extensions included in the server peer cert if not + otherwise specified are: </p> + <code>[#'Extension'{extnID = ?'id-ce-keyUsage', + extnValue = [digitalSignature, keyAgreement], + critical = false}, +#'Extension'{extnID = ?'id-ce-subjectAltName', + extnValue = [{dNSName, Hostname}], + critical = false}] + </code> + <p>Hostname is the result of calling net_adm:localhost() in the Erlang node + where this funcion is called. + </p></item> + + </taglist> + + <note><p> + Note that the generated certificates and keys does not provide a formally correct PKIX-trust-chain + and they can not be used to achieve real security. This function is provided for testing purposes only. +</p></note> + </desc> + </func> + <func> <name>pkix_verify(Cert, Key) -> boolean()</name> <fsummary>Verifies PKIX x.509 certificate signature.</fsummary> diff --git a/lib/public_key/doc/src/public_key_records.xml b/lib/public_key/doc/src/public_key_records.xml index d34f3ed9a3..739310c88b 100644 --- a/lib/public_key/doc/src/public_key_records.xml +++ b/lib/public_key/doc/src/public_key_records.xml @@ -171,9 +171,9 @@ #'ECPrivateKey'{ version, % integer() privateKey, % binary() - parameters, % der_encoded() - {'EcpkParameters', #'ECParameters'{}} | - {'EcpkParameters', {namedCurve, oid()}} | - {'EcpkParameters', 'NULL'} % Inherited by CA + parameters, % {ecParameters, #'ECParameters'{}} | + % {namedCurve, Oid::tuple()} | + % {implicitlyCA, 'NULL'} publicKey % bitstring() }. diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl index f45f2c2e9a..13833830a7 100644 --- a/lib/public_key/src/pubkey_cert.erl +++ b/lib/public_key/src/pubkey_cert.erl @@ -32,12 +32,25 @@ is_issuer/2, issuer_id/2, distribution_points/1, is_fixed_dh_cert/1, verify_data/1, verify_fun/4, select_extension/2, match_name/3, - extensions_list/1, cert_auth_key_id/1, time_str_2_gregorian_sec/1]). + extensions_list/1, cert_auth_key_id/1, time_str_2_gregorian_sec/1, + gen_test_certs/1]). -define(NULL, 0). - + +-export_type([chain_opts/0, test_config/0]). + +-type cert_opt() :: {digest, public_key:digest_type()} | + {key, public_key:key_params() | public_key:private_key()} | + {validity, {From::erlang:timestamp(), To::erlang:timestamp()}} | + {extensions, [#'Extension'{}]}. +-type chain_end() :: root | peer. +-type chain_opts() :: #{chain_end() := [cert_opt()], intermediates => [[cert_opt()]]}. +-type conf_opt() :: {cert, public_key:der_encoded()} | + {key, public_key:der_encoded()} | + {cacerts, [public_key:der_encoded()]}. +-type test_config() :: #{server_config := [conf_opt()], client_config := [conf_opt()]}. %%==================================================================== -%% Internal application API +%% Internal application APIu %%==================================================================== %%-------------------------------------------------------------------- @@ -417,6 +430,31 @@ match_name(Fun, Name, PermittedName, [Head | Tail]) -> false -> match_name(Fun, Name, Head, Tail) end. +%%% +-spec gen_test_certs(#{server_chain:= chain_opts(), client_chain:= chain_opts()}) -> test_config(). + +%% Generates server and and client configuration for testing +%% purposes. All certificate options have default values +gen_test_certs(#{client_chain := #{root := ClientRootConf, + intermediates := ClientCAs, + peer := ClientPeer}, + server_chain := + #{root := ServerRootConf, + intermediates := ServerCAs, + peer := ServerPeer}}) -> + SRootKey = gen_key(proplists:get_value(key, ServerRootConf, default_key_gen())), + CRootKey = gen_key(proplists:get_value(key, ClientRootConf, default_key_gen())), + ServerRoot = root_cert("server", SRootKey, ClientRootConf), + ClientRoot = root_cert("client", CRootKey, ServerRootConf), + + [{ServerDERCert, ServerDERKey} | ServerCAsKeys] = config(server, ServerRoot, + SRootKey, lists:reverse([ServerPeer | lists:reverse(ServerCAs)])), + [{ClientDERCert, ClientDERKey} | ClientCAsKeys] = config(client, ClientRoot, + CRootKey, lists:reverse([ClientPeer | lists:reverse(ClientCAs)])), + ServerDERCA = ca_config(ClientRoot, ServerCAsKeys), + ClientDERCA = ca_config(ServerRoot, ClientCAsKeys), + #{server_config => [{cert, ServerDERCert}, {key, ServerDERKey}, {cacerts, ServerDERCA}], + client_config => [{cert, ClientDERCert}, {key, ClientDERKey}, {cacerts, ClientDERCA}]}. %%-------------------------------------------------------------------- %%% Internal functions @@ -1064,3 +1102,212 @@ missing_basic_constraints(OtpCert, SelfSigned, ValidationState, VerifyFun, UserS Len - 1}, UserState} end. + + gen_key(KeyGen) -> + case is_key(KeyGen) of + true -> + KeyGen; + false -> + public_key:generate_key(KeyGen) + end. + +is_key(#'DSAPrivateKey'{}) -> + true; +is_key(#'RSAPrivateKey'{}) -> + true; +is_key(#'ECPrivateKey'{}) -> + true; +is_key(_) -> + false. + +root_cert(Role, PrivKey, Opts) -> + TBS = cert_template(), + Issuer = issuer("root", Role, " ROOT CA"), + OTPTBS = TBS#'OTPTBSCertificate'{ + signature = sign_algorithm(PrivKey, Opts), + issuer = Issuer, + validity = validity(Opts), + subject = Issuer, + subjectPublicKeyInfo = public_key(PrivKey), + extensions = extensions(Role, ca, Opts) + }, + public_key:pkix_sign(OTPTBS, PrivKey). + +cert_template() -> + #'OTPTBSCertificate'{ + version = v3, + serialNumber = trunc(rand:uniform()*100000000)*10000 + 1, + issuerUniqueID = asn1_NOVALUE, + subjectUniqueID = asn1_NOVALUE + }. +issuer(Contact, Role, Name) -> + subject(Contact, Role ++ Name). + +subject(Contact, Name) -> + Opts = [{email, Contact ++ "@erlang.org"}, + {name, Name}, + {city, "Stockholm"}, + {country, "SE"}, + {org, "erlang"}, + {org_unit, "automated testing"}], + subject(Opts). + +subject(SubjectOpts) when is_list(SubjectOpts) -> + Encode = fun(Opt) -> + {Type,Value} = subject_enc(Opt), + [#'AttributeTypeAndValue'{type=Type, value=Value}] + end, + {rdnSequence, [Encode(Opt) || Opt <- SubjectOpts]}. + +subject_enc({name, Name}) -> + {?'id-at-commonName', {printableString, Name}}; +subject_enc({email, Email}) -> + {?'id-emailAddress', Email}; +subject_enc({city, City}) -> + {?'id-at-localityName', {printableString, City}}; +subject_enc({org, Org}) -> + {?'id-at-organizationName', {printableString, Org}}; +subject_enc({org_unit, OrgUnit}) -> + {?'id-at-organizationalUnitName', {printableString, OrgUnit}}; +subject_enc({country, Country}) -> + {?'id-at-countryName', Country}. + +validity(Opts) -> + DefFrom0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())-1), + DefTo0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+7), + {DefFrom, DefTo} = proplists:get_value(validity, Opts, {DefFrom0, DefTo0}), + Format = fun({Y,M,D}) -> + lists:flatten(io_lib:format("~w~2..0w~2..0w000000Z",[Y,M,D])) + end, + #'Validity'{notBefore={generalTime, Format(DefFrom)}, + notAfter ={generalTime, Format(DefTo)}}. + +sign_algorithm(#'RSAPrivateKey'{}, Opts) -> + Type = rsa_digest_oid(proplists:get_value(digest, Opts, sha1)), + #'SignatureAlgorithm'{algorithm = Type, + parameters = 'NULL'}; +sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) -> + #'SignatureAlgorithm'{algorithm = ?'id-dsa-with-sha1', + parameters = {params,#'Dss-Parms'{p=P, q=Q, g=G}}}; +sign_algorithm(#'ECPrivateKey'{parameters = Parms}, Opts) -> + Type = ecdsa_digest_oid(proplists:get_value(digest, Opts, sha1)), + #'SignatureAlgorithm'{algorithm = Type, + parameters = Parms}. +rsa_digest_oid(sha1) -> + ?'sha1WithRSAEncryption'; +rsa_digest_oid(sha512) -> + ?'sha512WithRSAEncryption'; +rsa_digest_oid(sha384) -> + ?'sha384WithRSAEncryption'; +rsa_digest_oid(sha256) -> + ?'sha256WithRSAEncryption'; +rsa_digest_oid(md5) -> + ?'md5WithRSAEncryption'. + +ecdsa_digest_oid(sha1) -> + ?'ecdsa-with-SHA1'; +ecdsa_digest_oid(sha512) -> + ?'ecdsa-with-SHA512'; +ecdsa_digest_oid(sha384) -> + ?'ecdsa-with-SHA384'; +ecdsa_digest_oid(sha256) -> + ?'ecdsa-with-SHA256'. + +config(Role, Root, Key, Opts) -> + cert_chain(Role, Root, Key, Opts). + +cert_chain(Role, Root, RootKey, Opts) -> + cert_chain(Role, Root, RootKey, Opts, 0, []). + +cert_chain(Role, IssuerCert, IssuerKey, [PeerOpts], _, Acc) -> + Key = gen_key(proplists:get_value(key, PeerOpts, default_key_gen())), + Cert = cert(Role, public_key:pkix_decode_cert(IssuerCert, otp), + IssuerKey, Key, "admin", " Peer cert", PeerOpts, peer), + [{Cert, Key}, {IssuerCert, IssuerKey} | Acc]; +cert_chain(Role, IssuerCert, IssuerKey, [CAOpts | Rest], N, Acc) -> + Key = gen_key(proplists:get_value(key, CAOpts, default_key_gen())), + Cert = cert(Role, public_key:pkix_decode_cert(IssuerCert, otp), IssuerKey, Key, "webadmin", + " Intermidiate CA " ++ integer_to_list(N), CAOpts, ca), + cert_chain(Role, Cert, Key, Rest, N+1, [{IssuerCert, IssuerKey} | Acc]). + +cert(Role, #'OTPCertificate'{tbsCertificate = #'OTPTBSCertificate'{subject = Issuer}}, + PrivKey, Key, Contact, Name, Opts, Type) -> + TBS = cert_template(), + OTPTBS = TBS#'OTPTBSCertificate'{ + signature = sign_algorithm(PrivKey, Opts), + issuer = Issuer, + validity = validity(Opts), + subject = subject(Contact, atom_to_list(Role) ++ Name), + subjectPublicKeyInfo = public_key(Key), + extensions = extensions(Role, Type, Opts) + + }, + public_key:pkix_sign(OTPTBS, PrivKey). + +ca_config(Root, CAsKeys) -> + [Root | [CA || {CA, _} <- CAsKeys]]. + +default_key_gen() -> + case crypto:ec_curves() of + [] -> + {rsa, 2048, 17}; + [Curve |_] -> + Oid = pubkey_cert_records:namedCurves(Curve), + {namedCurve, Oid} + end. + +public_key(#'RSAPrivateKey'{modulus=N, publicExponent=E}) -> + Public = #'RSAPublicKey'{modulus=N, publicExponent=E}, + Algo = #'PublicKeyAlgorithm'{algorithm= ?rsaEncryption, parameters='NULL'}, + #'OTPSubjectPublicKeyInfo'{algorithm = Algo, + subjectPublicKey = Public}; +public_key(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) -> + Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa', + parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}}, + #'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y}; +public_key(#'ECPrivateKey'{version = _Version, + privateKey = _PrivKey, + parameters = Params, + publicKey = PubKey}) -> + Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-ecPublicKey', parameters=Params}, + #'OTPSubjectPublicKeyInfo'{algorithm = Algo, + subjectPublicKey = #'ECPoint'{point = PubKey}}. + +extensions(Role, Type, Opts) -> + Exts = proplists:get_value(extensions, Opts, []), + add_default_extensions(Role, Type, Exts). + +add_default_extensions(_, ca, Exts) -> + Default = [#'Extension'{extnID = ?'id-ce-keyUsage', + extnValue = [keyCertSign, cRLSign], + critical = false}, + #'Extension'{extnID = ?'id-ce-basicConstraints', + extnValue = #'BasicConstraints'{cA = true}, + critical = true}], + add_default_extensions(Default, Exts); + +add_default_extensions(server, peer, Exts) -> + Hostname = net_adm:localhost(), + Default = [#'Extension'{extnID = ?'id-ce-keyUsage', + extnValue = [digitalSignature, keyAgreement], + critical = false}, + #'Extension'{extnID = ?'id-ce-subjectAltName', + extnValue = [{dNSName, Hostname}], + critical = false} + ], + add_default_extensions(Default, Exts); + +add_default_extensions(_, peer, Exts) -> + Exts. + +add_default_extensions(Defaults0, Exts) -> + Defaults = lists:filtermap(fun(#'Extension'{extnID = ID} = Ext) -> + case lists:keymember(ID, 2, Exts) of + true -> + false; + false -> + {true, Ext} + end + end, Defaults0), + Exts ++ Defaults. + diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index c2060c144c..cc01b61433 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -58,11 +58,13 @@ pkix_match_dist_point/2, pkix_crl_verify/2, pkix_crl_issuer/1, - short_name_hash/1 + short_name_hash/1, + pkix_test_data/1 ]). -export_type([public_key/0, private_key/0, pem_entry/0, - pki_asn1_type/0, asn1_type/0, ssh_file/0, der_encoded/0]). + pki_asn1_type/0, asn1_type/0, ssh_file/0, der_encoded/0, + key_params/0, digest_type/0]). -type public_key() :: rsa_public_key() | dsa_public_key() | ec_public_key(). -type private_key() :: rsa_private_key() | dsa_private_key() | ec_private_key(). @@ -71,8 +73,12 @@ -type rsa_private_key() :: #'RSAPrivateKey'{}. -type dsa_private_key() :: #'DSAPrivateKey'{}. -type dsa_public_key() :: {integer(), #'Dss-Parms'{}}. --type ec_public_key() :: {#'ECPoint'{},{namedCurve, Oid::tuple()} | #'ECParameters'{}}. +-type ecpk_parameters() :: {ecParameters, #'ECParameters'{}} | {namedCurve, Oid::tuple()}. +-type ecpk_parameters_api() :: ecpk_parameters() | #'ECParameters'{} | {namedCurve, Name::atom()}. +-type ec_public_key() :: {#'ECPoint'{}, ecpk_parameters_api()}. -type ec_private_key() :: #'ECPrivateKey'{}. +-type key_params() :: #'DHParameter'{} | {namedCurve, oid()} | #'ECParameters'{} | + {rsa, Size::integer(), PubExp::integer()}. -type der_encoded() :: binary(). -type pki_asn1_type() :: 'Certificate' | 'RSAPrivateKey' | 'RSAPublicKey' | 'DSAPrivateKey' | 'DSAPublicKey' | 'DHParameter' @@ -100,6 +106,7 @@ -type crl_reason() :: unspecified | keyCompromise | cACompromise | affiliationChanged | superseded | cessationOfOperation | certificateHold | privilegeWithdrawn | aACompromise. -type oid() :: tuple(). +-type chain_type() :: server_chain | client_chain. -define(UINT32(X), X:32/unsigned-big-integer). -define(DER_NULL, <<5, 0>>). @@ -399,9 +406,7 @@ dh_gex_group(Min, N, Max, Groups) -> %%-------------------------------------------------------------------- -spec generate_key(#'DHParameter'{}) -> {Public::binary(), Private::binary()}; - ({namedCurve, Name ::oid()}) -> - #'ECPrivateKey'{}; - (#'ECParameters'{}) -> + (ecpk_parameters_api()) -> #'ECPrivateKey'{}; ({rsa, Size::pos_integer(), PubExp::pos_integer()}) -> #'RSAPrivateKey'{}. @@ -412,6 +417,8 @@ generate_key(#'DHParameter'{prime = P, base = G}) -> crypto:generate_key(dh, [P, G]); generate_key({namedCurve, _} = Params) -> ec_generate_key(Params); +generate_key({ecParameters, _} = Params) -> + ec_generate_key(Params); generate_key(#'ECParameters'{} = Params) -> ec_generate_key(Params); generate_key({rsa, ModulusSize, PublicExponent}) -> @@ -1025,6 +1032,22 @@ short_name_hash({rdnSequence, _Attributes} = Name) -> <<HashValue:32/little, _/binary>> = crypto:hash(sha, HashThis), string:to_lower(string:right(integer_to_list(HashValue, 16), 8, $0)). + +%%-------------------------------------------------------------------- +-spec pkix_test_data(#{chain_type() := pubkey_cert:chain_opts()}) -> + pubkey_cert:test_config(). + +%% Description: Generates OpenSSL-style hash of a name. +%%-------------------------------------------------------------------- + +pkix_test_data(#{client_chain := ClientChain0, + server_chain := ServerChain0}) -> + Default = #{intermediates => []}, + ClientChain = maps:merge(Default, ClientChain0), + ServerChain = maps:merge(Default, ServerChain0), + pubkey_cert:gen_test_certs(#{client_chain => ClientChain, + server_chain => ServerChain}). + %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- @@ -1286,22 +1309,34 @@ format_rsa_private_key(#'RSAPrivateKey'{modulus = N, publicExponent = E, is_integer(D) -> [E, N, D]. +-spec ec_generate_key(ecpk_parameters_api()) -> #'ECPrivateKey'{}. ec_generate_key(Params) -> Curve = ec_curve_spec(Params), Term = crypto:generate_key(ecdh, Curve), - ec_key(Term, Params). + NormParams = ec_normalize_params(Params), + ec_key(Term, NormParams). +-spec ec_normalize_params(ecpk_parameters_api()) -> ecpk_parameters(). +ec_normalize_params({namedCurve, Name}) when is_atom(Name) -> + {namedCurve, pubkey_cert_records:namedCurves(Name)}; +ec_normalize_params(#'ECParameters'{} = ECParams) -> + {ecParameters, ECParams}; +ec_normalize_params(Other) -> Other. + +-spec ec_curve_spec(ecpk_parameters_api()) -> term(). ec_curve_spec( #'ECParameters'{fieldID = FieldId, curve = PCurve, base = Base, order = Order, cofactor = CoFactor }) -> Field = {pubkey_cert_records:supportedCurvesTypes(FieldId#'FieldID'.fieldType), FieldId#'FieldID'.parameters}, Curve = {PCurve#'Curve'.a, PCurve#'Curve'.b, none}, {Field, Curve, Base, Order, CoFactor}; +ec_curve_spec({ecParameters, ECParams}) -> + ec_curve_spec(ECParams); ec_curve_spec({namedCurve, OID}) when is_tuple(OID), is_integer(element(1,OID)) -> ec_curve_spec({namedCurve, pubkey_cert_records:namedCurves(OID)}); ec_curve_spec({namedCurve, Name}) when is_atom(Name) -> crypto:ec_curve(Name). - +-spec ec_key({PubKey::term(), PrivateKey::term()}, Params::ecpk_parameters()) -> #'ECPrivateKey'{}. ec_key({PubKey, PrivateKey}, Params) -> #'ECPrivateKey'{version = 1, privateKey = PrivateKey, diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl index 80895ce97c..374fb20375 100644 --- a/lib/public_key/test/public_key_SUITE.erl +++ b/lib/public_key/test/public_key_SUITE.erl @@ -48,6 +48,8 @@ all() -> pkix_verify_hostname_cn, pkix_verify_hostname_subjAltName, pkix_verify_hostname_options, + pkix_test_data_all_default, + pkix_test_data, short_cert_issuer_hash, short_crl_issuer_hash, ssh_hostkey_fingerprint_md5_implicit, ssh_hostkey_fingerprint_md5, @@ -60,7 +62,8 @@ all() -> groups() -> [{pem_decode_encode, [], [dsa_pem, rsa_pem, ec_pem, encrypted_pem, - dh_pem, cert_pem, pkcs7_pem, pkcs10_pem]}, + dh_pem, cert_pem, pkcs7_pem, pkcs10_pem, ec_pem2, + ec_pem_encode_generated]}, {ssh_public_key_decode_encode, [], [ssh_rsa_public_key, ssh_dsa_public_key, ssh_ecdsa_public_key, ssh_rfc4716_rsa_comment, ssh_rfc4716_dsa_comment, @@ -92,6 +95,14 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. %%------------------------------------------------------------------- + +init_per_testcase(pkix_test_data_all_default, Config) -> + case crypto:ec_curves() of + [] -> + {skip, missing_ecc_support}; + _ -> + init_common_per_testcase(Config) + end; init_per_testcase(TestCase, Config) -> case TestCase of ssh_hostkey_fingerprint_md5_implicit -> init_fingerprint_testcase([md5], Config); @@ -101,6 +112,7 @@ init_per_testcase(TestCase, Config) -> ssh_hostkey_fingerprint_sha384 -> init_fingerprint_testcase([sha384], Config); ssh_hostkey_fingerprint_sha512 -> init_fingerprint_testcase([sha512], Config); ssh_hostkey_fingerprint_list -> init_fingerprint_testcase([sha,md5], Config); + ec_pem_encode_generated -> init_ec_pem_encode_generated(Config); _ -> init_common_per_testcase(Config) end. @@ -217,9 +229,47 @@ ec_pem(Config) when is_list(Config) -> true = check_entry_type(ECParams, 'EcpkParameters'), ECPrivKey = public_key:pem_entry_decode(Entry2), true = check_entry_type(ECPrivKey, 'ECPrivateKey'), + true = check_entry_type(ECPrivKey#'ECPrivateKey'.parameters, 'EcpkParameters'), ECPemNoEndNewLines = strip_superfluous_newlines(ECPrivPem), ECPemNoEndNewLines = strip_superfluous_newlines(public_key:pem_encode([Entry1, Entry2])). +ec_pem2() -> + [{doc, "EC key w/explicit params PEM-file decode/encode"}]. +ec_pem2(Config) when is_list(Config) -> + Datadir = proplists:get_value(data_dir, Config), + + %% Load key with explicit curve parameters. Generated with... + %% openssl ecparam -name secp521r1 -genkey -param_enc explicit -out ec_key2.pem + {ok, ECPrivPem} = file:read_file(filename:join(Datadir, "ec_key2.pem")), + [{'EcpkParameters', _, not_encrypted} = Entry1, + {'ECPrivateKey', _, not_encrypted} = Entry2] = public_key:pem_decode(ECPrivPem), + + ECParams = public_key:pem_entry_decode(Entry1), + true = check_entry_type(ECParams, 'EcpkParameters'), + ECPrivKey = public_key:pem_entry_decode(Entry2), + true = check_entry_type(ECPrivKey, 'ECPrivateKey'), + true = check_entry_type(ECPrivKey#'ECPrivateKey'.parameters, 'EcpkParameters'), + ECPemNoEndNewLines = strip_superfluous_newlines(ECPrivPem), + ECPemNoEndNewLines = strip_superfluous_newlines(public_key:pem_encode([Entry1, Entry2])). + + +init_ec_pem_encode_generated(Config) -> + case catch true = lists:member('secp384r1', crypto:ec_curves()) of + {'EXIT', _} -> {skip, {'secp384r1', not_supported}}; + _ -> init_common_per_testcase(Config) + end. + +ec_pem_encode_generated() -> + [{doc, "PEM-encode generated EC key"}]. +ec_pem_encode_generated(Config) -> + + Key1 = public_key:generate_key({namedCurve, 'secp384r1'}), + public_key:pem_entry_encode('ECPrivateKey', Key1), + + Key2 = public_key:generate_key({namedCurve, ?'secp384r1'}), + public_key:pem_entry_encode('ECPrivateKey', Key2). + + %%-------------------------------------------------------------------- encrypted_pem() -> @@ -1007,6 +1057,84 @@ general_name(Config) when is_list(Config) -> authorityCertSerialNumber = 1}). %%-------------------------------------------------------------------- + +pkix_test_data_all_default() -> + [{doc, "Test API function pkix_test_data/1"}]. + +pkix_test_data_all_default(Config) when is_list(Config) -> + #{server_config := ServerConf0, + client_config := ClientConf0} = public_key:pkix_test_data(#{server_chain => + #{root => [], + intermediates => [[]], + peer => []}, + client_chain => + #{root => [], + intermediates => [[]], + peer => []}}), + check_conf_member(ServerConf0, [key, cert, cacerts]), + check_conf_member(ClientConf0, [key, cert, cacerts]), + + 3 = length(proplists:get_value(cacerts, ServerConf0)), + 3 = length(proplists:get_value(cacerts, ServerConf0)), + + #{server_config := ServerConf1, + client_config := ClientConf1} = public_key:pkix_test_data(#{server_chain => + #{root => [], + peer => []}, + client_chain => + #{root => [], + peer => []}}), + 2 = length(proplists:get_value(cacerts, ServerConf1)), + 2 = length(proplists:get_value(cacerts, ServerConf1)), + + check_conf_member(ServerConf1, [key, cert, cacerts]), + check_conf_member(ClientConf1, [key, cert, cacerts]). + + +pkix_test_data() -> + [{doc, "Test API function pkix_test_data/1"}]. + +pkix_test_data(Config) when is_list(Config) -> + {Year, Month, Day} = date(), + Keygen = + case crypto:ec_curves() of + [] -> + {rsa, 2048, 17}; + [Curve |_] -> + Oid = pubkey_cert_records:namedCurves(Curve), + {namedCurve, Oid} + end, + #{server_config := ServerConf0, + client_config := ClientConf0} = + public_key:pkix_test_data(#{server_chain => + #{root => [], + intermediates => [], + peer => [{key, hardcode_rsa_key()}]}, + client_chain => + #{root => [{validity, {{Year-2, Month, Day}, + {Year-1, Month, Day}}}], + intermediates => + [[{extensions, [#'Extension'{extnID = ?'id-ce-basicConstraints', + extnValue = #'BasicConstraints'{cA=true, + pathLenConstraint = 1}, + critical = true}]}]], + peer => [{key, Keygen}, {digest, sha1}]}}), + check_conf_member(ServerConf0, [key, cert, cacerts]), + check_conf_member(ClientConf0, [key, cert, cacerts]). + + + +check_conf_member(_, []) -> + true; +check_conf_member(Conf, [Member | Rest]) -> + case lists:keymember(Member, 1, Conf) of + true -> + check_conf_member(Conf, Rest); + false -> + ct:fail({misssing_conf, Member}) + end. + +%%-------------------------------------------------------------------- short_cert_issuer_hash() -> [{doc, "Test OpenSSL-style hash for certificate issuer"}]. @@ -1095,7 +1223,7 @@ check_entry_type(#'ECPrivateKey'{}, 'ECPrivateKey') -> true; check_entry_type({namedCurve, _}, 'EcpkParameters') -> true; -check_entry_type(#'ECParameters'{}, 'EcpkParameters') -> +check_entry_type({ecParameters, #'ECParameters'{}}, 'EcpkParameters') -> true; check_entry_type(_,_) -> false. @@ -1128,3 +1256,15 @@ ssh_hostkey(rsa) -> public_key), PKdecoded. +hardcode_rsa_key() -> + #'RSAPrivateKey'{ + version = 'two-prime', + modulus = 23995666614853919027835084074500048897452890537492185072956789802729257783422306095699263934587064480357348855732149402060270996295002843755712064937715826848741191927820899197493902093529581182351132392364214171173881547273475904587683433713767834856230531387991145055273426806331200574039205571401702219159773947658558490957010003143162250693492642996408861265758000254664396313741422909188635443907373976005987612936763564996605457102336549804831742940035613780926178523017685712710473543251580072875247250504243621640157403744718833162626193206685233710319205099867303242759099560438381385658382486042995679707669, + publicExponent = 17, + privateExponent = 11292078406990079542510627799764728892919007311761028269626724613049062486316379339152594792746853873109340637991599718616598115903530750002688030558925094987642913848386305504703012749896273497577003478759630198199473669305165131570674557041773098755873191241407597673069847908861741446606684974777271632545629600685952292605647052193819136445675100211504432575554351515262198132231537860917084269870590492135731720141577986787033006338680118008484613510063003323516659048210893001173583018220214626635609151105287049126443102976056146630518124476470236027123782297108342869049542023328584384300970694412006494684657, + prime1 = 169371138592582642967021557955633494538845517070305333860805485424261447791289944610138334410987654265476540480228705481960508520379619587635662291973699651583489223555422528867090299996446070521801757353675026048850480903160224210802452555900007597342687137394192939372218903554801584969667104937092080815197, + prime2 = 141675062317286527042995673340952251894209529891636708844197799307963834958115010129693036021381525952081167155681637592199810112261679449166276939178032066869788822014115556349519329537177920752776047051833616197615329017439297361972726138285974555338480581117881706656603857310337984049152655480389797687577, + exponent1 = 119556097830058336212015217380447172615655659108450823901745048534772786676204666783627059584226579481512852103690850928442711896738555003036938088452023283470698275450886490965004917644550167427154181661417665446247398284583687678213495921811770068712485038160606780733330990744565824684470897602653233516609, + exponent2 = 41669135975672507953822256864985956439473391144599032012999352737636422046504414744027363535700448809435637398729893409470532385959317485048904982111185902020526124121798693043976273393287623750816484427009887116945685005129205106462566511260580751570141347387612266663707016855981760014456663376585234613993, + coefficient = 76837684977089699359024365285678488693966186052769523357232308621548155587515525857011429902602352279058920284048929101483304120686557782043616693940283344235057989514310975192908256494992960578961614059245280827077951132083993754797053182279229469590276271658395444955906108899267024101096069475145863928441, + otherPrimeInfos = asn1_NOVALUE}. diff --git a/lib/public_key/test/public_key_SUITE_data/ec_key2.pem b/lib/public_key/test/public_key_SUITE_data/ec_key2.pem new file mode 100644 index 0000000000..56b8169e86 --- /dev/null +++ b/lib/public_key/test/public_key_SUITE_data/ec_key2.pem @@ -0,0 +1,29 @@ +-----BEGIN EC PARAMETERS----- +MIIBwgIBATBNBgcqhkjOPQEBAkIB//////////////////////////////////// +//////////////////////////////////////////////////8wgZ4EQgH///// +//////////////////////////////////////////////////////////////// +/////////////////ARBUZU+uWGOHJofkpohoLaFQO6i2nJbmbMV87i0iZGO8Qnh +Vhk5Uex+k3sWUsC9O7G/BzVz34g9LDTx70Uf1GtQPwADFQDQnogAKRy4U5bMZxc5 +MoSqoNpkugSBhQQAxoWOBrcEBOnNnj7LZiOVtEKcZIE5BT+1Ifgor2BrTT26oUte +d+/nWSj+HcEnov+o3jNIs8GFakKb+X5+McLlvWYBGDkpaniaO8AEXIpftCx9G9mY +9URJV5tEaBevvRcnPmYsl+5ymV70JkDFULkBP60HYTU8cIaicsJAiL6Udp/RZlAC +QgH///////////////////////////////////////////pRhoeDvy+Wa3/MAUj3 +CaXQO7XJuImcR667b7cekThkCQIBAQ== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MIICnQIBAQRCAVE6lUKRj5AE8Cw21A+iPWhXSg+XNuerrTyeFERY6AtOrRJ9mTQ3 +Av3xjiM3zhZy2KWnm62hvkvlGbZ7iDKcqg2GoIIBxjCCAcICAQEwTQYHKoZIzj0B +AQJCAf////////////////////////////////////////////////////////// +////////////////////////////MIGeBEIB//////////////////////////// +//////////////////////////////////////////////////////////wEQVGV +PrlhjhyaH5KaIaC2hUDuotpyW5mzFfO4tImRjvEJ4VYZOVHsfpN7FlLAvTuxvwc1 +c9+IPSw08e9FH9RrUD8AAxUA0J6IACkcuFOWzGcXOTKEqqDaZLoEgYUEAMaFjga3 +BATpzZ4+y2YjlbRCnGSBOQU/tSH4KK9ga009uqFLXnfv51ko/h3BJ6L/qN4zSLPB +hWpCm/l+fjHC5b1mARg5KWp4mjvABFyKX7QsfRvZmPVESVebRGgXr70XJz5mLJfu +cple9CZAxVC5AT+tB2E1PHCGonLCQIi+lHaf0WZQAkIB//////////////////// +///////////////////////6UYaHg78vlmt/zAFI9wml0Du1ybiJnEeuu2+3HpE4 +ZAkCAQGhgYkDgYYABAFLBJzBphlIJmSPuXzTDTnZpL7A0fnyqit9V3TBvaOcL6Iw +6m2TpXvNakxi8Flj0Ok4hdRt+YhawFs0bmzZCT8kfAFs7p55BPHk7FaMZaba77R8 +4V6MhUJSKLc0I/XQBtvoOgVlPJ0MPOndnIxPspCPll886yxG5kOMUAx3HjFg16RT +eA== +-----END EC PRIVATE KEY----- diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk index 83a77d2a28..bb96c2237d 100644 --- a/lib/public_key/vsn.mk +++ b/lib/public_key/vsn.mk @@ -1 +1 @@ -PUBLIC_KEY_VSN = 1.4.1 +PUBLIC_KEY_VSN = 1.5 diff --git a/lib/reltool/doc/src/notes.xml b/lib/reltool/doc/src/notes.xml index 8593a1017f..d7ad7c8dcc 100644 --- a/lib/reltool/doc/src/notes.xml +++ b/lib/reltool/doc/src/notes.xml @@ -38,7 +38,26 @@ thus constitutes one section in this document. The title of each section is the version number of Reltool.</p> - <section><title>Reltool 0.7.4</title> + <section><title>Reltool 0.7.5</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Files generated by <c>release_handler</c> and + <c>reltool</c>, which might contain Unicode characters, + are now encoded as UTF-8 and written with format "~tp" or + "~ts". If the file is to be read by + <c>file:consult/1</c>, an encoding comment is added.</p> + <p> + Own Id: OTP-14463</p> + </item> + </list> + </section> + +</section> + +<section><title>Reltool 0.7.4</title> <section><title>Improvements and New Features</title> <list> diff --git a/lib/reltool/src/reltool.app.src b/lib/reltool/src/reltool.app.src index 90f93d2901..dc21c1cfce 100644 --- a/lib/reltool/src/reltool.app.src +++ b/lib/reltool/src/reltool.app.src @@ -36,6 +36,6 @@ {registered, []}, {applications, [stdlib, kernel]}, {env, []}, - {runtime_dependencies, ["wx-1.2","tools-2.6.14","stdlib-2.0","sasl-2.4", + {runtime_dependencies, ["wx-1.2","tools-2.6.14","stdlib-3.4","sasl-2.4", "kernel-3.0","erts-7.0"]} ]}. diff --git a/lib/reltool/src/reltool_mod_win.erl b/lib/reltool/src/reltool_mod_win.erl index 894d6e2ecb..dcd802a5de 100644 --- a/lib/reltool/src/reltool_mod_win.erl +++ b/lib/reltool/src/reltool_mod_win.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2016. All Rights Reserved. +%% Copyright Ericsson AB 2009-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/reltool/src/reltool_target.erl b/lib/reltool/src/reltool_target.erl index 1b1461178e..676ce70aea 100644 --- a/lib/reltool/src/reltool_target.erl +++ b/lib/reltool/src/reltool_target.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2016. All Rights Reserved. +%% Copyright Ericsson AB 2009-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/reltool/src/reltool_utils.erl b/lib/reltool/src/reltool_utils.erl index 3891b5ae4d..1a00671f13 100644 --- a/lib/reltool/src/reltool_utils.erl +++ b/lib/reltool/src/reltool_utils.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2016. All Rights Reserved. +%% Copyright Ericsson AB 2009-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/reltool/test/reltool_app_SUITE.erl b/lib/reltool/test/reltool_app_SUITE.erl index 18c74bea6c..a51ee8875a 100644 --- a/lib/reltool/test/reltool_app_SUITE.erl +++ b/lib/reltool/test/reltool_app_SUITE.erl @@ -24,7 +24,7 @@ %%---------------------------------------------------------------------- -module(reltool_app_SUITE). --compile(export_all). +-compile([export_all, nowarn_export_all]). -include("reltool_test_lib.hrl"). -include_lib("common_test/include/ct.hrl"). diff --git a/lib/reltool/test/reltool_manual_gui_SUITE.erl b/lib/reltool/test/reltool_manual_gui_SUITE.erl index eebe2303fb..44da4ffd2c 100644 --- a/lib/reltool/test/reltool_manual_gui_SUITE.erl +++ b/lib/reltool/test/reltool_manual_gui_SUITE.erl @@ -23,7 +23,7 @@ init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2]). --compile(export_all). +-export([config/1, depgraphs/1]). -include_lib("common_test/include/ct.hrl"). -include("reltool_test_lib.hrl"). diff --git a/lib/reltool/test/reltool_server_SUITE.erl b/lib/reltool/test/reltool_server_SUITE.erl index e8dfea94da..db13c56238 100644 --- a/lib/reltool/test/reltool_server_SUITE.erl +++ b/lib/reltool/test/reltool_server_SUITE.erl @@ -19,11 +19,7 @@ -module(reltool_server_SUITE). --export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, - init_per_suite/1, end_per_suite/1, - init_per_testcase/2, end_per_testcase/2]). - --compile(export_all). +-compile([export_all, nowarn_export_all]). -include_lib("reltool/src/reltool.hrl"). -include("reltool_test_lib.hrl"). @@ -2549,7 +2545,7 @@ undefined_regexp(_Config) -> %% Library functions erl_libs() -> - string:tokens(os:getenv("ERL_LIBS", ""), ":;"). + string:lexemes(os:getenv("ERL_LIBS", ""), ":;"). datadir(Config) -> %% Removes the trailing slash... @@ -2559,7 +2555,7 @@ latest(App) -> AppStr = atom_to_list(App), AppDirs = filelib:wildcard(filename:join(code:lib_dir(),AppStr++"-*")), [LatestAppDir|_] = lists:reverse(AppDirs), - [_,Vsn] = string:tokens(filename:basename(LatestAppDir),"-"), + [_,Vsn] = string:lexemes(filename:basename(LatestAppDir),"-"), Vsn. rm_missing_app(Apps) -> @@ -2635,16 +2631,11 @@ os_cmd(Cmd) when is_list(Cmd) -> Return-> %% Find the position of the status code wich is last in the string %% prepended with # - case string:rchr(Return, $#) of - - %% This happens only if the sh command pipe is somehow interrupted - 0-> - {98, Return}; - - Position-> - Result = string:left(Return,Position - 1), - Status = string:substr(Return,Position + 1, length(Return) - Position - 1), - {list_to_integer(Status), Result} + case string:split(Return, "$#", trailing) of + [_] -> %% This happens only if the sh command pipe is somehow interrupted + {98, Return}; + [Result, Status0] -> + {list_to_integer(string:trim(Status0)), Result} end end. diff --git a/lib/reltool/test/reltool_test_lib.erl b/lib/reltool/test/reltool_test_lib.erl index 6cc2d259fb..53aeb8c08c 100644 --- a/lib/reltool/test/reltool_test_lib.erl +++ b/lib/reltool/test/reltool_test_lib.erl @@ -18,7 +18,7 @@ %% %CopyrightEnd% -module(reltool_test_lib). --compile(export_all). +-compile([export_all, nowarn_export_all]). -include("reltool_test_lib.hrl"). -define(timeout, 20). % minutes diff --git a/lib/reltool/test/reltool_wx_SUITE.erl b/lib/reltool/test/reltool_wx_SUITE.erl index ac820db21c..19707894ae 100644 --- a/lib/reltool/test/reltool_wx_SUITE.erl +++ b/lib/reltool/test/reltool_wx_SUITE.erl @@ -23,7 +23,7 @@ init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2]). --compile(export_all). +-export([start_all_windows/1, check_no_win_crash/0, wait_terminate/1]). -include("reltool_test_lib.hrl"). diff --git a/lib/reltool/test/rtt.erl b/lib/reltool/test/rtt.erl index 173ffc5166..d9e8e5520d 100644 --- a/lib/reltool/test/rtt.erl +++ b/lib/reltool/test/rtt.erl @@ -18,7 +18,7 @@ %% %CopyrightEnd% -module(rtt). --compile(export_all). +-compile([export_all, nowarn_export_all]). %% Modules or suites can be shortcuts, for example server expands to reltool_server_SUITE. %% diff --git a/lib/reltool/vsn.mk b/lib/reltool/vsn.mk index 3617f6e0d9..49997b1e52 100644 --- a/lib/reltool/vsn.mk +++ b/lib/reltool/vsn.mk @@ -1 +1 @@ -RELTOOL_VSN = 0.7.4 +RELTOOL_VSN = 0.7.5 diff --git a/lib/runtime_tools/doc/src/notes.xml b/lib/runtime_tools/doc/src/notes.xml index d50994306b..8b4d437c26 100644 --- a/lib/runtime_tools/doc/src/notes.xml +++ b/lib/runtime_tools/doc/src/notes.xml @@ -32,6 +32,21 @@ <p>This document describes the changes made to the Runtime_Tools application.</p> +<section><title>Runtime_Tools 1.12.2</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + General Unicode improvements.</p> + <p> + Own Id: OTP-14462</p> + </item> + </list> + </section> + +</section> + <section><title>Runtime_Tools 1.12.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/runtime_tools/src/erts_alloc_config.erl b/lib/runtime_tools/src/erts_alloc_config.erl index 514530332c..342363d08d 100644 --- a/lib/runtime_tools/src/erts_alloc_config.erl +++ b/lib/runtime_tools/src/erts_alloc_config.erl @@ -621,7 +621,7 @@ format_header(FTO) -> [Y, Mo, D, H, Mi, S]), fcp(FTO, "~s was used when generating the configuration.", - [string:strip(erlang:system_info(system_version), both, $\n)]), + [string:trim(erlang:system_info(system_version), both, "$\n")]), case erlang:system_info(schedulers) of 1 -> ok; Schdlrs -> @@ -698,28 +698,32 @@ fc(IODev, Frmt, Args) -> fc(IODev, lists:flatten(io_lib:format(Frmt, Args))). fc(IODev, String) -> - fc_aux(IODev, string:tokens(String, " "), 0). + fc_aux(IODev, string:lexemes(String, " "), 0). fc_aux(_IODev, [], 0) -> ok; fc_aux(IODev, [], _Len) -> format(IODev, "~n"); fc_aux(IODev, [T|Ts], 0) -> - Len = 2 + length(T), + Len = 2 + string:length(T), format(IODev, "# ~s", [T]), fc_aux(IODev, Ts, Len); -fc_aux(IODev, [T|_Ts] = ATs, Len) when (length(T) + Len) >= ?PRINT_WITDH -> - format(IODev, "~n"), - fc_aux(IODev, ATs, 0); -fc_aux(IODev, [T|Ts], Len) -> - NewLen = Len + 1 + length(T), - format(IODev, " ~s", [T]), - fc_aux(IODev, Ts, NewLen). +fc_aux(IODev, [T|Ts] = ATs, Len) -> + TLength = string:length(T), + case (TLength + Len) >= ?PRINT_WITDH of + true -> + format(IODev, "~n"), + fc_aux(IODev, ATs, 0); + false -> + NewLen = Len + 1 + TLength, + format(IODev, " ~s", [T]), + fc_aux(IODev, Ts, NewLen) + end. %% fcl: format comment line fcl(FTO) -> EndStr = "# ", - Precision = length(EndStr), + Precision = string:length(EndStr), FieldWidth = -1*(?PRINT_WITDH), format(FTO, "~*.*.*s~n", [FieldWidth, Precision, $-, EndStr]). @@ -727,6 +731,6 @@ fcl(FTO, A) when is_atom(A) -> fcl(FTO, atom_to_list(A)); fcl(FTO, Str) when is_list(Str) -> Str2 = "# --- " ++ Str ++ " ", - Precision = length(Str2), + Precision = string:length(Str2), FieldWidth = -1*(?PRINT_WITDH), format(FTO, "~*.*.*s~n", [FieldWidth, Precision, $-, Str2]). diff --git a/lib/runtime_tools/src/system_information.erl b/lib/runtime_tools/src/system_information.erl index df25297eb9..92109c9a74 100644 --- a/lib/runtime_tools/src/system_information.erl +++ b/lib/runtime_tools/src/system_information.erl @@ -590,12 +590,12 @@ vsnstr2vsn(VsnStr) -> list_to_tuple(lists:map(fun (Part) -> list_to_integer(Part) end, - string:tokens(VsnStr, "."))). + string:lexemes(VsnStr, "."))). rtdepstrs2rtdeps([]) -> []; rtdepstrs2rtdeps([RTDep | RTDeps]) -> - [AppStr, VsnStr] = string:tokens(RTDep, "-"), + [AppStr, VsnStr] = string:lexemes(RTDep, "-"), [{list_to_atom(AppStr), vsnstr2vsn(VsnStr)} | rtdepstrs2rtdeps(RTDeps)]. build_app_table([], AppTab) -> diff --git a/lib/runtime_tools/vsn.mk b/lib/runtime_tools/vsn.mk index 7296221033..d8a4ede136 100644 --- a/lib/runtime_tools/vsn.mk +++ b/lib/runtime_tools/vsn.mk @@ -1 +1 @@ -RUNTIME_TOOLS_VSN = 1.12.1 +RUNTIME_TOOLS_VSN = 1.12.2 diff --git a/lib/sasl/doc/src/notes.xml b/lib/sasl/doc/src/notes.xml index bc35939d7e..b144122c4b 100644 --- a/lib/sasl/doc/src/notes.xml +++ b/lib/sasl/doc/src/notes.xml @@ -31,6 +31,41 @@ </header> <p>This document describes the changes made to the SASL application.</p> +<section><title>SASL 3.1</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + General Unicode improvements.</p> + <p> + Own Id: OTP-14462</p> + </item> + <item> + <p> + Files generated by <c>release_handler</c> and + <c>reltool</c>, which might contain Unicode characters, + are now encoded as UTF-8 and written with format "~tp" or + "~ts". If the file is to be read by + <c>file:consult/1</c>, an encoding comment is added.</p> + <p> + Own Id: OTP-14463</p> + </item> + <item> + <p> + The SASL error logger event handler, + <c>sasl_report_file_h</c>, will now by default open its + log file with encoding UTF-8. This can be overridden when + configuring SASL, see configuration parameter + <c>sasl_error_logger</c> in the SASL reference manual.</p> + <p> + Own Id: OTP-14618</p> + </item> + </list> + </section> + +</section> + <section><title>SASL 3.0.4</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/sasl/src/erlsrv.erl b/lib/sasl/src/erlsrv.erl index 29d40d362f..e0bbd37ee3 100644 --- a/lib/sasl/src/erlsrv.erl +++ b/lib/sasl/src/erlsrv.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2016. All Rights Reserved. +%% Copyright Ericsson AB 1998-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -34,7 +34,7 @@ erlsrv(EVer) -> filename:join([Root, "erts-" ++ EVer, "bin", "erlsrv.exe"]). current_version() -> - hd(string:tokens(erlang:system_info(version),"_ ")). + hd(string:lexemes(erlang:system_info(version),"_ ")). %%% Returns {ok, Output} | failed | {error, Reason} run_erlsrv(Command) -> @@ -107,7 +107,7 @@ get_all_services() -> []; {ok, [_H|T]} -> F = fun(X) -> - hd(string:tokens(X,"\t ")) + hd(string:lexemes(X,"\t ")) end, lists:map(F,T); _ -> @@ -191,8 +191,8 @@ get_service(EVer, ServiceName) -> %%% have in the environment list... EnvParts = lists:map( fun(S) -> - X = string:strip(S,left,$\t), - case hd(string:tokens(X,"=")) of + X = string:trim(S, leading, "$\t"), + case hd(string:lexemes(X,"=")) of X -> %% Can this happen? {X,""}; @@ -371,7 +371,7 @@ split_arglist([H|T]) -> parse_arglist(Str) -> lists:reverse(parse_arglist(Str,[])). parse_arglist(Str,Accum) -> - Stripped = string:strip(Str,left), + Stripped = string:trim(Str, leading), case length(Stripped) of 0 -> Accum; @@ -432,14 +432,9 @@ split_by_env(Data) -> splitline(Line) -> - case string:chr(Line,$:) of - 0 -> + case string:split(Line, ":") of + [_] -> {Line, ""}; - N -> - case length(string:substr(Line,N)) of - 1 -> - {string:substr(Line,1,N-1),""}; - _ -> - {string:substr(Line,1,N-1),string:substr(Line,N+2)} - end + [N, V] -> + {N, string:slice(V, 1)} end. diff --git a/lib/sasl/src/format_lib_supp.erl b/lib/sasl/src/format_lib_supp.erl index 80dcdc91da..cfe2ec7668 100644 --- a/lib/sasl/src/format_lib_supp.erl +++ b/lib/sasl/src/format_lib_supp.erl @@ -100,13 +100,13 @@ print_newlines(Device, N) when N > 0 -> print_one_line(Device, Line, Key, Value) -> Modifier = misc_supp:modifier(Device), StrKey = term_to_string(Key,Modifier), - KeyLen = lists:min([length(StrKey), Line]), + KeyLen = lists:min([string:length(StrKey), Line]), ValueLen = Line - KeyLen, Format1 = lists:concat(["~-", KeyLen, Modifier, "s"]), Format2 = lists:concat(["~", ValueLen, Modifier, "s~n"]), io:format(Device, Format1, [StrKey]), Try = term_to_string(Value,Modifier), - Length = length(Try), + Length = string:length(Try), if Length < ValueLen -> io:format(Device, Format2, [Try]); @@ -117,7 +117,7 @@ print_one_line(Device, Line, Key, Value) -> end. term_to_string(Value,Modifier) -> - lists:flatten(io_lib:format(get_format(Value,Modifier), [Value])). + io_lib:format(get_format(Value,Modifier), [Value]). get_format([],_) -> "~p"; diff --git a/lib/sasl/src/rb.erl b/lib/sasl/src/rb.erl index 6595d29a9c..28829132a1 100644 --- a/lib/sasl/src/rb.erl +++ b/lib/sasl/src/rb.erl @@ -586,14 +586,14 @@ find_widths([], _Modifier, DescrWidth, DateWidth, Data) -> {DescrWidth+1, DateWidth+1, lists:reverse(Data)}; find_widths([H|T], Modifier, DescrWidth, DateWidth, Data) -> DescrTerm = element(3,H), - Descr = lists:flatten(io_lib:format("~"++Modifier++"w", [DescrTerm])), - DescrTry = length(Descr), + Descr = io_lib:format("~"++Modifier++"w", [DescrTerm]), + DescrTry = string:length(Descr), NewDescrWidth = if DescrTry > DescrWidth -> DescrTry; true -> DescrWidth end, - DateTry = length(element(4, H)), + DateTry = string:length(element(4, H)), NewDateWitdh = if DateTry > DateWidth -> DateTry; diff --git a/lib/sasl/src/rb_format_supp.erl b/lib/sasl/src/rb_format_supp.erl index 1eda43dae4..b5b7aba151 100644 --- a/lib/sasl/src/rb_format_supp.erl +++ b/lib/sasl/src/rb_format_supp.erl @@ -108,7 +108,7 @@ print(Date, Report, Device) -> format_h(Line, Header, Pid, Date) -> NHeader = lists:flatten(io_lib:format("~s ~w", [Header, Pid])), - DateLen = length(Date), + DateLen = string:length(Date), HeaderLen = Line - DateLen, Format = lists:concat(["~-", HeaderLen, "s~", DateLen, "s"]), io_lib:format(Format, [NHeader, Date]). diff --git a/lib/sasl/src/release_handler.erl b/lib/sasl/src/release_handler.erl index d0a7c7332d..bfa49fc05d 100644 --- a/lib/sasl/src/release_handler.erl +++ b/lib/sasl/src/release_handler.erl @@ -420,7 +420,7 @@ upgrade_app(App, NewDir) -> %% located in the ebin dir of the _current_ version %%----------------------------------------------------------------- downgrade_app(App, OldDir) -> - case string:tokens(filename:basename(OldDir), "-") of + case string:lexemes(filename:basename(OldDir), "-") of [_AppS, OldVsn] -> downgrade_app(App, OldVsn, OldDir); _ -> @@ -1174,8 +1174,8 @@ new_emulator_rm_tmp_release(_,_,_,_,Releases,_) -> %% Rename the tempoarary service (for erts ugprade) to the real ToVsn rename_tmp_service(EVsn,TmpVsn,NewVsn) -> - FromName = hd(string:tokens(atom_to_list(node()),"@")) ++ "_" ++ TmpVsn, - ToName = hd(string:tokens(atom_to_list(node()),"@")) ++ "_" ++ NewVsn, + FromName = hd(string:lexemes(atom_to_list(node()),"@")) ++ "_" ++ TmpVsn, + ToName = hd(string:lexemes(atom_to_list(node()),"@")) ++ "_" ++ NewVsn, case erlsrv:get_service(EVsn,ToName) of {error, _Error} -> ok; @@ -1207,9 +1207,9 @@ rename_service(EVsn,FromName,ToName) -> %%% in which case we try to rename the old service to the new name and try %%% to update heart's view of what service we are really running. do_make_services_permanent(PermanentVsn,Vsn, PermanentEVsn, EVsn) -> - PermName = hd(string:tokens(atom_to_list(node()),"@")) + PermName = hd(string:lexemes(atom_to_list(node()),"@")) ++ "_" ++ PermanentVsn, - Name = hd(string:tokens(atom_to_list(node()),"@")) + Name = hd(string:lexemes(atom_to_list(node()),"@")) ++ "_" ++ Vsn, case erlsrv:get_service(EVsn,Name) of {error, _Error} -> @@ -1296,7 +1296,7 @@ do_make_permanent(#state{releases = Releases, do_back_service(OldVersion, CurrentVersion,OldEVsn,CurrentEVsn) -> - NN = hd(string:tokens(atom_to_list(node()),"@")), + NN = hd(string:lexemes(atom_to_list(node()),"@")), OldName = NN ++ "_" ++ OldVersion, CurrentName = NN ++ "_" ++ CurrentVersion, UpdData = case erlsrv:get_service(CurrentEVsn,CurrentName) of @@ -1385,7 +1385,7 @@ do_remove_service(Vsn) -> %% Very unconditionally remove the service. %% Note that the service could already have been removed when %% making another release permanent. - ServiceName = hd(string:tokens(atom_to_list(node()),"@")) + ServiceName = hd(string:lexemes(atom_to_list(node()),"@")) ++ "_" ++ Vsn, case erlsrv:get_service(ServiceName) of {error, _Error} -> @@ -1670,9 +1670,9 @@ flush() -> prepare_restart_nt(#release{erts_vsn = EVsn, vsn = Vsn}, #release{erts_vsn = PermEVsn, vsn = PermVsn}, DataFileName) -> - CurrentServiceName = hd(string:tokens(atom_to_list(node()),"@")) + CurrentServiceName = hd(string:lexemes(atom_to_list(node()),"@")) ++ "_" ++ PermVsn, - FutureServiceName = hd(string:tokens(atom_to_list(node()),"@")) + FutureServiceName = hd(string:lexemes(atom_to_list(node()),"@")) ++ "_" ++ Vsn, CurrentService = case erlsrv:get_service(PermEVsn,CurrentServiceName) of {error, _} = Error1 -> diff --git a/lib/sasl/src/sasl.app.src b/lib/sasl/src/sasl.app.src index d75543a91b..1e8e58a978 100644 --- a/lib/sasl/src/sasl.app.src +++ b/lib/sasl/src/sasl.app.src @@ -43,6 +43,6 @@ {env, [{sasl_error_logger, tty}, {errlog_type, all}]}, {mod, {sasl, []}}, - {runtime_dependencies, ["tools-2.6.14","stdlib-3.0","kernel-5.0", - "erts-8.1"]}]}. + {runtime_dependencies, ["tools-2.6.14","stdlib-3.4","kernel-5.3", + "erts-9.0"]}]}. diff --git a/lib/sasl/vsn.mk b/lib/sasl/vsn.mk index 2608ca5e00..e980a42688 100644 --- a/lib/sasl/vsn.mk +++ b/lib/sasl/vsn.mk @@ -1 +1 @@ -SASL_VSN = 3.0.4 +SASL_VSN = 3.1 diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml index b902e421ca..e8527ded93 100644 --- a/lib/snmp/doc/src/notes.xml +++ b/lib/snmp/doc/src/notes.xml @@ -34,7 +34,24 @@ </header> - <section><title>SNMP 5.2.6</title> + <section><title>SNMP 5.2.7</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A bug in the SNMP MIB compiler has been fixed. An + AUGMENTS referring to a table defined later in the MIB + did not work.</p> + <p> + Own Id: OTP-13014 Aux Id: ERL-375 </p> + </item> + </list> + </section> + +</section> + +<section><title>SNMP 5.2.6</title> <section><title>Fixed Bugs and Malfunctions</title> <list> diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src index db09ec3dc5..bde637744c 100644 --- a/lib/snmp/src/app/snmp.appup.src +++ b/lib/snmp/src/app/snmp.appup.src @@ -8,8 +8,17 @@ %% {update, snmpa_local_db, soft, soft_purge, soft_purge, []} %% {add_module, snmpm_net_if_mt} [ + {<<"5\\.2\\.6">>, + [{load_module, snmpc, soft_purge, soft_purge, []}, + {load_module, snmpc_lib, soft_purge, soft_purge, []}]}, + {<<"5\\.2\\.5">>, + [{load_module, snmpc, soft_purge, soft_purge, []}, + {load_module, snmpc_lib, soft_purge, soft_purge, []}, + {load_module, snmp_generic, soft_purge, soft_purge, []}]}, {<<"5\\.2\\.4">>, - [{load_module, snmp, soft_purge, soft_purge, []}, + [{load_module, snmpc, soft_purge, soft_purge, []}, + {load_module, snmp_generic, soft_purge, soft_purge, []}, + {load_module, snmp, soft_purge, soft_purge, []}, {load_module, snmpc_lib, soft_purge, soft_purge, []}, {load_module, snmpc_mib_gram, soft_purge, soft_purge, []}]}, {<<"5\\..*">>, [{restart_application, snmp}]}, @@ -21,8 +30,17 @@ %% {remove, {snmpm_net_if_mt, soft_purge, soft_purge}} [ + {<<"5\\.2\\.6">>, + [{load_module, snmpc, soft_purge, soft_purge, []}, + {load_module, snmpc_lib, soft_purge, soft_purge, []}]}, + {<<"5\\.2\\.5">>, + [{load_module, snmpc, soft_purge, soft_purge, []}, + {load_module, snmpc_lib, soft_purge, soft_purge, []}, + {load_module, snmp_generic, soft_purge, soft_purge, []}]}, {<<"5\\.2\\.4">>, - [{load_module, snmp, soft_purge, soft_purge, []}, + [{load_module, snmpc, soft_purge, soft_purge, []}, + {load_module, snmp_generic, soft_purge, soft_purge, []}, + {load_module, snmp, soft_purge, soft_purge, []}, {load_module, snmpc_lib, soft_purge, soft_purge, []}, {load_module, snmpc_mib_gram, soft_purge, soft_purge, []}]}, {<<"5\\..*">>, [{restart_application, snmp}]}, diff --git a/lib/snmp/src/compile/snmpc.erl b/lib/snmp/src/compile/snmpc.erl index 416353508e..4416626a4c 100644 --- a/lib/snmp/src/compile/snmpc.erl +++ b/lib/snmp/src/compile/snmpc.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2016. All Rights Reserved. +%% Copyright Ericsson AB 1997-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -455,7 +455,8 @@ compile_parsed_data(#pdata{mib_name = MibName, Deprecated = get_deprecated(Opts), RelChk = get_relaxed_row_name_assign_check(Opts), Data = #dldata{deprecated = Deprecated, - relaxed_row_name_assign_check = RelChk}, + relaxed_row_name_assign_check = RelChk}, + put(augmentations, false), definitions_loop(Definitions, Data), MibName. @@ -1211,7 +1212,39 @@ definitions_loop([{Obj,Line}|T], Data) -> definitions_loop([], _Data) -> ?vlog("defloop -> done", []), - ok. + case get(augmentations) of + true -> + CData = get(cdata), + put(cdata, CData#cdata{mes = augmentations(CData#cdata.mes)}), + ok; + false -> + ok + end. + +augmentations( + [#me{ + aliasname = AliasName, + assocList = + [{table_info, + #table_info{ + index_types = + {augments, SrcTableEntry, Line}} = TableInfo}|Ref]} = Me + |Mes]) -> + ?vlog("augmentations(~w) ->" + "~n NameOfTable: ~p" + "~n IndexingInfo: ~p" + "~n Sline: ~p", + [?LINE, AliasName, {augments, SrcTableEntry}, Line]), + NewTableInfo = snmpc_lib:fix_table_info_augmentation(TableInfo), + [Me#me{assocList = [{table_info,NewTableInfo}|Ref]} + |augmentations(Mes)]; +augmentations([Me | Mes]) -> + [Me|augmentations(Mes)]; +augmentations([]) -> + ?vlog("augmentations -> done", []), + []. + + safe_elem(N,T) -> case catch(element(N,T)) of diff --git a/lib/snmp/src/compile/snmpc_lib.erl b/lib/snmp/src/compile/snmpc_lib.erl index 33ddd78308..19a6bc8851 100644 --- a/lib/snmp/src/compile/snmpc_lib.erl +++ b/lib/snmp/src/compile/snmpc_lib.erl @@ -26,7 +26,7 @@ -export([test_father/4, make_ASN1type/1, import/1, makeInternalNode2/2, is_consistent/1, resolve_defval/1, make_variable_info/1, check_trap_name/3, make_table_info/5, get_final_mib/2, set_dir/2, - look_at/1, add_cdata/2, + fix_table_info_augmentation/1, look_at/1, add_cdata/2, check_object_group/4, check_notification_group/4, check_notification/3, register_oid/4, @@ -710,25 +710,34 @@ check_trap_name(EnterpriseName, Line, MEs) -> %% functions for tables. %%---------------------------------------------------------------------- +fix_table_info_augmentation( + #table_info{index_types = {augments, SrcTableEntry, Line}} = TableInfo) -> + MEs = (get(cdata))#cdata.mes, + Aug = + case lookup(SrcTableEntry, MEs) of + false -> + print_error( + "Cannot AUGMENT the non-existing table entry ~p", + [SrcTableEntry], Line), + {augments, error}; + {value, ME} -> + {augments, + {SrcTableEntry, translate_type(ME#me.asn1_type)}} + end, + TableInfo#table_info{index_types = Aug}. + + make_table_info(Line, TableName, {augments, SrcTableEntry}, _, ColumnMEs) -> ColMEs = lists:keysort(#me.oid, ColumnMEs), - Nbr_of_Cols = length(ColMEs), - MEs = ColMEs ++ (get(cdata))#cdata.mes, - Aug = case lookup(SrcTableEntry, MEs) of - false -> - print_error("Cannot AUGMENT the non-existing table entry ~p", - [SrcTableEntry], Line), - {augments, error}; - {value, ME} -> - {augments, {SrcTableEntry, translate_type(ME#me.asn1_type)}} - end, - FirstNonIdxCol = augments_first_non_index_column(ColMEs), + Nbr_of_Cols = length(ColMEs), + put(augmentations, true), + FirstNonIdxCol = augments_first_non_index_column(ColMEs), NoAccs = list_not_accessible(FirstNonIdxCol, ColMEs), FirstAcc = first_accessible(TableName, ColMEs), #table_info{nbr_of_cols = Nbr_of_Cols, - first_accessible = FirstAcc, - not_accessible = NoAccs, - index_types = Aug}; + first_accessible = FirstAcc, + not_accessible = NoAccs, + index_types = {augments, SrcTableEntry, Line}}; make_table_info(Line, TableName, {indexes, []}, _, _ColumnMEs) -> print_error("Table ~w lacks indexes.", [TableName],Line), #table_info{}; diff --git a/lib/snmp/test/snmp_compiler_test.erl b/lib/snmp/test/snmp_compiler_test.erl index 9b3c2bfd2c..2b6bba4ee6 100644 --- a/lib/snmp/test/snmp_compiler_test.erl +++ b/lib/snmp/test/snmp_compiler_test.erl @@ -57,8 +57,8 @@ otp_8595/1, otp_10799/1, otp_10808/1, - otp_14145/1 - + otp_14145/1, + otp_13014/1 ]). %%---------------------------------------------------------------------- @@ -137,7 +137,8 @@ all() -> groups() -> [{tickets, [], - [otp_6150, otp_8574, otp_8595, otp_10799, otp_10808, otp_14145]}]. + [otp_6150, otp_8574, otp_8595, otp_10799, otp_10808, otp_14145, + otp_13014]}]. init_per_group(_GroupName, Config) -> Config. @@ -436,7 +437,7 @@ otp_10808(Config) when is_list(Config) -> otp_14145(suite) -> []; otp_14145(Config) when is_list(Config) -> - put(tname, otp10808), + put(tname, otp14145), p("starting with Config: ~p~n", [Config]), Dir = ?config(case_top_dir, Config), @@ -457,6 +458,40 @@ otp_14145(Config) when is_list(Config) -> %%====================================================================== +otp_13014(suite) -> + []; +otp_13014(Config) when is_list(Config) -> + put(tname, otp13014), + p("starting with Config: ~p~n", [Config]), + + Dir = ?config(case_top_dir, Config), + MibDir = ?config(mib_dir, Config), + MibName = "Test-LLDP-MIB", + MibFile = join(MibDir, MibName++".mib"), + ?line {ok, MibBin} = + snmpc:compile(MibFile, [{outdir, Dir}, + {verbosity, log}, + {group_check, false}, + module_compliance]), + p("Mib: ~n~p~n", [MibBin]), + #mib{mes = MEs} = read_mib(MibBin), + Oid = [1,0,8802,1,1,2,1,1,7], + #me{ + entrytype = table, + aliasname = lldpConfigManAddrTable, + assocList = [{table_info,TableInfo}]} = + lists:keyfind(Oid, #me.oid, MEs), + #table_info{ + nbr_of_cols = 1, + first_accessible = 1, + not_accessible = [], + index_types = {augments,{lldpLocManAddrEntry,undefined}}} = + TableInfo, + ok. + + +%%====================================================================== + augments_extra_info(suite) -> []; augments_extra_info(Config) when is_list(Config) -> diff --git a/lib/snmp/test/snmp_test_data/Test-LLDP-MIB.mib b/lib/snmp/test/snmp_test_data/Test-LLDP-MIB.mib new file mode 100644 index 0000000000..40a9fc79e1 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/Test-LLDP-MIB.mib @@ -0,0 +1,251 @@ +Test-LLDP-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, Integer32, Counter32, NOTIFICATION-TYPE + FROM SNMPv2-SMI + TEXTUAL-CONVENTION, TimeStamp, TruthValue + FROM SNMPv2-TC + SnmpAdminString + FROM SNMP-FRAMEWORK-MIB + MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP + FROM SNMPv2-CONF; + +t-lldpMIB MODULE-IDENTITY + LAST-UPDATED "200505060000Z" -- May 06, 2005 + ORGANIZATION "IEEE 802.1 Working Group" + CONTACT-INFO + " Contact: The Erlang/OTP team at Ericsson AB, Sweden + + WG-URL: http://grouper.ieee.org/groups/802/1/index.html + WG-EMail: [email protected] + + Contact: Paul Congdon + Postal: Hewlett-Packard Company + 8000 Foothills Blvd. + Roseville, CA 95747 + USA + Tel: +1-916-785-5753 + E-mail: [email protected]" + DESCRIPTION + "This is the ripped out bits and pieces of LLDP-MIB + that triggered a compilation problem for Erlang/OTP's + MIB compiler due to an AUGMENTS in lldpConfigManAddrEntry + refering to a not yet defined OBJECT-TYPE lldpLocManAddrEntry. + Rip and rewrite done 2017. + + Management Information Base module for LLDP configuration, + statistics, local system data and remote systems data + components. + + Copyright (C) IEEE (2005). This version of this MIB module + is published as subclause 12.1 of IEEE Std 802.1AB-2005; + see the standard itself for full legal notices." + REVISION "200505060000Z" -- May 06, 2005 + DESCRIPTION + "Published as part of IEEE Std 802.1AB-2005 initial version." + ::= { iso std(0) iso8802(8802) ieee802dot1(1) ieee802dot1mibs(1) 2 } + +--lldpNotifications OBJECT IDENTIFIER ::= { lldpMIB 0 } +lldpObjects OBJECT IDENTIFIER ::= { t-lldpMIB 1 } +lldpConformance OBJECT IDENTIFIER ::= { t-lldpMIB 2 } + +-- +-- LLDP MIB Objects +-- + +lldpConfiguration OBJECT IDENTIFIER ::= { lldpObjects 1 } +--lldpStatistics OBJECT IDENTIFIER ::= { lldpObjects 2 } +lldpLocalSystemData OBJECT IDENTIFIER ::= { lldpObjects 3 } +--lldpRemoteSystemsData OBJECT IDENTIFIER ::= { lldpObjects 4 } +--lldpExtensions OBJECT IDENTIFIER ::= { lldpObjects 5 } + + + +LldpPortList ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Each octet within this value specifies a set of eight ports, + with the first octet specifying ports 1 through 8, the second + octet specifying ports 9 through 16, etc. Within each octet, + the most significant bit represents the lowest numbered port, + and the least significant bit represents the highest numbered + port. Thus, each port of the system is represented by a + single bit within the value of this object. If that bit has + a value of '1' then that port is included in the set of ports; + the port is not included if its bit has a value of '0'." + REFERENCE + "IETF RFC 2674 section 5" + SYNTAX OCTET STRING(SIZE(0..512)) + + + +-- +-- lldpManAddrConfigTxPortsTable : selection of management addresses +-- to be transmitted on a specified set +-- of ports. +-- + +lldpConfigManAddrTable OBJECT-TYPE + SYNTAX SEQUENCE OF LldpConfigManAddrEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The table that controls selection of LLDP management address + TLV instances to be transmitted on individual ports." + ::= { lldpConfiguration 7 } + +lldpConfigManAddrEntry OBJECT-TYPE + SYNTAX LldpConfigManAddrEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "LLDP configuration information that specifies the set + of ports (represented as a PortList) on which the local + system management address instance will be transmitted. + + This configuration object augments the lldpLocManAddrEntry, + therefore it is only present along with the management + address instance contained in the associated + lldpLocManAddrEntry entry. + + Each active lldpConfigManAddrEntry must be restored from + non-volatile and re-created (along with the corresponding + lldpLocManAddrEntry) after a re-initialization of the + management system." + AUGMENTS { lldpLocManAddrEntry } + ::= { lldpConfigManAddrTable 1 } + +LldpConfigManAddrEntry ::= SEQUENCE { + lldpConfigManAddrPortsTxEnable LldpPortList +} + +lldpConfigManAddrPortsTxEnable OBJECT-TYPE + SYNTAX LldpPortList + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "A set of ports that are identified by a PortList, in which + each port is represented as a bit. The corresponding local + system management address instance will be transmitted on the + member ports of the lldpManAddrPortsTxEnable. + + The default value for lldpConfigManAddrPortsTxEnable object + is empty binary string, which means no ports are specified + for advertising indicated management address instance." + REFERENCE + "IEEE 802.1AB-2005 10.2.1.1" + DEFVAL { ''H } -- empty binary string + ::= { lldpConfigManAddrEntry 1 } + + +-- +-- lldpLocManAddrTable : Management addresses of the local system +-- + +lldpLocManAddrTable OBJECT-TYPE + SYNTAX SEQUENCE OF LldpLocManAddrEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "This table contains management address information on the + local system known to this agent." + ::= { lldpLocalSystemData 8 } + +lldpLocManAddrEntry OBJECT-TYPE + SYNTAX LldpLocManAddrEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Management address information about a particular chassis + component. There may be multiple management addresses + configured on the system identified by a particular + lldpLocChassisId. Each management address should have + distinct 'management address type' (lldpLocManAddrSubtype) and + 'management address' (lldpLocManAddr.) + + Entries may be created and deleted in this table by the + agent." + INDEX { lldpLocManAddrIfId, + lldpLocManAddrLen } + ::= { lldpLocManAddrTable 1 } + +LldpLocManAddrEntry ::= SEQUENCE { + lldpLocManAddrIfId Integer32, + lldpLocManAddrLen Integer32, + lldpLocManAddrOID OBJECT IDENTIFIER +} + +lldpLocManAddrIfId OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The integer value used to identify the interface number + regarding the management address component associated with + the local system." + REFERENCE + "IEEE 802.1AB-2005 9.5.9.6" + ::= { lldpLocManAddrEntry 1 } + +lldpLocManAddrLen OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total length of the management address subtype and the + management address fields in LLDPDUs transmitted by the + local LLDP agent. + + The management address length field is needed so that the + receiving systems that do not implement SNMP will not be + required to implement an iana family numbers/address length + equivalency table in order to decode the management adress." + REFERENCE + "IEEE 802.1AB-2005 9.5.9.2" + ::= { lldpLocManAddrEntry 2 } + +lldpLocManAddrOID OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The OID value used to identify the type of hardware component + or protocol entity associated with the management address + advertised by the local system agent." + REFERENCE + "IEEE 802.1AB-2005 9.5.9.8" + ::= { lldpLocManAddrEntry 3 } + + +lldpGroups OBJECT IDENTIFIER ::= { lldpConformance 1 } + +lldpLocSysGroup OBJECT-GROUP + OBJECTS { + lldpLocManAddrIfId, + lldpLocManAddrLen, + lldpLocManAddrOID + } + STATUS current + DESCRIPTION + "The collection of objects which are used to represent LLDP + Local System Information. + + This group is mandatory for agents which implement the LLDP + and have the capability of transmitting LLDP frames." + ::= { lldpGroups 6 } + +lldpConfigTxGroup OBJECT-GROUP + OBJECTS { + lldpConfigManAddrPortsTxEnable + } + STATUS current + DESCRIPTION + "The collection of objects which are used to configure the + LLDP implementation behavior. + + This group is mandatory for agents which implement the LLDP + and have the capability of transmitting LLDP frames." + ::= { lldpGroups 3 } + + +END diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk index d41b1999cc..207f0084d8 100644 --- a/lib/snmp/vsn.mk +++ b/lib/snmp/vsn.mk @@ -19,6 +19,6 @@ # %CopyrightEnd% APPLICATION = snmp -SNMP_VSN = 5.2.6 +SNMP_VSN = 5.2.7 PRE_VSN = APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)" diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml index 5826d14a4a..4ba75b761f 100644 --- a/lib/ssh/doc/src/notes.xml +++ b/lib/ssh/doc/src/notes.xml @@ -30,6 +30,48 @@ <file>notes.xml</file> </header> +<section><title>Ssh 4.6</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Enables the <c>ssh_io module</c> to also accept binary + values when reading standard_io instead of getting stuck + in the receive clause.</p> + <p> + Own Id: OTP-14506 Aux Id: PR1503 </p> + </item> + <item> + <p> + Previously, the file owner access permission in response + to ssh_sftp:read_file_info/2 function was always + <c>read_write</c>. With this fix, the actual value of + file owner access permission is added to the returning + record. That value is calculated from file mode value.</p> + <p> + Own Id: OTP-14550 Aux Id: PR1533 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + A new option <c>modify_algorithms</c> is implemented. It + enables specifying changes on the default algorithms + list. See the reference manual and the SSH User's Guide + chapter "Configuring algorithms in SSH".</p> + <p> + Own Id: OTP-14568</p> + </item> + </list> + </section> + +</section> + <section><title>Ssh 4.5.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk index 006228f8e7..c201e70d82 100644 --- a/lib/ssh/vsn.mk +++ b/lib/ssh/vsn.mk @@ -1,5 +1,5 @@ #-*-makefile-*- ; force emacs to enter makefile-mode -SSH_VSN = 4.5.1 +SSH_VSN = 4.6 APP_VSN = "ssh-$(SSH_VSN)" diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index 5a39cac9bc..4c6a204e63 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -28,6 +28,40 @@ <p>This document describes the changes made to the SSL application.</p> +<section><title>SSL 8.2.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Max session table works correctly again</p> + <p> + Own Id: OTP-14556</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Customize alert handling for DTLS over UDP to mitigate + DoS attacks</p> + <p> + Own Id: OTP-14078</p> + </item> + <item> + <p> + Improved error propagation and reports</p> + <p> + Own Id: OTP-14236</p> + </item> + </list> + </section> + +</section> + <section><title>SSL 8.2</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/ssl/src/Makefile b/lib/ssl/src/Makefile index 2e7df9792e..8eba5cf347 100644 --- a/lib/ssl/src/Makefile +++ b/lib/ssl/src/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1999-2016. All Rights Reserved. +# Copyright Ericsson AB 1999-2017. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -87,8 +87,7 @@ MODULES= \ ssl_v2 \ ssl_v3 \ tls_v1 \ - dtls_v1 \ - ssl_tls_dist_proxy + dtls_v1 INTERNAL_HRL_FILES = \ ssl_alert.hrl ssl_cipher.hrl \ diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl index ff3e69bae5..ad560c0756 100644 --- a/lib/ssl/src/dtls_connection.erl +++ b/lib/ssl/src/dtls_connection.erl @@ -540,7 +540,7 @@ handle_info(new_cookie_secret, StateName, CookieInfo#{current_cookie_secret => dtls_v1:cookie_secret(), previous_cookie_secret => Secret}}}; handle_info(Msg, StateName, State) -> - ssl_connection:handle_info(Msg, StateName, State). + ssl_connection:StateName(info, Msg, State, ?MODULE). handle_call(Event, From, StateName, State) -> diff --git a/lib/ssl/src/inet6_tls_dist.erl b/lib/ssl/src/inet6_tls_dist.erl index ffd7296f93..96ce4d493a 100644 --- a/lib/ssl/src/inet6_tls_dist.erl +++ b/lib/ssl/src/inet6_tls_dist.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2015. All Rights Reserved. +%% Copyright Ericsson AB 2015-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -21,7 +21,8 @@ %% -module(inet6_tls_dist). --export([childspecs/0, listen/1, accept/1, accept_connection/5, +-export([childspecs/0]). +-export([listen/1, accept/1, accept_connection/5, setup/5, close/1, select/1]). childspecs() -> @@ -43,4 +44,4 @@ setup(Node, Type, MyNode, LongOrShortNames,SetupTime) -> inet_tls_dist:gen_setup(inet6_tcp, Node, Type, MyNode, LongOrShortNames,SetupTime). close(Socket) -> - inet_tls_dist:close(Socket). + inet_tls_dist:gen_close(inet6_tcp, Socket). diff --git a/lib/ssl/src/inet_tls_dist.erl b/lib/ssl/src/inet_tls_dist.erl index 0da4b3587f..d644cbe66a 100644 --- a/lib/ssl/src/inet_tls_dist.erl +++ b/lib/ssl/src/inet_tls_dist.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011-2016. All Rights Reserved. +%% Copyright Ericsson AB 2011-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -21,17 +21,26 @@ %% -module(inet_tls_dist). --export([childspecs/0, listen/1, accept/1, accept_connection/5, +-export([childspecs/0]). +-export([listen/1, accept/1, accept_connection/5, setup/5, close/1, select/1, is_node_name/1]). %% Generalized dist API -export([gen_listen/2, gen_accept/2, gen_accept_connection/6, - gen_setup/6, gen_select/2]). + gen_setup/6, gen_close/2, gen_select/2]). + +-export([split_node/1, nodelay/0]). + +-export([dbg/0]). % Debug -include_lib("kernel/include/net_address.hrl"). -include_lib("kernel/include/dist.hrl"). -include_lib("kernel/include/dist_util.hrl"). +-include("ssl_api.hrl"). + +%% ------------------------------------------------------------------------- + childspecs() -> {ok, [{ssl_dist_sup,{ssl_dist_sup, start_link, []}, permanent, infinity, supervisor, [ssl_dist_sup]}]}. @@ -40,111 +49,366 @@ select(Node) -> gen_select(inet_tcp, Node). gen_select(Driver, Node) -> - case split_node(atom_to_list(Node), $@, []) of - [_, Host] -> - case inet:getaddr(Host, Driver:family()) of + case split_node(Node) of + false -> + false; + Host -> + case Driver:getaddr(Host) of {ok, _} -> true; _ -> false - end; - _ -> - false + end end. -is_node_name(Node) when is_atom(Node) -> - select(Node); -is_node_name(_) -> - false. +%% ------------------------------------------------------------------------- + +is_node_name(Node) -> + case split_node(Node) of + false -> + false; + _Host -> + true + end. + +%% ------------------------------------------------------------------------- + +hs_data_common(#sslsocket{pid = DistCtrl} = SslSocket) -> + #hs_data{ + f_send = + fun (Ctrl, Packet) when Ctrl == DistCtrl -> + f_send(SslSocket, Packet) + end, + f_recv = + fun (Ctrl, Length, Timeout) when Ctrl == DistCtrl -> + f_recv(SslSocket, Length, Timeout) + end, + f_setopts_pre_nodeup = + fun (Ctrl) when Ctrl == DistCtrl -> + f_setopts_pre_nodeup(SslSocket) + end, + f_setopts_post_nodeup = + fun (Ctrl) when Ctrl == DistCtrl -> +%%% sys:trace(Ctrl, true), + f_setopts_post_nodeup(SslSocket) + end, + f_getll = + fun (Ctrl) when Ctrl == DistCtrl -> + f_getll(DistCtrl) + end, + f_address = + fun (Ctrl, Node) when Ctrl == DistCtrl -> + f_address(SslSocket, Node) + end, + mf_tick = + fun (Ctrl) when Ctrl == DistCtrl -> + mf_tick(DistCtrl) + end, + mf_getstat = + fun (Ctrl) when Ctrl == DistCtrl -> + mf_getstat(SslSocket) + end, + mf_setopts = + fun (Ctrl, Opts) when Ctrl == DistCtrl -> + mf_setopts(SslSocket, Opts) + end, + mf_getopts = + fun (Ctrl, Opts) when Ctrl == DistCtrl -> + mf_getopts(SslSocket, Opts) + end, + f_handshake_complete = + fun (Ctrl, Node, DHandle) when Ctrl == DistCtrl -> + f_handshake_complete(DistCtrl, Node, DHandle) + end}. + +f_send(SslSocket, Packet) -> + ssl:send(SslSocket, Packet). + +f_recv(SslSocket, Length, Timeout) -> + case ssl:recv(SslSocket, Length, Timeout) of + {ok, Bin} when is_binary(Bin) -> + {ok, binary_to_list(Bin)}; + Other -> + Other + end. + +f_setopts_pre_nodeup(_SslSocket) -> + ok. + +f_setopts_post_nodeup(_SslSocket) -> + ok. + +f_getll(DistCtrl) -> + {ok, DistCtrl}. + +f_address(SslSocket, Node) -> + case ssl:peername(SslSocket) of + {ok, Address} -> + case split_node(Node) of + false -> + {error, no_node}; + Host -> + #net_address{ + address=Address, host=Host, + protocol=tls, family=inet} + end + end. + +mf_tick(DistCtrl) -> + DistCtrl ! tick, + ok. + +mf_getstat(SslSocket) -> + case ssl:getstat( + SslSocket, [recv_cnt, send_cnt, send_pend]) of + {ok, Stat} -> + split_stat(Stat,0,0,0); + Error -> + Error + end. + +mf_setopts(SslSocket, Opts) -> + case setopts_filter(Opts) of + [] -> + ssl:setopts(SslSocket, Opts); + Opts1 -> + {error, {badopts,Opts1}} + end. + +mf_getopts(SslSocket, Opts) -> + ssl:getopts(SslSocket, Opts). + +f_handshake_complete(DistCtrl, Node, DHandle) -> + ssl_connection:handshake_complete(DistCtrl, Node, DHandle). + + +setopts_filter(Opts) -> + [Opt || {K,_} = Opt <- Opts, + K =:= active orelse K =:= deliver orelse K =:= packet]. + +split_stat([{recv_cnt, R}|Stat], _, W, P) -> + split_stat(Stat, R, W, P); +split_stat([{send_cnt, W}|Stat], R, _, P) -> + split_stat(Stat, R, W, P); +split_stat([{send_pend, P}|Stat], R, W, _) -> + split_stat(Stat, R, W, P); +split_stat([], R, W, P) -> + {ok, R, W, P}. + +%% ------------------------------------------------------------------------- listen(Name) -> gen_listen(inet_tcp, Name). gen_listen(Driver, Name) -> - ssl_tls_dist_proxy:listen(Driver, Name). + case inet_tcp_dist:gen_listen(Driver, Name) of + {ok, {Socket, Address, Creation}} -> + inet:setopts(Socket, [{packet, 4}]), + {ok, {Socket, Address#net_address{protocol=tls}, Creation}}; + Other -> + Other + end. + +%% ------------------------------------------------------------------------- accept(Listen) -> gen_accept(inet_tcp, Listen). gen_accept(Driver, Listen) -> - ssl_tls_dist_proxy:accept(Driver, Listen). + Kernel = self(), + monitor_pid( + spawn_opt( + fun () -> + accept_loop(Driver, Listen, Kernel) + end, + [link, {priority, max}])). -accept_connection(AcceptPid, Socket, MyNode, Allowed, SetupTime) -> - gen_accept_connection(inet_tcp, AcceptPid, Socket, MyNode, Allowed, SetupTime). +accept_loop(Driver, Listen, Kernel) -> + case Driver:accept(Listen) of + {ok, Socket} -> + Opts = get_ssl_options(server), + wait_for_code_server(), + case ssl:ssl_accept( + Socket, [{active, false}, {packet, 4}] ++ Opts, + net_kernel:connecttime()) of + {ok, #sslsocket{pid = DistCtrl} = SslSocket} -> + monitor_pid(DistCtrl), + trace( + Kernel ! + {accept, self(), DistCtrl, + Driver:family(), tls}), + receive + {Kernel, controller, Pid} -> + ok = ssl:controlling_process(SslSocket, Pid), + trace( + Pid ! {self(), controller}); + {Kernel, unsupported_protocol} -> + exit(trace(unsupported_protocol)) + end, + accept_loop(Driver, Listen, Kernel); + {error, {options, _}} = Error -> + %% Bad options: that's probably our fault. + %% Let's log that. + error_logger:error_msg( + "Cannot accept TLS distribution connection: ~s~n", + [ssl:format_error(Error)]), + _ = trace(Error), + gen_tcp:close(Socket); + Other -> + _ = trace(Other), + gen_tcp:close(Socket) + end; + Error -> + exit(trace(Error)) + end, + accept_loop(Driver, Listen, Kernel). -gen_accept_connection(Driver, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> +wait_for_code_server() -> + %% This is an ugly hack. Upgrading a socket to TLS requires the + %% crypto module to be loaded. Loading the crypto module triggers + %% its on_load function, which calls code:priv_dir/1 to find the + %% directory where its NIF library is. However, distribution is + %% started earlier than the code server, so the code server is not + %% necessarily started yet, and code:priv_dir/1 might fail because + %% of that, if we receive an incoming connection on the + %% distribution port early enough. + %% + %% If the on_load function of a module fails, the module is + %% unloaded, and the function call that triggered loading it fails + %% with 'undef', which is rather confusing. + %% + %% Thus, the accept process will terminate, and be + %% restarted by ssl_dist_sup. However, it won't have any memory + %% of being asked by net_kernel to listen for incoming + %% connections. Hence, the node will believe that it's open for + %% distribution, but it actually isn't. + %% + %% So let's avoid that by waiting for the code server to start. + case whereis(code_server) of + undefined -> + timer:sleep(10), + wait_for_code_server(); + Pid when is_pid(Pid) -> + ok + end. + +%% ------------------------------------------------------------------------- + +accept_connection(AcceptPid, DistCtrl, MyNode, Allowed, SetupTime) -> + gen_accept_connection( + inet_tcp, AcceptPid, DistCtrl, MyNode, Allowed, SetupTime). + +gen_accept_connection( + Driver, AcceptPid, DistCtrl, MyNode, Allowed, SetupTime) -> Kernel = self(), - spawn_link(fun() -> do_accept(Driver, Kernel, AcceptPid, Socket, - MyNode, Allowed, SetupTime) end). + monitor_pid( + spawn_opt( + fun() -> + do_accept( + Driver, Kernel, AcceptPid, DistCtrl, + MyNode, Allowed, SetupTime) + end, + [link, {priority, max}])). + +do_accept(Driver, Kernel, AcceptPid, DistCtrl, MyNode, Allowed, SetupTime) -> + SslSocket = ssl_connection:get_sslsocket(DistCtrl), + receive + {AcceptPid, controller} -> + Timer = dist_util:start_timer(SetupTime), + case check_ip(Driver, SslSocket) of + true -> + HSData0 = hs_data_common(SslSocket), + HSData = + HSData0#hs_data{ + kernel_pid = Kernel, + this_node = MyNode, + socket = DistCtrl, + timer = Timer, + this_flags = 0, + allowed = Allowed}, + dist_util:handshake_other_started(trace(HSData)); + {false,IP} -> + error_logger:error_msg( + "** Connection attempt from " + "disallowed IP ~w ** ~n", [IP]), + ?shutdown(trace(no_node)) + end + end. + + -setup(Node, Type, MyNode, LongOrShortNames,SetupTime) -> - gen_setup(inet_tcp, Node, Type, MyNode, LongOrShortNames,SetupTime). +setup(Node, Type, MyNode, LongOrShortNames, SetupTime) -> + gen_setup(inet_tcp, Node, Type, MyNode, LongOrShortNames, SetupTime). -gen_setup(Driver, Node, Type, MyNode, LongOrShortNames,SetupTime) -> +gen_setup(Driver, Node, Type, MyNode, LongOrShortNames, SetupTime) -> Kernel = self(), - spawn_opt(fun() -> do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) end, [link, {priority, max}]). - + monitor_pid( + spawn_opt( + fun() -> + do_setup( + Driver, Kernel, Node, Type, + MyNode, LongOrShortNames, SetupTime) + end, + [link, {priority, max}])). + do_setup(Driver, Kernel, Node, Type, MyNode, LongOrShortNames, SetupTime) -> [Name, Address] = splitnode(Driver, Node, LongOrShortNames), - case inet:getaddr(Address, Driver:family()) of + case Driver:getaddr(Address) of {ok, Ip} -> - Timer = dist_util:start_timer(SetupTime), + Timer = trace(dist_util:start_timer(SetupTime)), ErlEpmd = net_kernel:epmd_module(), case ErlEpmd:port_please(Name, Ip) of {port, TcpPort, Version} -> - ?trace("port_please(~p) -> version ~p~n", - [Node,Version]), + Opts = trace(connect_options(get_ssl_options(client))), dist_util:reset_timer(Timer), - case ssl_tls_dist_proxy:connect(Driver, Ip, TcpPort) of - {ok, Socket} -> - HSData = connect_hs_data(Kernel, Node, MyNode, Socket, - Timer, Version, Ip, TcpPort, Address, - Type), - dist_util:handshake_we_started(HSData); + case ssl:connect( + Ip, TcpPort, + [binary, {active, false}, {packet, 4}, + Driver:family(), nodelay()] ++ Opts, + net_kernel:connecttime()) of + {ok, #sslsocket{pid = DistCtrl} = SslSocket} -> + monitor_pid(DistCtrl), + ok = ssl:controlling_process(SslSocket, self()), + HSData0 = hs_data_common(SslSocket), + HSData = + HSData0#hs_data{ + kernel_pid = Kernel, + other_node = Node, + this_node = MyNode, + socket = DistCtrl, + timer = Timer, + this_flags = 0, + other_version = Version, + request_type = Type}, + dist_util:handshake_we_started(trace(HSData)); Other -> %% Other Node may have closed since %% port_please ! - ?trace("other node (~p) " - "closed since port_please.~n", - [Node]), - ?shutdown2(Node, {shutdown, {connect_failed, Other}}) + ?shutdown2( + Node, + trace({shutdown, {connect_failed, Other}})) end; Other -> - ?trace("port_please (~p) " - "failed.~n", [Node]), - ?shutdown2(Node, {shutdown, {port_please_failed, Other}}) + ?shutdown2( + Node, + trace({shutdown, {port_please_failed, Other}})) end; Other -> - ?trace("inet_getaddr(~p) " - "failed (~p).~n", [Node,Other]), - ?shutdown2(Node, {shutdown, {inet_getaddr_failed, Other}}) + ?shutdown2(Node, trace({shutdown, {getaddr_failed, Other}})) end. close(Socket) -> - gen_tcp:close(Socket), - ok. + gen_close(inet, Socket). + +gen_close(Driver, Socket) -> + trace(Driver:close(Socket)). -do_accept(Driver, Kernel, AcceptPid, Socket, MyNode, Allowed, SetupTime) -> - process_flag(priority, max), - receive - {AcceptPid, controller} -> - Timer = dist_util:start_timer(SetupTime), - case check_ip(Driver, Socket) of - true -> - HSData = accept_hs_data(Kernel, MyNode, Socket, Timer, Allowed), - dist_util:handshake_other_started(HSData); - {false,IP} -> - error_logger:error_msg("** Connection attempt from " - "disallowed IP ~w ** ~n", [IP]), - ?shutdown(no_node) - end - end. %% ------------------------------------------------------------ %% Do only accept new connection attempts from nodes at our %% own LAN, if the check_ip environment parameter is true. %% ------------------------------------------------------------ -check_ip(Driver, Socket) -> +check_ip(Driver, SslSocket) -> case application:get_env(check_ip) of {ok, true} -> - case get_ifs(Socket) of + case get_ifs(SslSocket) of {ok, IFs, IP} -> check_ip(Driver, IFs, IP); _ -> @@ -154,9 +418,18 @@ check_ip(Driver, Socket) -> true end. -get_ifs(Socket) -> +check_ip(Driver, [{OwnIP, _, Netmask}|IFs], PeerIP) -> + case {Driver:mask(Netmask, PeerIP), Driver:mask(Netmask, OwnIP)} of + {M, M} -> true; + _ -> check_ip(IFs, PeerIP) + end; +check_ip(_Driver, [], PeerIP) -> + {false, PeerIP}. + +get_ifs(#sslsocket{fd = {gen_tcp, Socket, _}}) -> case inet:peername(Socket) of {ok, {IP, _}} -> + %% XXX this is seriously broken for IPv6 case inet:getif(Socket) of {ok, IFs} -> {ok, IFs, IP}; Error -> Error @@ -165,14 +438,6 @@ get_ifs(Socket) -> Error end. -check_ip(Driver, [{OwnIP, _, Netmask}|IFs], PeerIP) -> - case {Driver:mask(Netmask, PeerIP), Driver:mask(Netmask, OwnIP)} of - {M, M} -> true; - _ -> check_ip(IFs, PeerIP) - end; -check_ip(_Driver, [], PeerIP) -> - {false, PeerIP}. - %% If Node is illegal terminate the connection setup!! splitnode(Driver, Node, LongOrShortNames) -> @@ -181,11 +446,13 @@ splitnode(Driver, Node, LongOrShortNames) -> Host = lists:append(Tail), check_node(Driver, Name, Node, Host, LongOrShortNames); [_] -> - error_logger:error_msg("** Nodename ~p illegal, no '@' character **~n", - [Node]), + error_logger:error_msg( + "** Nodename ~p illegal, no '@' character **~n", + [Node]), ?shutdown(Node); _ -> - error_logger:error_msg("** Nodename ~p illegal **~n", [Node]), + error_logger:error_msg( + "** Nodename ~p illegal **~n", [Node]), ?shutdown(Node) end. @@ -196,23 +463,34 @@ check_node(Driver, Name, Node, Host, LongOrShortNames) -> {ok, _} -> [Name, Host]; _ -> - error_logger:error_msg("** System running to use " - "fully qualified " - "hostnames **~n" - "** Hostname ~s is illegal **~n", - [Host]), + error_logger:error_msg( + "** System running to use " + "fully qualified hostnames **~n" + "** Hostname ~s is illegal **~n", + [Host]), ?shutdown(Node) end; [_, _ | _] when LongOrShortNames == shortnames -> - error_logger:error_msg("** System NOT running to use fully qualified " - "hostnames **~n" - "** Hostname ~s is illegal **~n", - [Host]), + error_logger:error_msg( + "** System NOT running to use " + "fully qualified hostnames **~n" + "** Hostname ~s is illegal **~n", + [Host]), ?shutdown(Node); _ -> [Name, Host] end. +split_node(Node) when is_atom(Node) -> + case split_node(atom_to_list(Node), $@, []) of + [_, Host] -> + Host; + _ -> + false + end; +split_node(_) -> + false. +%% split_node([Chr|T], Chr, Ack) -> [lists:reverse(Ack)|split_node(T, Chr, [])]; split_node([H|T], Chr, Ack) -> @@ -220,70 +498,154 @@ split_node([H|T], Chr, Ack) -> split_node([], _, Ack) -> [lists:reverse(Ack)]. -connect_hs_data(Kernel, Node, MyNode, Socket, Timer, Version, Ip, TcpPort, Address, Type) -> - common_hs_data(Kernel, MyNode, Socket, Timer, - #hs_data{other_node = Node, - other_version = Version, - f_address = - fun(_,_) -> - #net_address{address = {Ip,TcpPort}, - host = Address, - protocol = proxy, - family = inet} - end, - request_type = Type - }). - -accept_hs_data(Kernel, MyNode, Socket, Timer, Allowed) -> - common_hs_data(Kernel, MyNode, Socket, Timer, #hs_data{ - allowed = Allowed, - f_address = fun get_remote_id/2 - }). - -common_hs_data(Kernel, MyNode, Socket, Timer, HsData) -> - HsData#hs_data{ - kernel_pid = Kernel, - this_node = MyNode, - socket = Socket, - timer = Timer, - this_flags = 0, - f_send = - fun(S,D) -> - gen_tcp:send(S,D) - end, - f_recv = - fun(S,N,T) -> - gen_tcp:recv(S,N,T) - end, - f_setopts_pre_nodeup = - fun(S) -> - inet:setopts(S, [{active, false}, {packet, 4}]) - end, - f_setopts_post_nodeup = - fun(S) -> - inet:setopts(S, [{deliver, port},{active, true}]) - end, - f_getll = - fun(S) -> - inet:getll(S) - end, - mf_tick = - fun(S) -> - gen_tcp:send(S, <<>>) - end, - mf_getstat = - fun(S) -> - {ok, Stats} = inet:getstat(S, [recv_cnt, send_cnt, send_pend]), - R = proplists:get_value(recv_cnt, Stats, 0), - W = proplists:get_value(send_cnt, Stats, 0), - P = proplists:get_value(send_pend, Stats, 0), - {ok, R,W,P} - end}. - -get_remote_id(Socket, _Node) -> - case ssl_tls_dist_proxy:get_tcp_address(Socket) of - {ok, Address} -> - Address; - {error, _Reason} -> - ?shutdown(no_node) +%% ------------------------------------------------------------------------- + +connect_options(Opts) -> + case application:get_env(kernel, inet_dist_connect_options) of + {ok,ConnectOpts} -> + lists:ukeysort(1, ConnectOpts ++ Opts); + _ -> + Opts end. + +%% we may not always want the nodelay behaviour +%% for performance reasons +nodelay() -> + case application:get_env(kernel, dist_nodelay) of + undefined -> + {nodelay, true}; + {ok, true} -> + {nodelay, true}; + {ok, false} -> + {nodelay, false}; + _ -> + {nodelay, true} + end. + + +get_ssl_options(Type) -> + case init:get_argument(ssl_dist_opt) of + {ok, Args} -> + [{erl_dist, true} | ssl_options(Type, lists:append(Args))]; + _ -> + [{erl_dist, true}] + end. + +ssl_options(_,[]) -> + []; +ssl_options(server, ["client_" ++ _, _Value |T]) -> + ssl_options(server,T); +ssl_options(client, ["server_" ++ _, _Value|T]) -> + ssl_options(client,T); +ssl_options(server, ["server_certfile", Value|T]) -> + [{certfile, Value} | ssl_options(server,T)]; +ssl_options(client, ["client_certfile", Value | T]) -> + [{certfile, Value} | ssl_options(client,T)]; +ssl_options(server, ["server_cacertfile", Value|T]) -> + [{cacertfile, Value} | ssl_options(server,T)]; +ssl_options(client, ["client_cacertfile", Value|T]) -> + [{cacertfile, Value} | ssl_options(client,T)]; +ssl_options(server, ["server_keyfile", Value|T]) -> + [{keyfile, Value} | ssl_options(server,T)]; +ssl_options(client, ["client_keyfile", Value|T]) -> + [{keyfile, Value} | ssl_options(client,T)]; +ssl_options(server, ["server_password", Value|T]) -> + [{password, Value} | ssl_options(server,T)]; +ssl_options(client, ["client_password", Value|T]) -> + [{password, Value} | ssl_options(client,T)]; +ssl_options(server, ["server_verify", Value|T]) -> + [{verify, atomize(Value)} | ssl_options(server,T)]; +ssl_options(client, ["client_verify", Value|T]) -> + [{verify, atomize(Value)} | ssl_options(client,T)]; +ssl_options(server, ["server_verify_fun", Value|T]) -> + [{verify_fun, verify_fun(Value)} | ssl_options(server,T)]; +ssl_options(client, ["client_verify_fun", Value|T]) -> + [{verify_fun, verify_fun(Value)} | ssl_options(client,T)]; +ssl_options(server, ["server_crl_check", Value|T]) -> + [{crl_check, atomize(Value)} | ssl_options(server,T)]; +ssl_options(client, ["client_crl_check", Value|T]) -> + [{crl_check, atomize(Value)} | ssl_options(client,T)]; +ssl_options(server, ["server_crl_cache", Value|T]) -> + [{crl_cache, termify(Value)} | ssl_options(server,T)]; +ssl_options(client, ["client_crl_cache", Value|T]) -> + [{crl_cache, termify(Value)} | ssl_options(client,T)]; +ssl_options(server, ["server_reuse_sessions", Value|T]) -> + [{reuse_sessions, atomize(Value)} | ssl_options(server,T)]; +ssl_options(client, ["client_reuse_sessions", Value|T]) -> + [{reuse_sessions, atomize(Value)} | ssl_options(client,T)]; +ssl_options(server, ["server_secure_renegotiate", Value|T]) -> + [{secure_renegotiate, atomize(Value)} | ssl_options(server,T)]; +ssl_options(client, ["client_secure_renegotiate", Value|T]) -> + [{secure_renegotiate, atomize(Value)} | ssl_options(client,T)]; +ssl_options(server, ["server_depth", Value|T]) -> + [{depth, list_to_integer(Value)} | ssl_options(server,T)]; +ssl_options(client, ["client_depth", Value|T]) -> + [{depth, list_to_integer(Value)} | ssl_options(client,T)]; +ssl_options(server, ["server_hibernate_after", Value|T]) -> + [{hibernate_after, list_to_integer(Value)} | ssl_options(server,T)]; +ssl_options(client, ["client_hibernate_after", Value|T]) -> + [{hibernate_after, list_to_integer(Value)} | ssl_options(client,T)]; +ssl_options(server, ["server_ciphers", Value|T]) -> + [{ciphers, Value} | ssl_options(server,T)]; +ssl_options(client, ["client_ciphers", Value|T]) -> + [{ciphers, Value} | ssl_options(client,T)]; +ssl_options(server, ["server_dhfile", Value|T]) -> + [{dhfile, Value} | ssl_options(server,T)]; +ssl_options(server, ["server_fail_if_no_peer_cert", Value|T]) -> + [{fail_if_no_peer_cert, atomize(Value)} | ssl_options(server,T)]; +ssl_options(Type, Opts) -> + error(malformed_ssl_dist_opt, [Type, Opts]). + +atomize(List) when is_list(List) -> + list_to_atom(List); +atomize(Atom) when is_atom(Atom) -> + Atom. + +termify(String) when is_list(String) -> + {ok, Tokens, _} = erl_scan:string(String ++ "."), + {ok, Term} = erl_parse:parse_term(Tokens), + Term. + +verify_fun(Value) -> + case termify(Value) of + {Mod, Func, State} when is_atom(Mod), is_atom(Func) -> + Fun = fun Mod:Func/3, + {Fun, State}; + _ -> + error(malformed_ssl_dist_opt, [Value]) + end. + +%% ------------------------------------------------------------------------- + +%% Trace point +trace(Term) -> Term. + +%% Keep an eye on distribution Pid:s we know of +monitor_pid(Pid) -> + %%spawn( + %% fun () -> + %% MRef = erlang:monitor(process, Pid), + %% receive + %% {'DOWN', MRef, _, _, normal} -> + %% error_logger:error_report( + %% [dist_proc_died, + %% {reason, normal}, + %% {pid, Pid}]); + %% {'DOWN', MRef, _, _, Reason} -> + %% error_logger:info_report( + %% [dist_proc_died, + %% {reason, Reason}, + %% {pid, Pid}]) + %% end + %% end), + Pid. + +dbg() -> + dbg:stop(), + dbg:tracer(), + dbg:p(all, c), + dbg:tpl(?MODULE, cx), + dbg:tpl(erlang, dist_ctrl_get_data_notification, cx), + dbg:tpl(erlang, dist_ctrl_get_data, cx), + dbg:tpl(erlang, dist_ctrl_put_data, cx), + ok. diff --git a/lib/ssl/src/ssl.app.src b/lib/ssl/src/ssl.app.src index 064dcd6892..c5b55641a1 100644 --- a/lib/ssl/src/ssl.app.src +++ b/lib/ssl/src/ssl.app.src @@ -37,7 +37,6 @@ %% Erlang Distribution over SSL/TLS inet_tls_dist, inet6_tls_dist, - ssl_tls_dist_proxy, ssl_dist_sup, ssl_dist_connection_sup, ssl_dist_admin_sup, @@ -63,7 +62,5 @@ {applications, [crypto, public_key, kernel, stdlib]}, {env, []}, {mod, {ssl_app, []}}, - {runtime_dependencies, ["stdlib-3.2","public_key-1.2","kernel-3.0", - "erts-7.0","crypto-3.3", "inets-5.10.7"]}]}. - - + {runtime_dependencies, ["stdlib-3.2","public_key-1.5","kernel-6.0", + "erts-10.0","crypto-3.3", "inets-5.10.7"]}]}. diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index 5d48325719..dd62ccddcd 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -44,12 +44,14 @@ -export([send/2, recv/3, close/2, shutdown/2, new_user/2, get_opts/2, set_opts/2, peer_certificate/1, renegotiation/1, negotiated_protocol/1, prf/5, + get_sslsocket/1, handshake_complete/3, connection_information/2, handle_common_event/5 ]). %% General gen_statem state functions with extra callback argument %% to determine if it is an SSL/TLS or DTLS gen_statem machine --export([init/4, hello/4, abbreviated/4, certify/4, cipher/4, connection/4, downgrade/4]). +-export([init/4, hello/4, abbreviated/4, certify/4, cipher/4, + connection/4, death_row/4, downgrade/4]). %% gen_statem callbacks -export([terminate/3, format_status/2]). @@ -262,6 +264,13 @@ peer_certificate(ConnectionPid) -> renegotiation(ConnectionPid) -> call(ConnectionPid, renegotiate). + +get_sslsocket(ConnectionPid) -> + call(ConnectionPid, get_sslsocket). + +handshake_complete(ConnectionPid, Node, DHandle) -> + call(ConnectionPid, {handshake_complete, Node, DHandle}). + %%-------------------------------------------------------------------- -spec prf(pid(), binary() | 'master_secret', binary(), [binary() | ssl:prf_random()], non_neg_integer()) -> @@ -359,6 +368,12 @@ init({call, From}, {start, {Opts, EmOpts}, Timeout}, socket_options = SockOpts} = State0, Connection) -> try SslOpts = ssl:handle_options(Opts, OrigSSLOptions), + case SslOpts of + #ssl_options{erl_dist = true} -> + process_flag(priority, max); + _ -> + ok + end, State = ssl_config(SslOpts, Role, State0), init({call, From}, {start, Timeout}, State#state{ssl_options = SslOpts, socket_options = new_emulated(EmOpts, SockOpts)}, Connection) @@ -748,7 +763,7 @@ cipher(Type, Msg, State, Connection) -> #state{}, tls_connection | dtls_connection) -> gen_statem:state_function_result(). %%-------------------------------------------------------------------- -connection({call, From}, {application_data, Data}, +connection({call, {FromPid, _} = From}, {application_data, Data}, #state{protocol_cb = Connection} = State, Connection) -> %% We should look into having a worker process to do this to %% parallize send and receive decoding and not block the receiver @@ -756,7 +771,13 @@ connection({call, From}, {application_data, Data}, try write_application_data(Data, From, State) catch throw:Error -> - hibernate_after(connection, State, [{reply, From, Error}]) + case self() of + FromPid -> + {stop, {shutdown, Error}}; + _ -> + hibernate_after( + connection, State, [{reply, From, Error}]) + end end; connection({call, RecvFrom}, {recv, N, Timeout}, #state{protocol_cb = Connection, socket_options = @@ -784,8 +805,50 @@ connection({call, From}, negotiated_protocol, #state{negotiated_protocol = SelectedProtocol} = State, _) -> hibernate_after(connection, State, [{reply, From, {ok, SelectedProtocol}}]); +connection( + {call, From}, {handshake_complete, _Node, DHandle}, + #state{ + ssl_options = #ssl_options{erl_dist = true}, + socket_options = SockOpts, + protocol_specific = ProtocolSpecific} = State, + Connection) -> + %% From now on we execute on normal priority + process_flag(priority, normal), + try erlang:dist_ctrl_get_data_notification(DHandle) of + _ -> + NewState = + State#state{ + socket_options = + SockOpts#socket_options{active = true}, + protocol_specific = + ProtocolSpecific#{d_handle => DHandle}}, + {Record, NewerState} = Connection:next_record_if_active(NewState), + Connection:next_event(connection, Record, NewerState, [{reply, From, ok}]) + catch _:Reason -> + death_row(State, Reason) + end; connection({call, From}, Msg, State, Connection) -> handle_call(Msg, From, connection, State, Connection); +connection( + info, dist_data = Msg, + #state{ + ssl_options = #ssl_options{erl_dist = true}, + protocol_specific = #{d_handle := DHandle}} = State, + _) -> + eat_msgs(Msg), + try send_dist_data(connection, State, DHandle, []) + catch _:Reason -> + death_row(State, Reason) + end; +connection( + info, tick = Msg, + #state{ + ssl_options = #ssl_options{erl_dist = true}, + protocol_specific = #{d_handle := _}}, + _) -> + eat_msgs(Msg), + {keep_state_and_data, + [{next_event, {call, {self(), undefined}}, {application_data, <<>>}}]}; connection(info, Msg, State, _) -> handle_info(Msg, connection, State); connection(internal, {recv, _}, State, Connection) -> @@ -794,6 +857,30 @@ connection(Type, Msg, State, Connection) -> handle_common_event(Type, Msg, connection, State, Connection). %%-------------------------------------------------------------------- +-spec death_row(gen_statem:event_type(), term(), + #state{}, tls_connection | dtls_connection) -> + gen_statem:state_function_result(). +%%-------------------------------------------------------------------- +%% We just wait for the owner to die which triggers the monitor, +%% or the socket may die too +death_row( + info, {'DOWN', MonitorRef, _, _, Reason}, + #state{user_application={MonitorRef,_Pid} = State}, + _) -> + {stop, {shutdown, Reason}, State}; +death_row( + info, {'EXIT', Socket, Reason}, #state{socket = Socket} = State, _) -> + {stop, {shutdown, Reason}, State}; +death_row(state_timeout, Reason, _State, _Connection) -> + {stop, {shutdown,Reason}}; +death_row(_Type, _Msg, State, _Connection) -> + {keep_state, State, [postpone]}. + +%% State entry function +death_row(State, Reason) -> + {next_state, death_row, State, [{state_timeout, 5000, Reason}]}. + +%%-------------------------------------------------------------------- -spec downgrade(gen_statem:event_type(), term(), #state{}, tls_connection | dtls_connection) -> gen_statem:state_function_result(). @@ -804,10 +891,10 @@ downgrade(internal, #alert{description = ?CLOSE_NOTIFY}, tls_socket:setopts(Transport, Socket, [{active, false}, {packet, 0}, {mode, binary}]), Transport:controlling_process(Socket, Pid), gen_statem:reply(From, {ok, Socket}), - {stop, normal, State}; + stop_normal(State); downgrade(timeout, downgrade, #state{downgrade = {_, From}} = State, _) -> gen_statem:reply(From, {error, timeout}), - {stop, normal, State}; + stop_normal(State); downgrade(Type, Event, State, Connection) -> handle_common_event(Type, Event, downgrade, State, Connection). @@ -877,7 +964,7 @@ handle_call({shutdown, How0}, From, _, #state{transport_cb = Transport, negotiated_version = Version, connection_states = ConnectionStates, - socket = Socket}, Connection) -> + socket = Socket} = State, Connection) -> case How0 of How when How == write; How == both -> Alert = ?ALERT_REC(?WARNING, ?CLOSE_NOTIFY), @@ -893,7 +980,7 @@ handle_call({shutdown, How0}, From, _, {keep_state_and_data, [{reply, From, ok}]}; Error -> gen_statem:reply(From, {error, Error}), - {stop, normal} + stop_normal(State) end; handle_call({recv, _N, _Timeout}, From, _, #state{socket_options = @@ -928,6 +1015,15 @@ handle_call({set_opts, Opts0}, From, StateName, handle_call(renegotiate, From, StateName, _, _) when StateName =/= connection -> {keep_state_and_data, [{reply, From, {error, already_renegotiating}}]}; + +handle_call( + get_sslsocket, From, _StateName, + #state{transport_cb = Transport, socket = Socket, tracker = Tracker}, + Connection) -> + SslSocket = + Connection:socket(self(), Transport, Socket, Connection, Tracker), + {keep_state_and_data, [{reply, From, SslSocket}]}; + handle_call({prf, Secret, Label, Seed, WantedLength}, From, _, #state{connection_states = ConnectionStates, negotiated_version = Version}, _) -> @@ -964,18 +1060,19 @@ handle_info({ErrorTag, Socket, econnaborted}, StateName, tracker = Tracker} = State) when StateName =/= connection -> alert_user(Transport, Tracker,Socket, StartFrom, ?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), Role, Connection), - {stop, normal, State}; + stop_normal(State); handle_info({ErrorTag, Socket, Reason}, StateName, #state{socket = Socket, error_tag = ErrorTag} = State) -> Report = io_lib:format("SSL: Socket error: ~p ~n", [Reason]), - error_logger:info_report(Report), + error_logger:error_report(Report), handle_normal_shutdown(?ALERT_REC(?FATAL, ?CLOSE_NOTIFY), StateName, State), - {stop, normal, State}; + stop_normal(State); -handle_info({'DOWN', MonitorRef, _, _, _}, _, - State = #state{user_application={MonitorRef,_Pid}}) -> - {stop, normal, State}; +handle_info( + {'DOWN', MonitorRef, _, _, _}, _, + #state{user_application={MonitorRef,_Pid}} = State) -> + stop_normal(State); %%% So that terminate will be run when supervisor issues shutdown handle_info({'EXIT', _Sup, shutdown}, _StateName, State) -> @@ -983,6 +1080,8 @@ handle_info({'EXIT', _Sup, shutdown}, _StateName, State) -> handle_info({'EXIT', Socket, normal}, _StateName, #state{socket = Socket} = State) -> %% Handle as transport close" {stop, {shutdown, transport_closed}, State}; +handle_info({'EXIT', Socket, Reason}, _StateName, #state{socket = Socket} = State) -> + {stop, {shutdown, Reason}, State}; handle_info(allow_renegotiate, StateName, State) -> {next_state, StateName, State#state{allow_renegotiate = true}}; @@ -1006,6 +1105,38 @@ handle_info(Msg, StateName, #state{socket = Socket, error_tag = Tag} = State) -> error_logger:info_report(Report), {next_state, StateName, State}. + + +send_dist_data(StateName, State, DHandle, Acc) -> + case erlang:dist_ctrl_get_data(DHandle) of + none -> + erlang:dist_ctrl_get_data_notification(DHandle), + hibernate_after(StateName, State, lists:reverse(Acc)); + Data -> + send_dist_data( + StateName, State, DHandle, + [{next_event, {call, {self(), undefined}}, {application_data, Data}} + |Acc]) + end. + +%% Overload mitigation +eat_msgs(Msg) -> + receive Msg -> eat_msgs(Msg) + after 0 -> ok + end. + +%% When running with erl_dist the stop reason 'normal' +%% would be too silent and prevent cleanup +stop_normal(State) -> + Reason = + case State of + #state{ssl_options = #ssl_options{erl_dist = true}} -> + {shutdown, normal}; + _ -> + normal + end, + {stop, Reason, State}. + %%-------------------------------------------------------------------- %% gen_statem callbacks %%-------------------------------------------------------------------- @@ -1080,7 +1211,7 @@ format_status(terminate, [_, StateName, State]) -> %%-------------------------------------------------------------------- %%% %%-------------------------------------------------------------------- -write_application_data(Data0, From, +write_application_data(Data0, {FromPid, _} = From, #state{socket = Socket, negotiated_version = Version, protocol_cb = Connection, @@ -1095,10 +1226,19 @@ write_application_data(Data0, From, Connection:renegotiate(State#state{renegotiation = {true, internal}}, [{next_event, {call, From}, {application_data, Data0}}]); false -> - {Msgs, ConnectionStates} = Connection:encode_data(Data, Version, ConnectionStates0), - Result = Connection:send(Transport, Socket, Msgs), - ssl_connection:hibernate_after(connection, State#state{connection_states = ConnectionStates}, - [{reply, From, Result}]) + {Msgs, ConnectionStates} = + Connection:encode_data(Data, Version, ConnectionStates0), + NewState = State#state{connection_states = ConnectionStates}, + case Connection:send(Transport, Socket, Msgs) of + ok when FromPid =:= self() -> + hibernate_after(connection, NewState, []); + Error when FromPid =:= self() -> + {stop, {shutdown, Error}, NewState}; + ok -> + hibernate_after(connection, NewState, [{reply, From, ok}]); + Result -> + hibernate_after(connection, NewState, [{reply, From, Result}]) + end end. read_application_data(Data, #state{user_application = {_Mon, Pid}, @@ -1118,30 +1258,57 @@ read_application_data(Data, #state{user_application = {_Mon, Pid}, end, case get_data(SOpts, BytesToRead, Buffer1) of {ok, ClientData, Buffer} -> % Send data - SocketOpt = deliver_app_data(Transport, Socket, SOpts, - ClientData, Pid, RecvFrom, Tracker, Connection), - cancel_timer(Timer), - State = State0#state{user_data_buffer = Buffer, - start_or_recv_from = undefined, - timer = undefined, - bytes_to_read = undefined, - socket_options = SocketOpt - }, - if - SocketOpt#socket_options.active =:= false; Buffer =:= <<>> -> - %% Passive mode, wait for active once or recv - %% Active and empty, get more data - Connection:next_record_if_active(State); - true -> %% We have more data - read_application_data(<<>>, State) - end; + case State0 of + #state{ + ssl_options = #ssl_options{erl_dist = true}, + protocol_specific = #{d_handle := DHandle}} -> + State = + State0#state{ + user_data_buffer = Buffer, + bytes_to_read = undefined}, + try erlang:dist_ctrl_put_data(DHandle, ClientData) of + _ + when SOpts#socket_options.active =:= false; + Buffer =:= <<>> -> + %% Passive mode, wait for active once or recv + %% Active and empty, get more data + Connection:next_record_if_active(State); + _ -> %% We have more data + read_application_data(<<>>, State) + catch _:Reason -> + death_row(State, Reason) + end; + _ -> + SocketOpt = + deliver_app_data( + Transport, Socket, SOpts, + ClientData, Pid, RecvFrom, Tracker, Connection), + cancel_timer(Timer), + State = + State0#state{ + user_data_buffer = Buffer, + start_or_recv_from = undefined, + timer = undefined, + bytes_to_read = undefined, + socket_options = SocketOpt + }, + if + SocketOpt#socket_options.active =:= false; + Buffer =:= <<>> -> + %% Passive mode, wait for active once or recv + %% Active and empty, get more data + Connection:next_record_if_active(State); + true -> %% We have more data + read_application_data(<<>>, State) + end + end; {more, Buffer} -> % no reply, we need more data Connection:next_record(State0#state{user_data_buffer = Buffer}); {passive, Buffer} -> Connection:next_record_if_active(State0#state{user_data_buffer = Buffer}); {error,_Reason} -> %% Invalid packet in packet mode deliver_packet_error(Transport, Socket, SOpts, Buffer1, Pid, RecvFrom, Tracker, Connection), - {stop, normal, State0} + stop_normal(State0) end. %%-------------------------------------------------------------------- %%% @@ -1151,12 +1318,12 @@ handle_alert(#alert{level = ?FATAL} = Alert, StateName, protocol_cb = Connection, ssl_options = SslOpts, start_or_recv_from = From, host = Host, port = Port, session = Session, user_application = {_Mon, Pid}, - role = Role, socket_options = Opts, tracker = Tracker}) -> + role = Role, socket_options = Opts, tracker = Tracker} = State) -> invalidate_session(Role, Host, Port, Session), log_alert(SslOpts#ssl_options.log_alert, Role, Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}), alert_user(Transport, Tracker, Socket, StateName, Opts, Pid, From, Alert, Role, Connection), - {stop, normal}; + stop_normal(State); handle_alert(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert, StateName, State) -> diff --git a/lib/ssl/src/ssl_dist_sup.erl b/lib/ssl/src/ssl_dist_sup.erl index 690b896919..c241a9bced 100644 --- a/lib/ssl/src/ssl_dist_sup.erl +++ b/lib/ssl/src/ssl_dist_sup.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011-2016. All Rights Reserved. +%% Copyright Ericsson AB 2011-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -46,8 +46,7 @@ start_link() -> init([]) -> AdminSup = ssl_admin_child_spec(), ConnectionSup = ssl_connection_sup(), - ProxyServer = proxy_server_child_spec(), - {ok, {{one_for_all, 10, 3600}, [AdminSup, ProxyServer, ConnectionSup]}}. + {ok, {{one_for_all, 10, 3600}, [AdminSup, ConnectionSup]}}. %%-------------------------------------------------------------------- %%% Internal functions @@ -69,12 +68,3 @@ ssl_connection_sup() -> Modules = [ssl_connection_sup], Type = supervisor, {Name, StartFunc, Restart, Shutdown, Type, Modules}. - -proxy_server_child_spec() -> - Name = ssl_tls_dist_proxy, - StartFunc = {ssl_tls_dist_proxy, start_link, []}, - Restart = permanent, - Shutdown = 4000, - Modules = [ssl_tls_dist_proxy], - Type = worker, - {Name, StartFunc, Restart, Shutdown, Type, Modules}. diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl deleted file mode 100644 index 08947f24dd..0000000000 --- a/lib/ssl/src/ssl_tls_dist_proxy.erl +++ /dev/null @@ -1,479 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2011-2016. All Rights Reserved. -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% %CopyrightEnd% -%% --module(ssl_tls_dist_proxy). - - --export([listen/2, accept/2, connect/3, get_tcp_address/1]). --export([init/1, start_link/0, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3, ssl_options/2]). - --include_lib("kernel/include/net_address.hrl"). - --record(state, - {listen, - accept_loop - }). - --define(PPRE, 4). --define(PPOST, 4). - - -%%==================================================================== -%% Internal application API -%%==================================================================== - -listen(Driver, Name) -> - gen_server:call(?MODULE, {listen, Driver, Name}, infinity). - -accept(Driver, Listen) -> - gen_server:call(?MODULE, {accept, Driver, Listen}, infinity). - -connect(Driver, Ip, Port) -> - gen_server:call(?MODULE, {connect, Driver, Ip, Port}, infinity). - - -do_listen(Options) -> - {First,Last} = case application:get_env(kernel,inet_dist_listen_min) of - {ok,N} when is_integer(N) -> - case application:get_env(kernel, - inet_dist_listen_max) of - {ok,M} when is_integer(M) -> - {N,M}; - _ -> - {N,N} - end; - _ -> - {0,0} - end, - do_listen(First, Last, listen_options([{backlog,128}|Options])). - -do_listen(First,Last,_) when First > Last -> - {error,eaddrinuse}; -do_listen(First,Last,Options) -> - case gen_tcp:listen(First, Options) of - {error, eaddrinuse} -> - do_listen(First+1,Last,Options); - Other -> - Other - end. - -listen_options(Opts0) -> - Opts1 = - case application:get_env(kernel, inet_dist_use_interface) of - {ok, Ip} -> - [{ip, Ip} | Opts0]; - _ -> - Opts0 - end, - case application:get_env(kernel, inet_dist_listen_options) of - {ok,ListenOpts} -> - ListenOpts ++ Opts1; - _ -> - Opts1 - end. - -connect_options(Opts) -> - case application:get_env(kernel, inet_dist_connect_options) of - {ok,ConnectOpts} -> - lists:ukeysort(1, ConnectOpts ++ Opts); - _ -> - Opts - end. - -%%==================================================================== -%% gen_server callbacks -%%==================================================================== - -start_link() -> - gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). - -init([]) -> - process_flag(priority, max), - {ok, #state{}}. - -handle_call({listen, Driver, Name}, _From, State) -> - case gen_tcp:listen(0, [{active, false}, {packet,?PPRE}, {ip, loopback}]) of - {ok, Socket} -> - {ok, World} = do_listen([{active, false}, binary, {packet,?PPRE}, {reuseaddr, true}, - Driver:family()]), - {ok, TcpAddress} = get_tcp_address(Socket), - {ok, WorldTcpAddress} = get_tcp_address(World), - {_,Port} = WorldTcpAddress#net_address.address, - ErlEpmd = net_kernel:epmd_module(), - case ErlEpmd:register_node(Name, Port, Driver) of - {ok, Creation} -> - {reply, {ok, {Socket, TcpAddress, Creation}}, - State#state{listen={Socket, World}}}; - {error, _} = Error -> - {reply, Error, State} - end; - Error -> - {reply, Error, State} - end; - -handle_call({accept, _Driver, Listen}, {From, _}, State = #state{listen={_, World}}) -> - Self = self(), - ErtsPid = spawn_link(fun() -> accept_loop(Self, erts, Listen, From) end), - WorldPid = spawn_link(fun() -> accept_loop(Self, world, World, Listen) end), - {reply, ErtsPid, State#state{accept_loop={ErtsPid, WorldPid}}}; - -handle_call({connect, Driver, Ip, Port}, {From, _}, State) -> - Me = self(), - Pid = spawn_link(fun() -> setup_proxy(Driver, Ip, Port, Me) end), - receive - {Pid, go_ahead, LPort} -> - Res = {ok, Socket} = try_connect(LPort), - case gen_tcp:controlling_process(Socket, From) of - {error, badarg} = Error -> {reply, Error, State}; % From is dead anyway. - ok -> - flush_old_controller(From, Socket), - {reply, Res, State} - end; - {Pid, Error} -> - {reply, Error, State} - end; - -handle_call(_What, _From, State) -> - {reply, ok, State}. - -handle_cast(_What, State) -> - {noreply, State}. - -handle_info(_What, State) -> - {noreply, State}. - -terminate(_Reason, _St) -> - ok. - -code_change(_OldVsn, St, _Extra) -> - {ok, St}. - -%%-------------------------------------------------------------------- -%%% Internal functions -%%-------------------------------------------------------------------- -get_tcp_address(Socket) -> - case inet:sockname(Socket) of - {ok, Address} -> - {ok, Host} = inet:gethostname(), - NetAddress = #net_address{ - address = Address, - host = Host, - protocol = proxy, - family = inet - }, - {ok, NetAddress}; - {error, _} = Error -> Error - end. - -accept_loop(Proxy, erts = Type, Listen, Extra) -> - process_flag(priority, max), - case gen_tcp:accept(Listen) of - {ok, Socket} -> - Extra ! {accept,self(),Socket,inet,proxy}, - receive - {_Kernel, controller, Pid} -> - inet:setopts(Socket, [nodelay()]), - ok = gen_tcp:controlling_process(Socket, Pid), - flush_old_controller(Pid, Socket), - Pid ! {self(), controller}; - {_Kernel, unsupported_protocol} -> - exit(unsupported_protocol) - end; - {error, closed} -> - %% The listening socket is closed: the proxy process is - %% shutting down. Exit normally, to avoid generating a - %% spurious error report. - exit(normal); - Error -> - exit(Error) - end, - accept_loop(Proxy, Type, Listen, Extra); - -accept_loop(Proxy, world = Type, Listen, Extra) -> - process_flag(priority, max), - case gen_tcp:accept(Listen) of - {ok, Socket} -> - Opts = get_ssl_options(server), - wait_for_code_server(), - case ssl:ssl_accept(Socket, Opts) of - {ok, SslSocket} -> - PairHandler = - spawn_link(fun() -> - setup_connection(SslSocket, Extra) - end), - ok = ssl:controlling_process(SslSocket, PairHandler), - flush_old_controller(PairHandler, SslSocket); - {error, {options, _}} = Error -> - %% Bad options: that's probably our fault. Let's log that. - error_logger:error_msg("Cannot accept TLS distribution connection: ~s~n", - [ssl:format_error(Error)]), - gen_tcp:close(Socket); - _ -> - gen_tcp:close(Socket) - end; - Error -> - exit(Error) - end, - accept_loop(Proxy, Type, Listen, Extra). - -wait_for_code_server() -> - %% This is an ugly hack. Upgrading a socket to TLS requires the - %% crypto module to be loaded. Loading the crypto module triggers - %% its on_load function, which calls code:priv_dir/1 to find the - %% directory where its NIF library is. However, distribution is - %% started earlier than the code server, so the code server is not - %% necessarily started yet, and code:priv_dir/1 might fail because - %% of that, if we receive an incoming connection on the - %% distribution port early enough. - %% - %% If the on_load function of a module fails, the module is - %% unloaded, and the function call that triggered loading it fails - %% with 'undef', which is rather confusing. - %% - %% Thus, the ssl_tls_dist_proxy process will terminate, and be - %% restarted by ssl_dist_sup. However, it won't have any memory - %% of being asked by net_kernel to listen for incoming - %% connections. Hence, the node will believe that it's open for - %% distribution, but it actually isn't. - %% - %% So let's avoid that by waiting for the code server to start. - case whereis(code_server) of - undefined -> - timer:sleep(10), - wait_for_code_server(); - Pid when is_pid(Pid) -> - ok - end. - -try_connect(Port) -> - case gen_tcp:connect({127,0,0,1}, Port, [{active, false}, {packet,?PPRE}, nodelay()]) of - R = {ok, _S} -> - R; - {error, _R} -> - try_connect(Port) - end. - -setup_proxy(Driver, Ip, Port, Parent) -> - process_flag(trap_exit, true), - Opts = connect_options(get_ssl_options(client)), - case ssl:connect(Ip, Port, [{active, true}, binary, {packet,?PPRE}, nodelay(), - Driver:family()] ++ Opts) of - {ok, World} -> - {ok, ErtsL} = gen_tcp:listen(0, [{active, true}, {ip, loopback}, binary, {packet,?PPRE}]), - {ok, #net_address{address={_,LPort}}} = get_tcp_address(ErtsL), - Parent ! {self(), go_ahead, LPort}, - case gen_tcp:accept(ErtsL) of - {ok, Erts} -> - %% gen_tcp:close(ErtsL), - loop_conn_setup(World, Erts); - Err -> - Parent ! {self(), Err} - end; - {error, {options, _}} = Err -> - %% Bad options: that's probably our fault. Let's log that. - error_logger:error_msg("Cannot open TLS distribution connection: ~s~n", - [ssl:format_error(Err)]), - Parent ! {self(), Err}; - Err -> - Parent ! {self(), Err} - end. - - -%% we may not always want the nodelay behaviour -%% %% for performance reasons - -nodelay() -> - case application:get_env(kernel, dist_nodelay) of - undefined -> - {nodelay, true}; - {ok, true} -> - {nodelay, true}; - {ok, false} -> - {nodelay, false}; - _ -> - {nodelay, true} - end. - -setup_connection(World, ErtsListen) -> - process_flag(trap_exit, true), - {ok, TcpAddress} = get_tcp_address(ErtsListen), - {_Addr,Port} = TcpAddress#net_address.address, - {ok, Erts} = gen_tcp:connect({127,0,0,1}, Port, [{active, true}, binary, {packet,?PPRE}, nodelay()]), - ssl:setopts(World, [{active,true}, {packet,?PPRE}, nodelay()]), - loop_conn_setup(World, Erts). - -loop_conn_setup(World, Erts) -> - receive - {ssl, World, Data = <<$a, _/binary>>} -> - gen_tcp:send(Erts, Data), - ssl:setopts(World, [{packet,?PPOST}, nodelay()]), - inet:setopts(Erts, [{packet,?PPOST}, nodelay()]), - loop_conn(World, Erts); - {tcp, Erts, Data = <<$a, _/binary>>} -> - ssl:send(World, Data), - ssl:setopts(World, [{packet,?PPOST}, nodelay()]), - inet:setopts(Erts, [{packet,?PPOST}, nodelay()]), - loop_conn(World, Erts); - {ssl, World, Data = <<_, _/binary>>} -> - gen_tcp:send(Erts, Data), - loop_conn_setup(World, Erts); - {tcp, Erts, Data = <<_, _/binary>>} -> - ssl:send(World, Data), - loop_conn_setup(World, Erts); - {ssl, World, Data} -> - gen_tcp:send(Erts, Data), - loop_conn_setup(World, Erts); - {tcp, Erts, Data} -> - ssl:send(World, Data), - loop_conn_setup(World, Erts); - {tcp_closed, Erts} -> - ssl:close(World); - {ssl_closed, World} -> - gen_tcp:close(Erts); - {ssl_error, World, _} -> - - ssl:close(World) - end. - -loop_conn(World, Erts) -> - receive - {ssl, World, Data} -> - gen_tcp:send(Erts, Data), - loop_conn(World, Erts); - {tcp, Erts, Data} -> - ssl:send(World, Data), - loop_conn(World, Erts); - {tcp_closed, Erts} -> - ssl:close(World); - {ssl_closed, World} -> - gen_tcp:close(Erts); - {ssl_error, World, _} -> - ssl:close(World) - end. - -get_ssl_options(Type) -> - case init:get_argument(ssl_dist_opt) of - {ok, Args} -> - [{erl_dist, true} | ssl_options(Type, lists:append(Args))]; - _ -> - [{erl_dist, true}] - end. - -ssl_options(_,[]) -> - []; -ssl_options(server, ["client_" ++ _, _Value |T]) -> - ssl_options(server,T); -ssl_options(client, ["server_" ++ _, _Value|T]) -> - ssl_options(client,T); -ssl_options(server, ["server_certfile", Value|T]) -> - [{certfile, Value} | ssl_options(server,T)]; -ssl_options(client, ["client_certfile", Value | T]) -> - [{certfile, Value} | ssl_options(client,T)]; -ssl_options(server, ["server_cacertfile", Value|T]) -> - [{cacertfile, Value} | ssl_options(server,T)]; -ssl_options(client, ["client_cacertfile", Value|T]) -> - [{cacertfile, Value} | ssl_options(client,T)]; -ssl_options(server, ["server_keyfile", Value|T]) -> - [{keyfile, Value} | ssl_options(server,T)]; -ssl_options(client, ["client_keyfile", Value|T]) -> - [{keyfile, Value} | ssl_options(client,T)]; -ssl_options(server, ["server_password", Value|T]) -> - [{password, Value} | ssl_options(server,T)]; -ssl_options(client, ["client_password", Value|T]) -> - [{password, Value} | ssl_options(client,T)]; -ssl_options(server, ["server_verify", Value|T]) -> - [{verify, atomize(Value)} | ssl_options(server,T)]; -ssl_options(client, ["client_verify", Value|T]) -> - [{verify, atomize(Value)} | ssl_options(client,T)]; -ssl_options(server, ["server_verify_fun", Value|T]) -> - [{verify_fun, verify_fun(Value)} | ssl_options(server,T)]; -ssl_options(client, ["client_verify_fun", Value|T]) -> - [{verify_fun, verify_fun(Value)} | ssl_options(client,T)]; -ssl_options(server, ["server_crl_check", Value|T]) -> - [{crl_check, atomize(Value)} | ssl_options(server,T)]; -ssl_options(client, ["client_crl_check", Value|T]) -> - [{crl_check, atomize(Value)} | ssl_options(client,T)]; -ssl_options(server, ["server_crl_cache", Value|T]) -> - [{crl_cache, termify(Value)} | ssl_options(server,T)]; -ssl_options(client, ["client_crl_cache", Value|T]) -> - [{crl_cache, termify(Value)} | ssl_options(client,T)]; -ssl_options(server, ["server_reuse_sessions", Value|T]) -> - [{reuse_sessions, atomize(Value)} | ssl_options(server,T)]; -ssl_options(client, ["client_reuse_sessions", Value|T]) -> - [{reuse_sessions, atomize(Value)} | ssl_options(client,T)]; -ssl_options(server, ["server_secure_renegotiate", Value|T]) -> - [{secure_renegotiate, atomize(Value)} | ssl_options(server,T)]; -ssl_options(client, ["client_secure_renegotiate", Value|T]) -> - [{secure_renegotiate, atomize(Value)} | ssl_options(client,T)]; -ssl_options(server, ["server_depth", Value|T]) -> - [{depth, list_to_integer(Value)} | ssl_options(server,T)]; -ssl_options(client, ["client_depth", Value|T]) -> - [{depth, list_to_integer(Value)} | ssl_options(client,T)]; -ssl_options(server, ["server_hibernate_after", Value|T]) -> - [{hibernate_after, list_to_integer(Value)} | ssl_options(server,T)]; -ssl_options(client, ["client_hibernate_after", Value|T]) -> - [{hibernate_after, list_to_integer(Value)} | ssl_options(client,T)]; -ssl_options(server, ["server_ciphers", Value|T]) -> - [{ciphers, Value} | ssl_options(server,T)]; -ssl_options(client, ["client_ciphers", Value|T]) -> - [{ciphers, Value} | ssl_options(client,T)]; -ssl_options(server, ["server_dhfile", Value|T]) -> - [{dhfile, Value} | ssl_options(server,T)]; -ssl_options(server, ["server_fail_if_no_peer_cert", Value|T]) -> - [{fail_if_no_peer_cert, atomize(Value)} | ssl_options(server,T)]; -ssl_options(Type, Opts) -> - error(malformed_ssl_dist_opt, [Type, Opts]). - -atomize(List) when is_list(List) -> - list_to_atom(List); -atomize(Atom) when is_atom(Atom) -> - Atom. - -termify(String) when is_list(String) -> - {ok, Tokens, _} = erl_scan:string(String ++ "."), - {ok, Term} = erl_parse:parse_term(Tokens), - Term. - -verify_fun(Value) -> - case termify(Value) of - {Mod, Func, State} when is_atom(Mod), is_atom(Func) -> - Fun = fun Mod:Func/3, - {Fun, State}; - _ -> - error(malformed_ssl_dist_opt, [Value]) - end. - -flush_old_controller(Pid, Socket) -> - receive - {tcp, Socket, Data} -> - Pid ! {tcp, Socket, Data}, - flush_old_controller(Pid, Socket); - {tcp_closed, Socket} -> - Pid ! {tcp_closed, Socket}, - flush_old_controller(Pid, Socket); - {ssl, Socket, Data} -> - Pid ! {ssl, Socket, Data}, - flush_old_controller(Pid, Socket); - {ssl_closed, Socket} -> - Pid ! {ssl_closed, Socket}, - flush_old_controller(Pid, Socket) - after 0 -> - ok - end. diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index e3ffbea3d3..16b30a92c6 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -65,7 +65,7 @@ %% gen_statem state functions -export([init/3, error/3, downgrade/3, %% Initiation and take down states hello/3, certify/3, cipher/3, abbreviated/3, %% Handshake states - connection/3]). + connection/3, death_row/3]). %% gen_statem callbacks -export([callback_mode/0, terminate/3, code_change/4, format_status/2]). @@ -378,6 +378,13 @@ connection(Type, Event, State) -> ssl_connection:connection(Type, Event, State, ?MODULE). %%-------------------------------------------------------------------- +-spec death_row(gen_statem:event_type(), term(), #state{}) -> + gen_statem:state_function_result(). +%%-------------------------------------------------------------------- +death_row(Type, Event, State) -> + ssl_connection:death_row(Type, Event, State, ?MODULE). + +%%-------------------------------------------------------------------- -spec downgrade(gen_statem:event_type(), term(), #state{}) -> gen_statem:state_function_result(). %%-------------------------------------------------------------------- @@ -434,7 +441,7 @@ handle_info({CloseTag, Socket}, StateName, next_event(StateName, no_record, State) end; handle_info(Msg, StateName, State) -> - ssl_connection:handle_info(Msg, StateName, State). + ssl_connection:StateName(info, Msg, State, ?MODULE). handle_common_event(internal, #alert{} = Alert, StateName, #state{negotiated_version = Version} = State) -> diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl index 64e8042b25..f38c0a7416 100644 --- a/lib/ssl/test/ssl_ECC_SUITE.erl +++ b/lib/ssl/test/ssl_ECC_SUITE.erl @@ -232,103 +232,150 @@ end_per_testcase(_TestCase, Config) -> %% ECDH_RSA client_ecdh_rsa_server_ecdh_rsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], ecdh_rsa, ecdh_rsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdh_rsa} | proplists:delete(check_keyex, Config)]). client_ecdhe_rsa_server_ecdh_rsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_rsa, ecdh_rsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_rsa, ecdh_rsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdh_rsa} | proplists:delete(check_keyex, Config)]). client_ecdhe_ecdsa_server_ecdh_rsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdh_rsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdh_rsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdh_rsa} | proplists:delete(check_keyex, Config)]). %% ECDHE_RSA client_ecdh_rsa_server_ecdhe_rsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdh_rsa, ecdhe_rsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdh_rsa, ecdhe_rsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdhe_rsa} | proplists:delete(check_keyex, Config)]). client_ecdhe_rsa_server_ecdhe_rsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_rsa, ecdhe_rsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_rsa, ecdhe_rsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdhe_rsa} | proplists:delete(check_keyex, Config)]). client_ecdhe_ecdsa_server_ecdhe_rsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdh_ecdsa, ecdhe_rsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdh_ecdsa, ecdhe_rsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdhe_rsa} | proplists:delete(check_keyex, Config)]). - + %% ECDH_ECDSA client_ecdh_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_peer_opts, - [{extensions, [{key_usage, [keyEncipherment] - }]}]}], + Ext = x509_test:extensions([{key_usage, [keyEncipherment]}]), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, + [[], [], [{extensions, Ext}]]}, + {client_chain, + ssl_test_lib:default_cert_chain_conf()}], ecdh_ecdsa, ecdh_ecdsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdh_ecdsa} | proplists:delete(check_keyex, Config)]). client_ecdhe_rsa_server_ecdh_ecdsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_peer_opts, - [{extensions, [{key_usage, [keyEncipherment] - }]}]}], - ecdhe_rsa, ecdh_ecdsa, Config), - basic_test(COpts, SOpts, [{check_keyex, ecdh_ecdsa} | proplists:delete(check_keyex, Config)]). + Ext = x509_test:extensions([{key_usage, [keyEncipherment]}]), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, + [[], [], [{extensions, Ext}]]}, + {client_chain, + ssl_test_lib:default_cert_chain_conf()}], + ecdhe_rsa, ecdh_ecdsa, Config), + basic_test(COpts, SOpts, [{check_keyex, ecdh_ecdsa} | proplists:delete(check_keyex, Config)]). client_ecdhe_ecdsa_server_ecdh_ecdsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_peer_opts, - [{extensions, [{key_usage, [keyEncipherment] - }]}]}], - ecdhe_ecdsa, ecdh_ecdsa, Config), + Ext = x509_test:extensions([{key_usage, [keyEncipherment]}]), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, + [[], [], [{extensions, Ext}]]}, + {client_chain, + ssl_test_lib:default_cert_chain_conf()}], + ecdhe_ecdsa, ecdh_ecdsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdh_ecdsa} | proplists:delete(check_keyex, Config)]). %% ECDHE_ECDSA client_ecdh_rsa_server_ecdhe_ecdsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdh_rsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdh_rsa, ecdhe_ecdsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdhe_ecdsa} | proplists:delete(check_keyex, Config)]). client_ecdh_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdh_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdh_ecdsa, ecdhe_ecdsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdhe_ecdsa} | proplists:delete(check_keyex, Config)]). client_ecdhe_ecdsa_server_ecdhe_ecdsa(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_ecdsa, Config), basic_test(COpts, SOpts, [{check_keyex, ecdhe_ecdsa} | proplists:delete(check_keyex, Config)]). client_ecdsa_server_ecdsa_with_raw_key(Config) when is_list(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}] + , ecdhe_ecdsa, ecdhe_ecdsa, Config), ServerKeyFile = proplists:get_value(keyfile, SOpts), {ok, PemBin} = file:read_file(ServerKeyFile), PemEntries = public_key:pem_decode(PemBin), - {'ECPrivateKey', Key, not_encrypted} = proplists:lookup('ECPrivateKey', PemEntries), + {'ECPrivateKey', Key, not_encrypted} = proplists:lookup('ECPrivateKey', PemEntries), ServerKey = {'ECPrivateKey', Key}, SType = proplists:get_value(server_type, Config), CType = proplists:get_value(client_type, Config), {Server, Port} = start_server_with_raw_key(SType, [{key, ServerKey} | proplists:delete(keyfile, SOpts)], - Config), + Config), Client = start_client(CType, Port, COpts, Config), - check_result(Server, SType, Client, CType), + check_result(Server, SType, Client, CType), close(Server, Client). ecc_default_order(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_ecdsa, Config), ECCOpts = [], case supported_eccs([{eccs, [sect571r1]}]) of true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config); false -> {skip, "unsupported named curves"} - end. + end. ecc_default_order_custom_curves(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_ecdsa, Config), ECCOpts = [{eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of - true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config); + true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config); false -> {skip, "unsupported named curves"} end. ecc_client_order(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_ecdsa, Config), ECCOpts = [{honor_ecc_order, false}], case supported_eccs([{eccs, [sect571r1]}]) of - true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config); + true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config); false -> {skip, "unsupported named curves"} end. ecc_client_order_custom_curves(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_ecdsa, Config), ECCOpts = [{honor_ecc_order, false}, {eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of true -> ecc_test(sect571r1, COpts, SOpts, [], ECCOpts, Config); @@ -336,45 +383,62 @@ ecc_client_order_custom_curves(Config) -> end. ecc_unknown_curve(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_ecdsa, Config), ECCOpts = [{eccs, ['123_fake_curve']}], ecc_test_error(COpts, SOpts, [], ECCOpts, Config). client_ecdh_rsa_server_ecdhe_ecdsa_server_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdh_rsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdh_rsa, ecdhe_ecdsa, Config), ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}], - case supported_eccs(ECCOpts) of - true -> ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config); - false -> {skip, "unsupported named curves"} - end. + case supported_eccs(ECCOpts) of + true -> ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config); + false -> {skip, "unsupported named curves"} + end. client_ecdh_rsa_server_ecdhe_rsa_server_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdh_rsa, ecdhe_rsa, Config), - ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}], + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdh_rsa, ecdhe_rsa, Config), + ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of true -> ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config); false -> {skip, "unsupported named curves"} end. client_ecdhe_rsa_server_ecdhe_ecdsa_server_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_rsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_rsa, ecdhe_ecdsa, Config), ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of - true -> ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config); + true -> ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config); false -> {skip, "unsupported named curves"} end. client_ecdhe_rsa_server_ecdhe_rsa_server_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_rsa, ecdhe_rsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_rsa, ecdhe_rsa, Config), ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of true -> ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config); false -> {skip, "unsupported named curves"} - end. + end. client_ecdhe_rsa_server_ecdh_rsa_server_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_peer_opts, - [{extensions, [{key_usage, [keyEncipherment] - }]}]}], ecdhe_rsa, ecdh_rsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + Ext = x509_test:extensions([{key_usage, [keyEncipherment]}]), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, [[], [], [{extensions, Ext}]]}, + {client_chain, Default}], + ecdhe_rsa, ecdh_rsa, Config), ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of true -> ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config); @@ -382,7 +446,10 @@ client_ecdhe_rsa_server_ecdh_rsa_server_custom(Config) -> end. client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([], ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_ecdsa, Config), ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of true -> ecc_test(secp256r1, COpts, SOpts, [], ECCOpts, Config); @@ -390,7 +457,10 @@ client_ecdhe_ecdsa_server_ecdhe_ecdsa_server_custom(Config) -> end. client_ecdhe_ecdsa_server_ecdhe_rsa_server_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_rsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_rsa, Config), ECCOpts = [{honor_ecc_order, true}, {eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of true -> ecc_test(undefined, COpts, SOpts, [], ECCOpts, Config); @@ -398,7 +468,10 @@ client_ecdhe_ecdsa_server_ecdhe_rsa_server_custom(Config) -> end. client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_ecdsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_ecdsa, ecdhe_ecdsa, Config), ECCOpts = [{eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of true -> ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config); @@ -406,7 +479,10 @@ client_ecdhe_ecdsa_server_ecdhe_ecdsa_client_custom(Config) -> end. client_ecdhe_rsa_server_ecdhe_ecdsa_client_custom(Config) -> - {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([],ecdhe_rsa, ecdhe_ecdsa, Config), + Default = ssl_test_lib:default_cert_chain_conf(), + {COpts, SOpts} = ssl_test_lib:make_ec_cert_chains([{server_chain, Default}, + {client_chain, Default}], + ecdhe_rsa, ecdhe_ecdsa, Config), ECCOpts = [{eccs, [secp256r1, sect571r1]}], case supported_eccs(ECCOpts) of true -> ecc_test(secp256r1, COpts, SOpts, ECCOpts, [], Config); diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl index c3fd73bf09..0bc265fa10 100644 --- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl +++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl @@ -439,7 +439,7 @@ server_require_peer_cert_partial_chain_fun_fail(Config) when is_list(Config) -> [{_,_,_}, {_, IntermidiateCA, _} | _] = public_key:pem_decode(ServerCAs), PartialChain = fun(_CertChain) -> - ture = false %% crash on purpose + ture = false %% crash on purpose end, Server = ssl_test_lib:start_server_error([{node, ServerNode}, {port, 0}, @@ -567,9 +567,12 @@ cert_expired() -> cert_expired(Config) when is_list(Config) -> {Year, Month, Day} = date(), Active = proplists:get_value(active, Config), - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_ca_0, - [{validity, {{Year-2, Month, Day}, - {Year-1, Month, Day}}}]}], + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_chain, + [[], + [{validity, {{Year-2, Month, Day}, + {Year-1, Month, Day}}}], + [] + ]}], Config, "_expired"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), @@ -598,11 +601,11 @@ extended_key_usage_verify_server() -> [{doc,"Test cert that has a critical extended_key_usage extension in server cert"}]. extended_key_usage_verify_server(Config) when is_list(Config) -> - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_peer_opts, - [{extensions, - [{?'id-ce-extKeyUsage', - [?'id-kp-serverAuth'], true}] - }]}], Config, "_keyusage_server"), + Ext = x509_test:extensions([{?'id-ce-extKeyUsage', + [?'id-kp-serverAuth'], true}]), + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_chain, + [[],[], [{extensions, Ext}]]}], Config, + "_keyusage_server"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), Active = proplists:get_value(active, Config), @@ -632,14 +635,13 @@ extended_key_usage_verify_both() -> [{doc,"Test cert that has a critical extended_key_usage extension in client verify_peer mode"}]. extended_key_usage_verify_both(Config) when is_list(Config) -> - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_peer_opts, - [{extensions, [{?'id-ce-extKeyUsage', - [?'id-kp-serverAuth'], true}] - }]}, - {client_peer_opts, - [{extensions, [{?'id-ce-extKeyUsage', - [?'id-kp-clientAuth'], true}] - }]}], Config, "_keyusage_both"), + ServerExt = x509_test:extensions([{?'id-ce-extKeyUsage', + [?'id-kp-serverAuth'], true}]), + ClientExt = x509_test:extensions([{?'id-ce-extKeyUsage', + [?'id-kp-clientAuth'], true}]), + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_chain, [[],[],[{extensions, ClientExt}]]}, + {server_chain, [[],[],[{extensions, ServerExt}]]}], + Config, "_keyusage_both"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), Active = proplists:get_value(active, Config), @@ -668,10 +670,10 @@ critical_extension_verify_server() -> [{doc,"Test cert that has a critical unknown extension in verify_peer mode"}]. critical_extension_verify_server(Config) when is_list(Config) -> - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_peer_opts, - [{extensions, [{{2,16,840,1,113730,1,1}, - <<3,2,6,192>>, true}] - }]}], Config, "_client_unknown_extension"), + Ext = x509_test:extensions([{{2,16,840,1,113730,1,1}, <<3,2,6,192>>, true}]), + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_chain, + [[],[], [{extensions, Ext}]]}], + Config, "_client_unknown_extension"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), Active = proplists:get_value(active, Config), @@ -705,10 +707,10 @@ critical_extension_verify_client() -> [{doc,"Test cert that has a critical unknown extension in verify_peer mode"}]. critical_extension_verify_client(Config) when is_list(Config) -> - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_peer_opts, - [{extensions, [{{2,16,840,1,113730,1,1}, - <<3,2,6,192>>, true}] - }]}], Config, "_server_unknown_extensions"), + Ext = x509_test:extensions([{{2,16,840,1,113730,1,1}, <<3,2,6,192>>, true}]), + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_chain, + [[],[],[{extensions, Ext}]]}], + Config, "_server_unknown_extensions"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), Active = proplists:get_value(active, Config), @@ -741,11 +743,10 @@ critical_extension_verify_none() -> [{doc,"Test cert that has a critical unknown extension in verify_none mode"}]. critical_extension_verify_none(Config) when is_list(Config) -> - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_peer_opts, - [{extensions, - [{{2,16,840,1,113730,1,1}, - <<3,2,6,192>>, true}] - }]}], Config, "_unknown_extensions"), + Ext = x509_test:extensions([{{2,16,840,1,113730,1,1}, <<3,2,6,192>>, true}]), + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_chain, + [[],[], [{extensions, Ext}]]}], + Config, "_unknown_extensions"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), Active = proplists:get_value(active, Config), @@ -780,12 +781,7 @@ no_authority_key_identifier() -> " but are present in trusted certs db."}]. no_authority_key_identifier(Config) when is_list(Config) -> - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_peer_opts, - [{extensions, [{auth_key_id, undefined}] - }]}, - {client_peer_opts, - [{extensions, [{auth_key_id, undefined}] - }]}], Config, "_peer_no_auth_key_id"), + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([], Config, "_peer_no_auth_key_id"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), @@ -822,14 +818,10 @@ no_authority_key_identifier_keyEncipherment() -> " authorityKeyIdentifier extension, but are present in trusted certs db."}]. no_authority_key_identifier_keyEncipherment(Config) when is_list(Config) -> - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{server_peer_opts, - [{extensions, [{auth_key_id, undefined}, - {key_usage, [digitalSignature, - keyEncipherment]}] - }]}, - {client_peer_opts, - [{extensions, [{auth_key_id, undefined}] - }]}], Config, "_peer_keyEncipherment"), + ClientExt = x509_test:extensions([{key_usage, [digitalSignature, keyEncipherment]}]), + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_chain, + [[],[],[{extensions, ClientExt}]]}], + Config, "_peer_keyEncipherment"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config), @@ -932,12 +924,10 @@ client_with_cert_cipher_suites_handshake() -> [{doc, "Test that client with a certificate without keyEncipherment usage " " extension can connect to a server with restricted cipher suites "}]. client_with_cert_cipher_suites_handshake(Config) when is_list(Config) -> - {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_peer_opts, - [{extensions, - [{key_usage, [digitalSignature]}] - }]}], Config, "_sign_only_extensions"), - - + Ext = x509_test:extensions([{key_usage, [digitalSignature]}]), + {ClientOpts0, ServerOpts0} = ssl_test_lib:make_rsa_cert_chains([{client_chain, + [[], [], [{extensions, Ext}]]}], + Config, "_sign_only_extensions"), ClientOpts = ssl_test_lib:ssl_options(ClientOpts0, Config), ServerOpts = ssl_test_lib:ssl_options(ServerOpts0, Config), diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index a5f03a1f15..4e7252f469 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -449,11 +449,12 @@ make_dsa_cert(Config) -> CryptoSupport = crypto:supports(), case proplists:get_bool(dss, proplists:get_value(public_keys, CryptoSupport)) of true -> + ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()), + ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()), + CertChainConf = gen_conf(dsa, dsa, ClientChain, ServerChain), ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "dsa"]), ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "dsa"]), - KeyGenSpec = key_gen_info(dsa, dsa), - - GenCertData = x509_test:gen_test_certs([{digest, sha} | KeyGenSpec]), + GenCertData = public_key:pkix_test_data(CertChainConf), [{server_config, ServerConf}, {client_config, ClientConf}] = x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase), @@ -469,12 +470,13 @@ make_dsa_cert(Config) -> false -> Config end. -make_rsa_cert_chains(ChainConf, Config, Suffix) -> - CryptoSupport = crypto:supports(), - KeyGenSpec = key_gen_info(rsa, rsa), +make_rsa_cert_chains(UserConf, Config, Suffix) -> + ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()), + ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()), + CertChainConf = gen_conf(rsa, rsa, ClientChain, ServerChain), ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa" ++ Suffix]), ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa" ++ Suffix]), - GenCertData = x509_test:gen_test_certs([{digest, appropriate_sha(CryptoSupport)} | KeyGenSpec] ++ ChainConf), + GenCertData = public_key:pkix_test_data(CertChainConf), [{server_config, ServerConf}, {client_config, ClientConf}] = x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase), @@ -482,12 +484,13 @@ make_rsa_cert_chains(ChainConf, Config, Suffix) -> [{reuseaddr, true}, {verify, verify_peer} | ServerConf] }. -make_ec_cert_chains(ChainConf, ClientChainType, ServerChainType, Config) -> - CryptoSupport = crypto:supports(), - KeyGenSpec = key_gen_info(ClientChainType, ServerChainType), +make_ec_cert_chains(UserConf, ClientChainType, ServerChainType, Config) -> + ClientChain = proplists:get_value(client_chain, UserConf, default_cert_chain_conf()), + ServerChain = proplists:get_value(server_chain, UserConf, default_cert_chain_conf()), + CertChainConf = gen_conf(ClientChainType, ServerChainType, ClientChain, ServerChain), ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ClientChainType)]), ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), atom_to_list(ServerChainType)]), - GenCertData = x509_test:gen_test_certs([{digest, appropriate_sha(CryptoSupport)} | KeyGenSpec] ++ ChainConf), + GenCertData = public_key:pkix_test_data(CertChainConf), [{server_config, ServerConf}, {client_config, ClientConf}] = x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase), @@ -495,56 +498,113 @@ make_ec_cert_chains(ChainConf, ClientChainType, ServerChainType, Config) -> [{reuseaddr, true}, {verify, verify_peer} | ServerConf] }. -key_gen_info(ClientChainType, ServerChainType) -> - key_gen_spec("client", ClientChainType) ++ key_gen_spec("server", ServerChainType). +default_cert_chain_conf() -> + %% Use only default options + [[],[],[]]. + +gen_conf(ClientChainType, ServerChainType, UserClient, UserServer) -> + ClientTag = conf_tag("client"), + ServerTag = conf_tag("server"), + + DefaultClient = chain_spec(client, ClientChainType), + DefaultServer = chain_spec(server, ServerChainType), + + ClientConf = merge_chain_spec(UserClient, DefaultClient, []), + ServerConf = merge_chain_spec(UserServer, DefaultServer, []), + + new_format([{ClientTag, ClientConf}, {ServerTag, ServerConf}]). + +new_format(Conf) -> + CConf = proplists:get_value(client_chain, Conf), + SConf = proplists:get_value(server_chain, Conf), + #{server_chain => proplist_to_map(SConf), + client_chain => proplist_to_map(CConf)}. + +proplist_to_map([Head | Rest]) -> + [Last | Tail] = lists:reverse(Rest), + #{root => Head, + intermediates => lists:reverse(Tail), + peer => Last}. + +conf_tag(Role) -> + list_to_atom(Role ++ "_chain"). -key_gen_spec(Role, ecdh_rsa) -> +chain_spec(_Role, ecdh_rsa) -> + Digest = {digest, appropriate_sha(crypto:supports())}, CurveOid = hd(tls_v1:ecc_curves(0)), - [{list_to_atom(Role ++ "_key_gen"), {namedCurve, CurveOid}}, - {list_to_atom(Role ++ "_key_gen_chain"), [hardcode_rsa_key(1), - {namedCurve, CurveOid}]} - ]; -key_gen_spec(Role, ecdhe_ecdsa) -> + [[Digest, {key, {namedCurve, CurveOid}}], + [Digest, {key, hardcode_rsa_key(1)}], + [Digest, {key, {namedCurve, CurveOid}}]]; + +chain_spec(_Role, ecdhe_ecdsa) -> + Digest = {digest, appropriate_sha(crypto:supports())}, CurveOid = hd(tls_v1:ecc_curves(0)), - [{list_to_atom(Role ++ "_key_gen"), {namedCurve, CurveOid}}, - {list_to_atom(Role ++ "_key_gen_chain"), [{namedCurve, CurveOid}, - {namedCurve, CurveOid}]} - ]; -key_gen_spec(Role, ecdh_ecdsa) -> + [[Digest, {key, {namedCurve, CurveOid}}], + [Digest, {key, {namedCurve, CurveOid}}], + [Digest, {key, {namedCurve, CurveOid}}]]; + +chain_spec(_Role, ecdh_ecdsa) -> + Digest = {digest, appropriate_sha(crypto:supports())}, CurveOid = hd(tls_v1:ecc_curves(0)), - [{list_to_atom(Role ++ "_key_gen"), {namedCurve, CurveOid}}, - {list_to_atom(Role ++ "_key_gen_chain"), [{namedCurve, CurveOid}, - {namedCurve, CurveOid}]} - ]; -key_gen_spec(Role, ecdhe_rsa) -> - [{list_to_atom(Role ++ "_key_gen"), hardcode_rsa_key(1)}, - {list_to_atom(Role ++ "_key_gen_chain"), [hardcode_rsa_key(2), - hardcode_rsa_key(3)]} - ]; -key_gen_spec(Role, rsa) -> - [{list_to_atom(Role ++ "_key_gen"), hardcode_rsa_key(1)}, - {list_to_atom(Role ++ "_key_gen_chain"), [hardcode_rsa_key(2), - hardcode_rsa_key(3)]} - ]; -key_gen_spec(Role, dsa) -> - [{list_to_atom(Role ++ "_key_gen"), hardcode_dsa_key(1)}, - {list_to_atom(Role ++ "_key_gen_chain"), [hardcode_dsa_key(2), - hardcode_dsa_key(3)]} - ]. + [[Digest, {key, {namedCurve, CurveOid}}], + [Digest, {key, {namedCurve, CurveOid}}], + [Digest, {key, {namedCurve, CurveOid}}]]; +chain_spec(_Role, ecdhe_rsa) -> + Digest = {digest, appropriate_sha(crypto:supports())}, + [[Digest, {key, hardcode_rsa_key(1)}], + [Digest, {key, hardcode_rsa_key(2)}], + [Digest, {key, hardcode_rsa_key(3)}]]; +chain_spec(_Role, ecdsa) -> + Digest = {digest, appropriate_sha(crypto:supports())}, + CurveOid = hd(tls_v1:ecc_curves(0)), + [[Digest, {key, {namedCurve, CurveOid}}], + [Digest, {key, {namedCurve, CurveOid}}], + [Digest, {key, {namedCurve, CurveOid}}]]; +chain_spec(_Role, rsa) -> + Digest = {digest, appropriate_sha(crypto:supports())}, + [[Digest, {key, hardcode_rsa_key(1)}], + [Digest, {key, hardcode_rsa_key(2)}], + [Digest, {key, hardcode_rsa_key(3)}]]; +chain_spec(_Role, dsa) -> + Digest = {digest, appropriate_sha(crypto:supports())}, + [[Digest, {key, hardcode_dsa_key(1)}], + [Digest, {key, hardcode_dsa_key(2)}], + [Digest, {key, hardcode_dsa_key(3)}]]. + +merge_chain_spec([], [], Acc)-> + lists:reverse(Acc); +merge_chain_spec([User| UserRest], [Default | DefaultRest], Acc) -> + Merge = merge_spec(User, Default, confs(), []), + merge_chain_spec(UserRest, DefaultRest, [Merge | Acc]). + +confs() -> + [key, digest, validity, extensions]. + +merge_spec(_, _, [], Acc) -> + Acc; +merge_spec(User, Default, [Conf | Rest], Acc) -> + case proplists:get_value(Conf, User, undefined) of + undefined -> + case proplists:get_value(Conf, Default, undefined) of + undefined -> + merge_spec(User, Default, Rest, Acc); + Value -> + merge_spec(User, Default, Rest, [{Conf, Value} | Acc]) + end; + Value -> + merge_spec(User, Default, Rest, [{Conf, Value} | Acc]) + end. + make_ecdsa_cert(Config) -> CryptoSupport = crypto:supports(), case proplists:get_bool(ecdsa, proplists:get_value(public_keys, CryptoSupport)) of true -> ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdsa"]), ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdsa"]), - CurveOid = hd(tls_v1:ecc_curves(0)), - GenCertData = x509_test:gen_test_certs([{server_key_gen, {namedCurve, CurveOid}}, - {client_key_gen, {namedCurve, CurveOid}}, - {server_key_gen_chain, [{namedCurve, CurveOid}, - {namedCurve, CurveOid}]}, - {client_key_gen_chain, [{namedCurve, CurveOid}, - {namedCurve, CurveOid}]}, - {digest, appropriate_sha(CryptoSupport)}]), + ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()), + ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()), + CertChainConf = gen_conf(ecdsa, ecdsa, ClientChain, ServerChain), + GenCertData = public_key:pkix_test_data(CertChainConf), [{server_config, ServerConf}, {client_config, ClientConf}] = x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase), @@ -563,13 +623,10 @@ make_rsa_cert(Config) -> true -> ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa"]), ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "rsa"]), - GenCertData = x509_test:gen_test_certs([{server_key_gen, hardcode_rsa_key(1)}, - {client_key_gen, hardcode_rsa_key(2)}, - {server_key_gen_chain, [hardcode_rsa_key(3), - hardcode_rsa_key(4)]}, - {client_key_gen_chain, [hardcode_rsa_key(5), - hardcode_rsa_key(6)]}, - {digest, appropriate_sha(CryptoSupport)}]), + ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()), + ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()), + CertChainConf = gen_conf(rsa, rsa, ClientChain, ServerChain), + GenCertData = public_key:pkix_test_data(CertChainConf), [{server_config, ServerConf}, {client_config, ClientConf}] = x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase), @@ -601,16 +658,10 @@ make_ecdh_rsa_cert(Config) -> true -> ClientFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdh_rsa"]), ServerFileBase = filename:join([proplists:get_value(priv_dir, Config), "ecdh_rsa"]), - CurveOid = hd(tls_v1:ecc_curves(0)), - GenCertData = x509_test:gen_test_certs([{server_key_gen, {namedCurve, CurveOid}}, - {client_key_gen, {namedCurve, CurveOid}}, - {server_key_gen_chain, [hardcode_rsa_key(1), - {namedCurve, CurveOid} - ]}, - {client_key_gen_chain, [hardcode_rsa_key(2), - {namedCurve, CurveOid} - ]}, - {digest, appropriate_sha(CryptoSupport)}]), + ClientChain = proplists:get_value(client_chain, Config, default_cert_chain_conf()), + ServerChain = proplists:get_value(server_chain, Config, default_cert_chain_conf()), + CertChainConf = gen_conf(ecdh_rsa, ecdh_rsa, ClientChain, ServerChain), + GenCertData = public_key:pkix_test_data(CertChainConf), [{server_config, ServerConf}, {client_config, ClientConf}] = x509_test:gen_pem_config_files(GenCertData, ClientFileBase, ServerFileBase), @@ -1509,73 +1560,79 @@ tls_version(Atom) -> tls_record:protocol_version(Atom). hardcode_rsa_key(1) -> - {'RSAPrivateKey', 'two-prime', - 23995666614853919027835084074500048897452890537492185072956789802729257783422306095699263934587064480357348855732149402060270996295002843755712064937715826848741191927820899197493902093529581182351132392364214171173881547273475904587683433713767834856230531387991145055273426806331200574039205571401702219159773947658558490957010003143162250693492642996408861265758000254664396313741422909188635443907373976005987612936763564996605457102336549804831742940035613780926178523017685712710473543251580072875247250504243621640157403744718833162626193206685233710319205099867303242759099560438381385658382486042995679707669, - 17, - 11292078406990079542510627799764728892919007311761028269626724613049062486316379339152594792746853873109340637991599718616598115903530750002688030558925094987642913848386305504703012749896273497577003478759630198199473669305165131570674557041773098755873191241407597673069847908861741446606684974777271632545629600685952292605647052193819136445675100211504432575554351515262198132231537860917084269870590492135731720141577986787033006338680118008484613510063003323516659048210893001173583018220214626635609151105287049126443102976056146630518124476470236027123782297108342869049542023328584384300970694412006494684657, - 169371138592582642967021557955633494538845517070305333860805485424261447791289944610138334410987654265476540480228705481960508520379619587635662291973699651583489223555422528867090299996446070521801757353675026048850480903160224210802452555900007597342687137394192939372218903554801584969667104937092080815197, - 141675062317286527042995673340952251894209529891636708844197799307963834958115010129693036021381525952081167155681637592199810112261679449166276939178032066869788822014115556349519329537177920752776047051833616197615329017439297361972726138285974555338480581117881706656603857310337984049152655480389797687577, - 119556097830058336212015217380447172615655659108450823901745048534772786676204666783627059584226579481512852103690850928442711896738555003036938088452023283470698275450886490965004917644550167427154181661417665446247398284583687678213495921811770068712485038160606780733330990744565824684470897602653233516609, - 41669135975672507953822256864985956439473391144599032012999352737636422046504414744027363535700448809435637398729893409470532385959317485048904982111185902020526124121798693043976273393287623750816484427009887116945685005129205106462566511260580751570141347387612266663707016855981760014456663376585234613993, - 76837684977089699359024365285678488693966186052769523357232308621548155587515525857011429902602352279058920284048929101483304120686557782043616693940283344235057989514310975192908256494992960578961614059245280827077951132083993754797053182279229469590276271658395444955906108899267024101096069475145863928441, - asn1_NOVALUE}; + #'RSAPrivateKey'{ + version = 'two-prime', + modulus = 23995666614853919027835084074500048897452890537492185072956789802729257783422306095699263934587064480357348855732149402060270996295002843755712064937715826848741191927820899197493902093529581182351132392364214171173881547273475904587683433713767834856230531387991145055273426806331200574039205571401702219159773947658558490957010003143162250693492642996408861265758000254664396313741422909188635443907373976005987612936763564996605457102336549804831742940035613780926178523017685712710473543251580072875247250504243621640157403744718833162626193206685233710319205099867303242759099560438381385658382486042995679707669, + publicExponent = 17, + privateExponent = 11292078406990079542510627799764728892919007311761028269626724613049062486316379339152594792746853873109340637991599718616598115903530750002688030558925094987642913848386305504703012749896273497577003478759630198199473669305165131570674557041773098755873191241407597673069847908861741446606684974777271632545629600685952292605647052193819136445675100211504432575554351515262198132231537860917084269870590492135731720141577986787033006338680118008484613510063003323516659048210893001173583018220214626635609151105287049126443102976056146630518124476470236027123782297108342869049542023328584384300970694412006494684657, + prime1 = 169371138592582642967021557955633494538845517070305333860805485424261447791289944610138334410987654265476540480228705481960508520379619587635662291973699651583489223555422528867090299996446070521801757353675026048850480903160224210802452555900007597342687137394192939372218903554801584969667104937092080815197, + prime2 = 141675062317286527042995673340952251894209529891636708844197799307963834958115010129693036021381525952081167155681637592199810112261679449166276939178032066869788822014115556349519329537177920752776047051833616197615329017439297361972726138285974555338480581117881706656603857310337984049152655480389797687577, + exponent1 = 119556097830058336212015217380447172615655659108450823901745048534772786676204666783627059584226579481512852103690850928442711896738555003036938088452023283470698275450886490965004917644550167427154181661417665446247398284583687678213495921811770068712485038160606780733330990744565824684470897602653233516609, + exponent2 = 41669135975672507953822256864985956439473391144599032012999352737636422046504414744027363535700448809435637398729893409470532385959317485048904982111185902020526124121798693043976273393287623750816484427009887116945685005129205106462566511260580751570141347387612266663707016855981760014456663376585234613993, + coefficient = 76837684977089699359024365285678488693966186052769523357232308621548155587515525857011429902602352279058920284048929101483304120686557782043616693940283344235057989514310975192908256494992960578961614059245280827077951132083993754797053182279229469590276271658395444955906108899267024101096069475145863928441, + otherPrimeInfos = asn1_NOVALUE}; hardcode_rsa_key(2) -> -{'RSAPrivateKey', 'two-prime', - 21343679768589700771839799834197557895311746244621307033143551583788179817796325695589283169969489517156931770973490560582341832744966317712674900833543896521418422508485833901274928542544381247956820115082240721897193055368570146764204557110415281995205343662628196075590438954399631753508888358737971039058298703003743872818150364935790613286541190842600031570570099801682794056444451081563070538409720109449780410837763602317050353477918147758267825417201591905091231778937606362076129350476690460157227101296599527319242747999737801698427160817755293383890373574621116766934110792127739174475029121017282777887777, - 17, - 18832658619343853622211588088997845201745658451136447382185486691577805721584993260814073385267196632785528033211903435807948675951440868570007265441362261636545666919252206383477878125774454042314841278013741813438699754736973658909592256273895837054592950290554290654932740253882028017801960316533503857992358685308186680144968293076156011747178275038098868263178095174694099811498968993700538293188879611375604635940554394589807673542938082281934965292051746326331046224291377703201248790910007232374006151098976879987912446997911775904329728563222485791845480864283470332826504617837402078265424772379987120023773, - 146807662748886761089048448970170315054939768171908279335181627815919052012991509112344782731265837727551849787333310044397991034789843793140419387740928103541736452627413492093463231242466386868459637115999163097726153692593711599245170083315894262154838974616739452594203727376460632750934355508361223110419, - 145385325050081892763917667176962991350872697916072592966410309213561884732628046256782356731057378829876640317801978404203665761131810712267778698468684631707642938779964806354584156202882543264893826268426566901882487709510744074274965029453915224310656287149777603803201831202222853023280023478269485417083, - 51814469205489445090252393754177758254684624060673510353593515699736136004585238510239335081623236845018299924941168250963996835808180162284853901555621683602965806809675350150634081614988136541809283687999704622726877773856604093851236499993845033701707873394143336209718962603456693912094478414715725803677, - 51312467664734785681382706062457526359131540440966797517556579722433606376221663384746714140373192528191755406283051201483646739222992016094510128871300458249756331334105225772206172777487956446433115153562317730076172132768497908567634716277852432109643395464627389577600646306666889302334125933506877206029, - 30504662229874176232343608562807118278893368758027179776313787938167236952567905398252901545019583024374163153775359371298239336609182249464886717948407152570850677549297935773605431024166978281486607154204888016179709037883348099374995148481968169438302456074511782717758301581202874062062542434218011141540, - asn1_NOVALUE}; - + #'RSAPrivateKey'{ + version = 'two-prime', + modulus = 21343679768589700771839799834197557895311746244621307033143551583788179817796325695589283169969489517156931770973490560582341832744966317712674900833543896521418422508485833901274928542544381247956820115082240721897193055368570146764204557110415281995205343662628196075590438954399631753508888358737971039058298703003743872818150364935790613286541190842600031570570099801682794056444451081563070538409720109449780410837763602317050353477918147758267825417201591905091231778937606362076129350476690460157227101296599527319242747999737801698427160817755293383890373574621116766934110792127739174475029121017282777887777, + publicExponent = 17, + privateExponent = 18832658619343853622211588088997845201745658451136447382185486691577805721584993260814073385267196632785528033211903435807948675951440868570007265441362261636545666919252206383477878125774454042314841278013741813438699754736973658909592256273895837054592950290554290654932740253882028017801960316533503857992358685308186680144968293076156011747178275038098868263178095174694099811498968993700538293188879611375604635940554394589807673542938082281934965292051746326331046224291377703201248790910007232374006151098976879987912446997911775904329728563222485791845480864283470332826504617837402078265424772379987120023773, + prime1 = 146807662748886761089048448970170315054939768171908279335181627815919052012991509112344782731265837727551849787333310044397991034789843793140419387740928103541736452627413492093463231242466386868459637115999163097726153692593711599245170083315894262154838974616739452594203727376460632750934355508361223110419, + prime2 = 145385325050081892763917667176962991350872697916072592966410309213561884732628046256782356731057378829876640317801978404203665761131810712267778698468684631707642938779964806354584156202882543264893826268426566901882487709510744074274965029453915224310656287149777603803201831202222853023280023478269485417083, + exponent1 = 51814469205489445090252393754177758254684624060673510353593515699736136004585238510239335081623236845018299924941168250963996835808180162284853901555621683602965806809675350150634081614988136541809283687999704622726877773856604093851236499993845033701707873394143336209718962603456693912094478414715725803677, + exponent2 = 51312467664734785681382706062457526359131540440966797517556579722433606376221663384746714140373192528191755406283051201483646739222992016094510128871300458249756331334105225772206172777487956446433115153562317730076172132768497908567634716277852432109643395464627389577600646306666889302334125933506877206029, + coefficient = 30504662229874176232343608562807118278893368758027179776313787938167236952567905398252901545019583024374163153775359371298239336609182249464886717948407152570850677549297935773605431024166978281486607154204888016179709037883348099374995148481968169438302456074511782717758301581202874062062542434218011141540, + otherPrimeInfos = asn1_NOVALUE}; hardcode_rsa_key(3) -> -{'RSAPrivateKey', 'two-prime', - 25089040456112869869472694987833070928503703615633809313972554887193090845137746668197820419383804666271752525807484521370419854590682661809972833718476098189250708650325307850184923546875260207894844301992963978994451844985784504212035958130279304082438876764367292331581532569155681984449177635856426023931875082020262146075451989132180409962870105455517050416234175675478291534563995772675388370042873175344937421148321291640477650173765084699931690748536036544188863178325887393475703801759010864779559318631816411493486934507417755306337476945299570726975433250753415110141783026008347194577506976486290259135429, - 17, - 8854955455098659953931539407470495621824836570223697404931489960185796768872145882893348383311931058684147950284994536954265831032005645344696294253579799360912014817761873358888796545955974191021709753644575521998041827642041589721895044045980930852625485916835514940558187965584358347452650930302268008446431977397918214293502821599497633970075862760001650736520566952260001423171553461362588848929781360590057040212831994258783694027013289053834376791974167294527043946669963760259975273650548116897900664646809242902841107022557239712438496384819445301703021164043324282687280801738470244471443835900160721870265, - 171641816401041100605063917111691927706183918906535463031548413586331728772311589438043965564336865070070922328258143588739626712299625805650832695450270566547004154065267940032684307994238248203186986569945677705100224518137694769557564475390859269797990555863306972197736879644001860925483629009305104925823, - 146170909759497809922264016492088453282310383272504533061020897155289106805616042710009332510822455269704884883705830985184223718261139908416790475825625309815234508695722132706422885088219618698987115562577878897003573425367881351537506046253616435685549396767356003663417208105346307649599145759863108910523, - 60579464612132153154728441333538327425711971378777222246428851853999433684345266860486105493295364142377972586444050678378691780811632637288529186629507258781295583787741625893888579292084087601124818789392592131211843947578009918667375697196773859928702549128225990187436545756706539150170692591519448797349, - 137572620950115585809189662580789132500998007785886619351549079675566218169991569609420548245479957900898715184664311515467504676010484619686391036071176762179044243478326713135456833024206699951987873470661533079532774988581535389682358631768109586527575902839864474036157372334443583670210960715165278974609, - 15068630434698373319269196003209754243798959461311186548759287649485250508074064775263867418602372588394608558985183294561315208336731894947137343239541687540387209051236354318837334154993136528453613256169847839789803932725339395739618592522865156272771578671216082079933457043120923342632744996962853951612, - asn1_NOVALUE}; + #'RSAPrivateKey'{ + version = 'two-prime', + modulus = 25089040456112869869472694987833070928503703615633809313972554887193090845137746668197820419383804666271752525807484521370419854590682661809972833718476098189250708650325307850184923546875260207894844301992963978994451844985784504212035958130279304082438876764367292331581532569155681984449177635856426023931875082020262146075451989132180409962870105455517050416234175675478291534563995772675388370042873175344937421148321291640477650173765084699931690748536036544188863178325887393475703801759010864779559318631816411493486934507417755306337476945299570726975433250753415110141783026008347194577506976486290259135429, + publicExponent = 17, + privateExponent = 8854955455098659953931539407470495621824836570223697404931489960185796768872145882893348383311931058684147950284994536954265831032005645344696294253579799360912014817761873358888796545955974191021709753644575521998041827642041589721895044045980930852625485916835514940558187965584358347452650930302268008446431977397918214293502821599497633970075862760001650736520566952260001423171553461362588848929781360590057040212831994258783694027013289053834376791974167294527043946669963760259975273650548116897900664646809242902841107022557239712438496384819445301703021164043324282687280801738470244471443835900160721870265, + prime1 = 171641816401041100605063917111691927706183918906535463031548413586331728772311589438043965564336865070070922328258143588739626712299625805650832695450270566547004154065267940032684307994238248203186986569945677705100224518137694769557564475390859269797990555863306972197736879644001860925483629009305104925823, + prime2 =146170909759497809922264016492088453282310383272504533061020897155289106805616042710009332510822455269704884883705830985184223718261139908416790475825625309815234508695722132706422885088219618698987115562577878897003573425367881351537506046253616435685549396767356003663417208105346307649599145759863108910523, + exponent1 = 60579464612132153154728441333538327425711971378777222246428851853999433684345266860486105493295364142377972586444050678378691780811632637288529186629507258781295583787741625893888579292084087601124818789392592131211843947578009918667375697196773859928702549128225990187436545756706539150170692591519448797349, + exponent2 = 137572620950115585809189662580789132500998007785886619351549079675566218169991569609420548245479957900898715184664311515467504676010484619686391036071176762179044243478326713135456833024206699951987873470661533079532774988581535389682358631768109586527575902839864474036157372334443583670210960715165278974609, + coefficient = 15068630434698373319269196003209754243798959461311186548759287649485250508074064775263867418602372588394608558985183294561315208336731894947137343239541687540387209051236354318837334154993136528453613256169847839789803932725339395739618592522865156272771578671216082079933457043120923342632744996962853951612, + otherPrimeInfos = asn1_NOVALUE}; hardcode_rsa_key(4) -> -{'RSAPrivateKey', 'two-prime', - 28617237755030755643854803617273584643843067580642149032833640135949799721163782522787597288521902619948688786051081993247908700824196122780349730169173433743054172191054872553484065655968335396052034378669869864779940355219732200954630251223541048434478476115391643898092650304645086338265930608997389611376417609043761464100338332976874588396803891301015812818307951159858145399281035705713082131199940309445719678087542976246147777388465712394062188801177717719764254900022006288880246925156931391594131839991579403409541227225173269459173129377291869028712271737734702830877034334838181789916127814298794576266389, - 17, - 26933870828264240605980991639786903194205240075898493207372837775011576208154148256741268036255908348187001210401018346586267012540419880263858569570986761169933338532757527109161473558558433313931326474042230460969355628442100895016122589386862163232450330461545076609969553227901257730132640573174013751883368376011370428995523268034111482031427024082719896108094847702954695363285832195666458915142143884210891427766607838346722974883433132513540317964796373298134261669479023445911856492129270184781873446960437310543998533283339488055776892320162032014809906169940882070478200435536171854883284366514852906334641, - 177342190816702392178883147766999616783253285436834252111702533617098994535049411784501174309695427674025956656849179054202187436663487378682303508229883753383891163725167367039879190685255046547908384208614573353917213168937832054054779266431207529839577747601879940934691505396807977946728204814969824442867, - 161367340863680900415977542864139121629424927689088951345472941851682581254789586032968359551717004797621579428672968948552429138154521719743297455351687337112710712475376510559020211584326773715482918387500187602625572442687231345855402020688502483137168684570635690059254866684191216155909970061793538842967, - 62591361464718491357252875682470452982324688977706206627659717747211409835899792394529826226951327414362102349476180842659595565881230839534930649963488383547255704844176717778780890830090016428673547367746320007264898765507470136725216211681602657590439205035957626212244060728285168687080542875871702744541, - 28476589564178982426348978152495139111074987239250991413906989738532220221433456358759122273832412611344984605059935696803369847909621479954699550944415412431654831613301737157474154985469430655673456186029444871051571607533040825739188591886206320553618003159523945304574388238386685203984112363845918619347, - 34340318160575773065401929915821192439103777558577109939078671096408836197675640654693301707202885840826672396546056002756167635035389371579540325327619480512374920136684787633921441576901246290213545161954865184290700344352088099063404416346968182170720521708773285279884132629954461545103181082503707725012, - asn1_NOVALUE}; + #'RSAPrivateKey'{ + version ='two-prime', + modulus = 28617237755030755643854803617273584643843067580642149032833640135949799721163782522787597288521902619948688786051081993247908700824196122780349730169173433743054172191054872553484065655968335396052034378669869864779940355219732200954630251223541048434478476115391643898092650304645086338265930608997389611376417609043761464100338332976874588396803891301015812818307951159858145399281035705713082131199940309445719678087542976246147777388465712394062188801177717719764254900022006288880246925156931391594131839991579403409541227225173269459173129377291869028712271737734702830877034334838181789916127814298794576266389, + publicExponent = 17, + privateExponent = 26933870828264240605980991639786903194205240075898493207372837775011576208154148256741268036255908348187001210401018346586267012540419880263858569570986761169933338532757527109161473558558433313931326474042230460969355628442100895016122589386862163232450330461545076609969553227901257730132640573174013751883368376011370428995523268034111482031427024082719896108094847702954695363285832195666458915142143884210891427766607838346722974883433132513540317964796373298134261669479023445911856492129270184781873446960437310543998533283339488055776892320162032014809906169940882070478200435536171854883284366514852906334641, + prime1 = 177342190816702392178883147766999616783253285436834252111702533617098994535049411784501174309695427674025956656849179054202187436663487378682303508229883753383891163725167367039879190685255046547908384208614573353917213168937832054054779266431207529839577747601879940934691505396807977946728204814969824442867, + prime2 = 161367340863680900415977542864139121629424927689088951345472941851682581254789586032968359551717004797621579428672968948552429138154521719743297455351687337112710712475376510559020211584326773715482918387500187602625572442687231345855402020688502483137168684570635690059254866684191216155909970061793538842967, + exponent1 = 62591361464718491357252875682470452982324688977706206627659717747211409835899792394529826226951327414362102349476180842659595565881230839534930649963488383547255704844176717778780890830090016428673547367746320007264898765507470136725216211681602657590439205035957626212244060728285168687080542875871702744541, + exponent2 = 28476589564178982426348978152495139111074987239250991413906989738532220221433456358759122273832412611344984605059935696803369847909621479954699550944415412431654831613301737157474154985469430655673456186029444871051571607533040825739188591886206320553618003159523945304574388238386685203984112363845918619347, + coefficient = 34340318160575773065401929915821192439103777558577109939078671096408836197675640654693301707202885840826672396546056002756167635035389371579540325327619480512374920136684787633921441576901246290213545161954865184290700344352088099063404416346968182170720521708773285279884132629954461545103181082503707725012, + otherPrimeInfos = asn1_NOVALUE}; + hardcode_rsa_key(5) -> -{'RSAPrivateKey', 'two-prime', - 26363170152814518327068346871197765236382539835597898797762992537312221863402655353436079974302838986536256364057947538018476963115004626096654613827403121905035011992899481598437933532388248462251770039307078647864188314916665766359828262009578648593031111569685489178543405615478739906285223620987558499488359880003693226535420421293716164794046859453204135383236667988765227190694994861629971618548127529849059769249520775574008363789050621665120207265361610436965088511042779948238320901918522125988916609088415989475825860046571847719492980547438560049874493788767083330042728150253120940100665370844282489982633, - 17, - 10855423004100095781734025182257903332628104638187370093196526338893267826106975733767797636477639582691399679317978398007608161282648963686857782164224814902073240232370374775827384395689278778574258251479385325591136364965685903795223402003944149420659869469870495544106108194608892902588033255700759382142132115013969680562678811046675523365751498355532768935784747314021422035957153013494814430893022253205880275287307995039363642554998244274484818208792520243113824379110193356010059999642946040953102866271737127640405568982049887176990990501963784502429481034227543991366980671390566584211881030995602076468001, - 163564135568104310461344551909369650951960301778977149705601170951529791054750122905880591964737953456660497440730575925978769763154927541340839715938951226089095007207042122512586007411328664679011914120351043948122025612160733403945093961374276707993674792189646478659304624413958625254578122842556295400709, - 161179405627326572739107057023381254841260287988433675196680483761672455172873134522398837271764104320975746111042211695289319249471386600030523328069395763313848583139553961129874895374324504709512019736703349829576024049432816885712623938437949550266365056310544300920756181033500610331519029869549723159637, - 115457036871603042678596154288966812436677860079277988027483179495197499568058910286503947269226790675289762899339230065396778656344654735064122152427494983121714122734382674714766593466820233891067233496718383963380253373289929461608301619793607087995535147427985749641862087821617853120878674947686796753441, - 142217122612346975946270932667689342506994371754500301644129838613240401623123353990351915239791856753802128921507833848784693455415929352968108818884760967629866396887841730408713142977345151214275311532385308673155315337734838428569962298621720191411498579097539089047726042088382891468987379296661520434973, - 40624877259097915043489529504071755460170951428490878553842519165800720914888257733191322215286203357356050737713125202129282154441426952501134581314792133018830748896123382106683994268028624341502298766844710276939303555637478596035491641473828661569958212421472263269629366559343208764012473880251174832392, - asn1_NOVALUE}; + #'RSAPrivateKey'{ + version= 'two-prime', + modulus = 26363170152814518327068346871197765236382539835597898797762992537312221863402655353436079974302838986536256364057947538018476963115004626096654613827403121905035011992899481598437933532388248462251770039307078647864188314916665766359828262009578648593031111569685489178543405615478739906285223620987558499488359880003693226535420421293716164794046859453204135383236667988765227190694994861629971618548127529849059769249520775574008363789050621665120207265361610436965088511042779948238320901918522125988916609088415989475825860046571847719492980547438560049874493788767083330042728150253120940100665370844282489982633, + publicExponent = 17, + privateExponent = 10855423004100095781734025182257903332628104638187370093196526338893267826106975733767797636477639582691399679317978398007608161282648963686857782164224814902073240232370374775827384395689278778574258251479385325591136364965685903795223402003944149420659869469870495544106108194608892902588033255700759382142132115013969680562678811046675523365751498355532768935784747314021422035957153013494814430893022253205880275287307995039363642554998244274484818208792520243113824379110193356010059999642946040953102866271737127640405568982049887176990990501963784502429481034227543991366980671390566584211881030995602076468001, + prime1 =163564135568104310461344551909369650951960301778977149705601170951529791054750122905880591964737953456660497440730575925978769763154927541340839715938951226089095007207042122512586007411328664679011914120351043948122025612160733403945093961374276707993674792189646478659304624413958625254578122842556295400709, + prime2 = 161179405627326572739107057023381254841260287988433675196680483761672455172873134522398837271764104320975746111042211695289319249471386600030523328069395763313848583139553961129874895374324504709512019736703349829576024049432816885712623938437949550266365056310544300920756181033500610331519029869549723159637, + exponent1 = 115457036871603042678596154288966812436677860079277988027483179495197499568058910286503947269226790675289762899339230065396778656344654735064122152427494983121714122734382674714766593466820233891067233496718383963380253373289929461608301619793607087995535147427985749641862087821617853120878674947686796753441, + exponent2 = 142217122612346975946270932667689342506994371754500301644129838613240401623123353990351915239791856753802128921507833848784693455415929352968108818884760967629866396887841730408713142977345151214275311532385308673155315337734838428569962298621720191411498579097539089047726042088382891468987379296661520434973, + coefficient = 40624877259097915043489529504071755460170951428490878553842519165800720914888257733191322215286203357356050737713125202129282154441426952501134581314792133018830748896123382106683994268028624341502298766844710276939303555637478596035491641473828661569958212421472263269629366559343208764012473880251174832392, + otherPrimeInfos = asn1_NOVALUE}; hardcode_rsa_key(6) -> -{'RSAPrivateKey', 'two-prime', - 22748888494866396715768692484866595111939200209856056370972713870125588774286266397044592487895293134537316190976192161177144143633669641697309689280475257429554879273045671863645233402796222694405634510241820106743648116753479926387434021380537483429927516962909367257212902212159798399531316965145618774905828756510318897899298783143203190245236381440043169622358239226123652592179006905016804587837199618842875361941208299410035232803124113612082221121192550063791073372276763648926636149384299189072950588522522800393261949880796214514243704858378436010975184294077063518776479282353562934591448646412389762167039, - 17, - 6690849557313646092873144848490175032923294179369428344403739373566349639495960705013115437616262686628622409110644753287395336362844012263914614494257428655751435080307550548130951000822418439531068973600535325512837681398082331290421770994275730420566916753796872722709677121223470117509210872101652580854566448661533030419787125312956120661097410038933324613372774190658239039998357548275441758790939430824924502690997433186652165055694361752689819209062683281242276039100201318203707142383491769671330743466041394101421674581185260900666085723130684175548215193875544802254923825103844262661010117443222587769713, - 164748737139489923768181260808494855987398781964531448608652166632780898215212977127034263859971474195908846263894581556691971503119888726148555271179103885786024920582830105413607436718060544856016793981261118694063993837665813285582095833772675610567592660039821387740255651489996976698808018635344299728063, - 138082323967104548254375818343885141517788525705334488282154811252858957969378263753268344088034079842223206527922445018725900110643394926788280539200323021781309918753249061620424428562366627334409266756720941754364262467100514166396917565961434203543659974860389803369482625510495464845206228470088664021953, - 19382204369351755737433089506881747763223386113474288071606137250915399790025056132592266336467232258342217207517009594904937823896457497193947678962247515974826461245038835931012639613889475865413740468383661022831058098548919210068481862796785365949128548239978986792971253116470232552800943368864035262125, - 48734937870742781736838524121371226418043009072470995864289933383361985165662916618800592031070851709019955245149098241903258862580021738866451955011878713569874088971734962924855680669070574353320917678842685325069739694270769705787147376221682660074232932303666989424523279591939575827719845342384234360689, - 81173034184183681160439870161505779100040258708276674532866007896310418779840630960490793104541748007902477778658270784073595697910785917474138815202903114440800310078464142273778315781957021015333260021813037604142367434117205299831740956310682461174553260184078272196958146289378701001596552915990080834227, - asn1_NOVALUE}. + #'RSAPrivateKey'{ + version = 'two-prime', + modulus = 22748888494866396715768692484866595111939200209856056370972713870125588774286266397044592487895293134537316190976192161177144143633669641697309689280475257429554879273045671863645233402796222694405634510241820106743648116753479926387434021380537483429927516962909367257212902212159798399531316965145618774905828756510318897899298783143203190245236381440043169622358239226123652592179006905016804587837199618842875361941208299410035232803124113612082221121192550063791073372276763648926636149384299189072950588522522800393261949880796214514243704858378436010975184294077063518776479282353562934591448646412389762167039, + publicExponent = 17, + privateExponent = 6690849557313646092873144848490175032923294179369428344403739373566349639495960705013115437616262686628622409110644753287395336362844012263914614494257428655751435080307550548130951000822418439531068973600535325512837681398082331290421770994275730420566916753796872722709677121223470117509210872101652580854566448661533030419787125312956120661097410038933324613372774190658239039998357548275441758790939430824924502690997433186652165055694361752689819209062683281242276039100201318203707142383491769671330743466041394101421674581185260900666085723130684175548215193875544802254923825103844262661010117443222587769713, + prime1 = 164748737139489923768181260808494855987398781964531448608652166632780898215212977127034263859971474195908846263894581556691971503119888726148555271179103885786024920582830105413607436718060544856016793981261118694063993837665813285582095833772675610567592660039821387740255651489996976698808018635344299728063, + prime2 = 138082323967104548254375818343885141517788525705334488282154811252858957969378263753268344088034079842223206527922445018725900110643394926788280539200323021781309918753249061620424428562366627334409266756720941754364262467100514166396917565961434203543659974860389803369482625510495464845206228470088664021953, + exponent1 = 19382204369351755737433089506881747763223386113474288071606137250915399790025056132592266336467232258342217207517009594904937823896457497193947678962247515974826461245038835931012639613889475865413740468383661022831058098548919210068481862796785365949128548239978986792971253116470232552800943368864035262125, + exponent2 = 48734937870742781736838524121371226418043009072470995864289933383361985165662916618800592031070851709019955245149098241903258862580021738866451955011878713569874088971734962924855680669070574353320917678842685325069739694270769705787147376221682660074232932303666989424523279591939575827719845342384234360689, + coefficient = 81173034184183681160439870161505779100040258708276674532866007896310418779840630960490793104541748007902477778658270784073595697910785917474138815202903114440800310078464142273778315781957021015333260021813037604142367434117205299831740956310682461174553260184078272196958146289378701001596552915990080834227, + otherPrimeInfos = asn1_NOVALUE}. hardcode_dsa_key(1) -> {'DSAPrivateKey',0, @@ -1585,19 +1642,21 @@ hardcode_dsa_key(1) -> 48598545580251057979126570873881530215432219542526130654707948736559463436274835406081281466091739849794036308281564299754438126857606949027748889019480936572605967021944405048011118039171039273602705998112739400664375208228641666852589396502386172780433510070337359132965412405544709871654840859752776060358, 1457508827177594730669011716588605181448418352823}; hardcode_dsa_key(2) -> - {'DSAPrivateKey',0, - 145447354557382582722944332987784622105075065624518040072393858097520305927329240484963764783346271194321683798321743658303478090647837211867389721684646254999291098347011037298359107547264573476540026676832159205689428125157386525591130716464335426605521884822982379206842523670736739023467072341958074788151, - 742801637799670234315651916144768554943688916729, - 79727684678125120155622004643594683941478642656111969487719464672433839064387954070113655822700268007902716505761008423792735229036965034283173483862273639257533568978482104785033927768441235063983341565088899599358397638308472931049309161811156189887217888328371767967629005149630676763492409067382020352505, - 35853727034965131665219275925554159789667905059030049940938124723126925435403746979702929280654735557166864135215989313820464108440192507913554896358611966877432546584986661291483639036057475682547385322659469460385785257933737832719745145778223672383438466035853830832837226950912832515496378486927322864228, - 801315110178350279541885862867982846569980443911}; + #'DSAPrivateKey'{ + version = 0, + p = 145447354557382582722944332987784622105075065624518040072393858097520305927329240484963764783346271194321683798321743658303478090647837211867389721684646254999291098347011037298359107547264573476540026676832159205689428125157386525591130716464335426605521884822982379206842523670736739023467072341958074788151, + q = 742801637799670234315651916144768554943688916729, + g = 79727684678125120155622004643594683941478642656111969487719464672433839064387954070113655822700268007902716505761008423792735229036965034283173483862273639257533568978482104785033927768441235063983341565088899599358397638308472931049309161811156189887217888328371767967629005149630676763492409067382020352505, + y = 35853727034965131665219275925554159789667905059030049940938124723126925435403746979702929280654735557166864135215989313820464108440192507913554896358611966877432546584986661291483639036057475682547385322659469460385785257933737832719745145778223672383438466035853830832837226950912832515496378486927322864228, + x = 801315110178350279541885862867982846569980443911}; hardcode_dsa_key(3) -> - {'DSAPrivateKey',0, - 99438313664986922963487511141216248076486724382260996073922424025828494981416579966171753999204426907349400798052572573634137057487829150578821328280864500098312146772602202702021153757550650696224643730869835650674962433068943942837519621267815961566259265204876799778977478160416743037274938277357237615491, - 1454908511695148818053325447108751926908854531909, - 20302424198893709525243209250470907105157816851043773596964076323184805650258390738340248469444700378962907756890306095615785481696522324901068493502141775433048117442554163252381401915027666416630898618301033737438756165023568220631119672502120011809327566543827706483229480417066316015458225612363927682579, - 48598545580251057979126570873881530215432219542526130654707948736559463436274835406081281466091739849794036308281564299754438126857606949027748889019480936572605967021944405048011118039171039273602705998112739400664375208228641666852589396502386172780433510070337359132965412405544709871654840859752776060358, - 1457508827177594730669011716588605181448418352823}. + #'DSAPrivateKey'{ + version = 0, + p = 99438313664986922963487511141216248076486724382260996073922424025828494981416579966171753999204426907349400798052572573634137057487829150578821328280864500098312146772602202702021153757550650696224643730869835650674962433068943942837519621267815961566259265204876799778977478160416743037274938277357237615491, + q = 1454908511695148818053325447108751926908854531909, + g = 20302424198893709525243209250470907105157816851043773596964076323184805650258390738340248469444700378962907756890306095615785481696522324901068493502141775433048117442554163252381401915027666416630898618301033737438756165023568220631119672502120011809327566543827706483229480417066316015458225612363927682579, + y = 48598545580251057979126570873881530215432219542526130654707948736559463436274835406081281466091739849794036308281564299754438126857606949027748889019480936572605967021944405048011118039171039273602705998112739400664375208228641666852589396502386172780433510070337359132965412405544709871654840859752776060358, + x = 1457508827177594730669011716588605181448418352823}. dtls_hello() -> [1, diff --git a/lib/ssl/test/x509_test.erl b/lib/ssl/test/x509_test.erl index 4da1537ef6..031fad1216 100644 --- a/lib/ssl/test/x509_test.erl +++ b/lib/ssl/test/x509_test.erl @@ -24,23 +24,10 @@ -include_lib("public_key/include/public_key.hrl"). - -export([gen_test_certs/1, gen_pem_config_files/3]). +-export([extensions/1, gen_pem_config_files/3]). - gen_test_certs(Opts) -> - SRootKey = gen_key(proplists:get_value(server_key_gen, Opts)), - CRootKey = gen_key(proplists:get_value(client_key_gen, Opts)), - ServerRoot = root_cert("server", SRootKey, Opts), - ClientRoot = root_cert("client", CRootKey, Opts), - [{ServerCert, ServerKey} | ServerCAsKeys] = config(server, ServerRoot, SRootKey, Opts), - [{ClientCert, ClientKey} | ClientCAsKeys] = config(client, ClientRoot, CRootKey, Opts), - ServerCAs = ca_config(ClientRoot, ServerCAsKeys), - ClientCAs = ca_config(ServerRoot, ClientCAsKeys), - [{server_config, [{cert, ServerCert}, {key, ServerKey}, {cacerts, ServerCAs}]}, - {client_config, [{cert, ClientCert}, {key, ClientKey}, {cacerts, ClientCAs}]}]. - -gen_pem_config_files(GenCertData, ClientBase, ServerBase) -> - ServerConf = proplists:get_value(server_config, GenCertData), - ClientConf = proplists:get_value(client_config, GenCertData), +gen_pem_config_files(#{server_config := ServerConf, + client_config := ClientConf}, ClientBase, ServerBase) -> ServerCaCertFile = ServerBase ++ "_server_cacerts.pem", ServerCertFile = ServerBase ++ "_server_cert.pem", @@ -62,147 +49,33 @@ gen_pem_config_files(GenCertData, ClientBase, ServerBase) -> {keyfile, ServerKeyFile}, {cacertfile, ServerCaCertFile}]}, {client_config, [{certfile, ClientCertFile}, {keyfile, ClientKeyFile}, {cacertfile, ClientCaCertFile}]}]. - - - do_gen_pem_config_files(Config, CertFile, KeyFile, CAFile) -> - CAs = proplists:get_value(cacerts, Config), - Cert = proplists:get_value(cert, Config), - Key = proplists:get_value(key, Config), - der_to_pem(CertFile, [cert_entry(Cert)]), - der_to_pem(KeyFile, [key_entry(Key)]), - der_to_pem(CAFile, ca_entries(CAs)). - - cert_entry(Cert) -> - {'Certificate', Cert, not_encrypted}. - - key_entry(Key = #'RSAPrivateKey'{}) -> - Der = public_key:der_encode('RSAPrivateKey', Key), - {'RSAPrivateKey', Der, not_encrypted}; - key_entry(Key = #'DSAPrivateKey'{}) -> - Der = public_key:der_encode('DSAPrivateKey', Key), - {'DSAPrivateKey', Der, not_encrypted}; - key_entry(Key = #'ECPrivateKey'{}) -> - Der = public_key:der_encode('ECPrivateKey', Key), - {'ECPrivateKey', Der, not_encrypted}. - - ca_entries(CAs) -> - [{'Certificate', CACert, not_encrypted} || CACert <- CAs]. - - gen_key(KeyGen) -> - case is_key(KeyGen) of - true -> - KeyGen; - false -> - public_key:generate_key(KeyGen) - end. - -root_cert(Role, PrivKey, Opts) -> - TBS = cert_template(), - Issuer = issuer("root", Role, " ROOT CA"), - OTPTBS = TBS#'OTPTBSCertificate'{ - signature = sign_algorithm(PrivKey, Opts), - issuer = Issuer, - validity = validity(Opts), - subject = Issuer, - subjectPublicKeyInfo = public_key(PrivKey), - extensions = extensions(Role, ca, Opts) - }, - public_key:pkix_sign(OTPTBS, PrivKey). - -config(Role, Root, Key, Opts) -> - KeyGenOpt = list_to_atom(atom_to_list(Role) ++ "_key_gen_chain"), - KeyGens = proplists:get_value(KeyGenOpt, Opts, default_key_gen()), - Keys = lists:map(fun gen_key/1, KeyGens), - cert_chain(Role, Root, Key, Opts, Keys). - -cert_template() -> - #'OTPTBSCertificate'{ - version = v3, - serialNumber = trunc(rand:uniform()*100000000)*10000 + 1, - issuerUniqueID = asn1_NOVALUE, - subjectUniqueID = asn1_NOVALUE - }. - -issuer(Contact, Role, Name) -> - subject(Contact, Role ++ Name). - -subject(Contact, Name) -> - Opts = [{email, Contact ++ "@erlang.org"}, - {name, Name}, - {city, "Stockholm"}, - {country, "SE"}, - {org, "erlang"}, - {org_unit, "automated testing"}], - subject(Opts). - -subject(SubjectOpts) when is_list(SubjectOpts) -> - Encode = fun(Opt) -> - {Type,Value} = subject_enc(Opt), - [#'AttributeTypeAndValue'{type=Type, value=Value}] - end, - {rdnSequence, [Encode(Opt) || Opt <- SubjectOpts]}. - -subject_enc({name, Name}) -> - {?'id-at-commonName', {printableString, Name}}; -subject_enc({email, Email}) -> - {?'id-emailAddress', Email}; -subject_enc({city, City}) -> - {?'id-at-localityName', {printableString, City}}; -subject_enc({state, State}) -> - {?'id-at-stateOrProvinceName', {printableString, State}}; -subject_enc({org, Org}) -> - {?'id-at-organizationName', {printableString, Org}}; -subject_enc({org_unit, OrgUnit}) -> - {?'id-at-organizationalUnitName', {printableString, OrgUnit}}; -subject_enc({country, Country}) -> - {?'id-at-countryName', Country}; -subject_enc({serial, Serial}) -> - {?'id-at-serialNumber', Serial}; -subject_enc({title, Title}) -> - {?'id-at-title', {printableString, Title}}; -subject_enc({dnQualifer, DnQ}) -> - {?'id-at-dnQualifier', DnQ}; -subject_enc(Other) -> - Other. - -validity(Opts) -> - DefFrom0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())-1), - DefTo0 = calendar:gregorian_days_to_date(calendar:date_to_gregorian_days(date())+7), - {DefFrom, DefTo} = proplists:get_value(validity, Opts, {DefFrom0, DefTo0}), - Format = fun({Y,M,D}) -> - lists:flatten(io_lib:format("~w~2..0w~2..0w000000Z",[Y,M,D])) - end, - #'Validity'{notBefore={generalTime, Format(DefFrom)}, - notAfter ={generalTime, Format(DefTo)}}. - -extensions(Role, Type, Opts) -> - Exts = proplists:get_value(extensions, Opts, []), - lists:flatten([extension(Ext) || Ext <- default_extensions(Role, Type, Exts)]). - -%% Common extension: name_constraints, policy_constraints, ext_key_usage, inhibit_any, -%% auth_key_id, subject_key_id, policy_mapping, - -default_extensions(_, ca, Exts) -> - Def = [{key_usage, [keyCertSign, cRLSign]}, - {basic_constraints, default}], - add_default_extensions(Def, Exts); - -default_extensions(server, peer, Exts) -> - Hostname = net_adm:localhost(), - Def = [{key_usage, [digitalSignature, keyAgreement]}, - {subject_alt, Hostname}], - add_default_extensions(Def, Exts); - -default_extensions(_, peer, Exts) -> - Exts. - -add_default_extensions(Def, Exts) -> - Filter = fun({Key, _}, D) -> - lists:keydelete(Key, 1, D); - ({Key, _, _}, D) -> - lists:keydelete(Key, 1, D) - end, - Exts ++ lists:foldl(Filter, Def, Exts). +extensions(Exts) -> + [extension(Ext) || Ext <- Exts]. + + +do_gen_pem_config_files(Config, CertFile, KeyFile, CAFile) -> + CAs = proplists:get_value(cacerts, Config), + Cert = proplists:get_value(cert, Config), + Key = proplists:get_value(key, Config), + der_to_pem(CertFile, [cert_entry(Cert)]), + der_to_pem(KeyFile, [key_entry(Key)]), + der_to_pem(CAFile, ca_entries(CAs)). + +cert_entry(Cert) -> + {'Certificate', Cert, not_encrypted}. + +key_entry(Key = #'RSAPrivateKey'{}) -> + Der = public_key:der_encode('RSAPrivateKey', Key), + {'RSAPrivateKey', Der, not_encrypted}; +key_entry(Key = #'DSAPrivateKey'{}) -> + Der = public_key:der_encode('DSAPrivateKey', Key), + {'DSAPrivateKey', Der, not_encrypted}; +key_entry(Key = #'ECPrivateKey'{}) -> + Der = public_key:der_encode('ECPrivateKey', Key), + {'ECPrivateKey', Der, not_encrypted}. + +ca_entries(CAs) -> + [{'Certificate', CACert, not_encrypted} || CACert <- CAs]. extension({_, undefined}) -> []; @@ -222,13 +95,6 @@ extension({basic_constraints, Data}) -> #'Extension'{extnID = ?'id-ce-basicConstraints', extnValue = Data} end; -extension({auth_key_id, {Oid, Issuer, SNr}}) -> - #'Extension'{extnID = ?'id-ce-authorityKeyIdentifier', - extnValue = #'AuthorityKeyIdentifier'{ - keyIdentifier = Oid, - authorityCertIssuer = Issuer, - authorityCertSerialNumber = SNr}, - critical = false}; extension({key_usage, Value}) -> #'Extension'{extnID = ?'id-ce-keyUsage', extnValue = Value, @@ -240,113 +106,6 @@ extension({subject_alt, Hostname}) -> extension({Id, Data, Critical}) -> #'Extension'{extnID = Id, extnValue = Data, critical = Critical}. -public_key(#'RSAPrivateKey'{modulus=N, publicExponent=E}) -> - Public = #'RSAPublicKey'{modulus=N, publicExponent=E}, - Algo = #'PublicKeyAlgorithm'{algorithm= ?rsaEncryption, parameters='NULL'}, - #'OTPSubjectPublicKeyInfo'{algorithm = Algo, - subjectPublicKey = Public}; -public_key(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) -> - Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa', - parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}}, - #'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y}; -public_key(#'ECPrivateKey'{version = _Version, - privateKey = _PrivKey, - parameters = Params, - publicKey = PubKey}) -> - Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-ecPublicKey', parameters=Params}, - #'OTPSubjectPublicKeyInfo'{algorithm = Algo, - subjectPublicKey = #'ECPoint'{point = PubKey}}. - -sign_algorithm(#'RSAPrivateKey'{}, Opts) -> - Type = rsa_digest_oid(proplists:get_value(digest, Opts, sha1)), - #'SignatureAlgorithm'{algorithm = Type, - parameters = 'NULL'}; -sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) -> - #'SignatureAlgorithm'{algorithm = ?'id-dsa-with-sha1', - parameters = {params,#'Dss-Parms'{p=P, q=Q, g=G}}}; -sign_algorithm(#'ECPrivateKey'{parameters = Parms}, Opts) -> - Type = ecdsa_digest_oid(proplists:get_value(digest, Opts, sha1)), - #'SignatureAlgorithm'{algorithm = Type, - parameters = Parms}. - -rsa_digest_oid(sha1) -> - ?'sha1WithRSAEncryption'; -rsa_digest_oid(sha512) -> - ?'sha512WithRSAEncryption'; -rsa_digest_oid(sha384) -> - ?'sha384WithRSAEncryption'; -rsa_digest_oid(sha256) -> - ?'sha256WithRSAEncryption'; -rsa_digest_oid(md5) -> - ?'md5WithRSAEncryption'. - -ecdsa_digest_oid(sha1) -> - ?'ecdsa-with-SHA1'; -ecdsa_digest_oid(sha512) -> - ?'ecdsa-with-SHA512'; -ecdsa_digest_oid(sha384) -> - ?'ecdsa-with-SHA384'; -ecdsa_digest_oid(sha256) -> - ?'ecdsa-with-SHA256'. - -ca_config(Root, CAsKeys) -> - [Root | [CA || {CA, _} <- CAsKeys]]. - -cert_chain(Role, Root, RootKey, Opts, Keys) -> - cert_chain(Role, Root, RootKey, Opts, Keys, 0, []). - -cert_chain(Role, IssuerCert, IssuerKey, Opts, [Key], _, Acc) -> - PeerOpts = list_to_atom(atom_to_list(Role) ++ "_peer_opts"), - Cert = cert(Role, public_key:pkix_decode_cert(IssuerCert, otp), - IssuerKey, Key, "admin", " Peer cert", Opts, PeerOpts, peer), - [{Cert, Key}, {IssuerCert, IssuerKey} | Acc]; -cert_chain(Role, IssuerCert, IssuerKey, Opts, [Key | Keys], N, Acc) -> - CAOpts = list_to_atom(atom_to_list(Role) ++ "_ca_" ++ integer_to_list(N)), - Cert = cert(Role, public_key:pkix_decode_cert(IssuerCert, otp), IssuerKey, Key, "webadmin", - " Intermidiate CA " ++ integer_to_list(N), Opts, CAOpts, ca), - cert_chain(Role, Cert, Key, Opts, Keys, N+1, [{IssuerCert, IssuerKey} | Acc]). - -cert(Role, #'OTPCertificate'{tbsCertificate = #'OTPTBSCertificate'{subject = Issuer, - serialNumber = SNr - }}, - PrivKey, Key, Contact, Name, Opts, CertOptsName, Type) -> - CertOpts = proplists:get_value(CertOptsName, Opts, []), - TBS = cert_template(), - OTPTBS = TBS#'OTPTBSCertificate'{ - signature = sign_algorithm(PrivKey, Opts), - issuer = Issuer, - validity = validity(CertOpts), - subject = subject(Contact, atom_to_list(Role) ++ Name), - subjectPublicKeyInfo = public_key(Key), - extensions = extensions(Role, Type, - add_default_extensions([{auth_key_id, {auth_key_oid(Role), Issuer, SNr}}], - CertOpts)) - }, - public_key:pkix_sign(OTPTBS, PrivKey). - -is_key(#'DSAPrivateKey'{}) -> - true; -is_key(#'RSAPrivateKey'{}) -> - true; -is_key(#'ECPrivateKey'{}) -> - true; -is_key(_) -> - false. - der_to_pem(File, Entries) -> PemBin = public_key:pem_encode(Entries), file:write_file(File, PemBin). - -default_key_gen() -> - case tls_v1:ecc_curves(0) of - [] -> - [{rsa, 2048, 17}, {rsa, 2048, 17}]; - [_|_] -> - [{namedCurve, hd(tls_v1:ecc_curves(0))}, - {namedCurve, hd(tls_v1:ecc_curves(0))}] - end. - -auth_key_oid(server) -> - ?'id-kp-serverAuth'; -auth_key_oid(client) -> - ?'id-kp-clientAuth'. diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index 25b2a2bec0..bb77326751 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -1 +1 @@ -SSL_VSN = 8.2 +SSL_VSN = 8.2.1 diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml index 95af2b77a5..576959b1c8 100644 --- a/lib/stdlib/doc/src/ets.xml +++ b/lib/stdlib/doc/src/ets.xml @@ -325,7 +325,7 @@ <p><c><anno>Acc0</anno></c> is returned if the table is empty. This function is similar to <seealso marker="lists#foldl/3"><c>lists:foldl/3</c></seealso>. - The table elements are traversed is unspecified order, except for + The table elements are traversed in an unspecified order, except for <c>ordered_set</c> tables, where they are traversed first to last.</p> <p>If <c><anno>Function</anno></c> inserts objects into the table, or another @@ -341,7 +341,7 @@ <p><c><anno>Acc0</anno></c> is returned if the table is empty. This function is similar to <seealso marker="lists#foldr/3"><c>lists:foldr/3</c></seealso>. - The table elements are traversed is unspecified order, except for + The table elements are traversed in an unspecified order, except for <c>ordered_set</c> tables, where they are traversed last to first.</p> <p>If <c><anno>Function</anno></c> inserts objects into the table, or another diff --git a/lib/stdlib/doc/src/notes.xml b/lib/stdlib/doc/src/notes.xml index 604d758db3..d396f1de8f 100644 --- a/lib/stdlib/doc/src/notes.xml +++ b/lib/stdlib/doc/src/notes.xml @@ -31,6 +31,56 @@ </header> <p>This document describes the changes made to the STDLIB application.</p> +<section><title>STDLIB 3.4.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> Fix a bug in the Erlang shell where recursively + defined records with typed fields could cause a loop. + </p> + <p> + Own Id: OTP-14488 Aux Id: PR-1489 </p> + </item> + <item> + <p> + Make edlin handle grapheme clusters instead of codepoints + to improve the handling multi-codepoints characters.</p> + <p> + Own Id: OTP-14542</p> + </item> + <item> + <p>There could be false warnings for + <c>erlang:get_stacktrace/0</c> being used outside of a + <c>try</c> block when using multiple <c>catch</c> + clauses.</p> + <p> + Own Id: OTP-14600 Aux Id: ERL-478 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> The Erlang code linter no longer checks that the + functions mentioned in <c>nowarn_deprecated_function</c> + options are declared in the module. </p> + <p> + Own Id: OTP-14378</p> + </item> + <item> + <p> + General Unicode improvements.</p> + <p> + Own Id: OTP-14462</p> + </item> + </list> + </section> + +</section> + <section><title>STDLIB 3.4.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/stdlib/doc/src/rand.xml b/lib/stdlib/doc/src/rand.xml index a68fb7d55f..89fb858823 100644 --- a/lib/stdlib/doc/src/rand.xml +++ b/lib/stdlib/doc/src/rand.xml @@ -35,12 +35,19 @@ <module>rand</module> <modulesummary>Pseudo random number generation.</modulesummary> <description> - <p>This module provides a random number generator. The module contains - a number of algorithms. The uniform distribution algorithms use the - <url href="http://xorshift.di.unimi.it">scrambled Xorshift algorithms by - Sebastiano Vigna</url>. The normal distribution algorithm uses the - <url href="http://www.jstatsoft.org/v05/i08">Ziggurat Method by Marsaglia - and Tsang</url>.</p> + <p> + This module provides a pseudo random number generator. + The module contains a number of algorithms. + The uniform distribution algorithms use the + <url href="http://xorshift.di.unimi.it"> + xoroshiro116+ and xorshift1024* algorithms by Sebastiano Vigna. + </url> + The normal distribution algorithm uses the + <url href="http://www.jstatsoft.org/v05/i08"> + Ziggurat Method by Marsaglia and Tsang + </url> + on top of the uniform distribution algorithm. + </p> <p>For some algorithms, jump functions are provided for generating non-overlapping sequences for parallel computations. The jump functions perform calculations @@ -393,9 +400,34 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre> <name name="uniform" arity="0"/> <fsummary>Return a random float.</fsummary> <desc><marker id="uniform-0"/> - <p>Returns a random float uniformly distributed in the value + <p> + Returns a random float uniformly distributed in the value range <c>0.0 =< <anno>X</anno> < 1.0</c> and - updates the state in the process dictionary.</p> + updates the state in the process dictionary. + </p> + <p> + The generated numbers are on the form N * 2.0^(-53), + that is; equally spaced in the interval. + </p> + <warning> + <p> + This function may return exactly <c>0.0</c> which can be + fatal for certain applications. If that is undesired + you can use <c>(1.0 - rand:uniform())</c> to get the + interval <c>0.0 < <anno>X</anno> =< 1.0</c>. + </p> + <p> + If neither endpoint is desired you can test and re-try + like this: + </p> + <pre> +my_uniform() -> + case rand:uniform() of + 0.0 -> my_uniform(); + X -> X + end +end.</pre> + </warning> </desc> </func> @@ -414,9 +446,34 @@ tests. We suggest to use a sign test to extract a random Boolean value.</pre> <name name="uniform_s" arity="1"/> <fsummary>Return a random float.</fsummary> <desc> - <p>Returns, for a specified state, random float + <p> + Returns, for a specified state, random float uniformly distributed in the value range <c>0.0 =< - <anno>X</anno> < 1.0</c> and a new state.</p> + <anno>X</anno> < 1.0</c> and a new state. + </p> + <p> + The generated numbers are on the form N * 2.0^(-53), + that is; equally spaced in the interval. + </p> + <warning> + <p> + This function may return exactly <c>0.0</c> which can be + fatal for certain applications. If that is undesired + you can use <c>(1.0 - rand:uniform(State))</c> to get the + interval <c>0.0 < <anno>X</anno> =< 1.0</c>. + </p> + <p> + If neither endpoint is desired you can test and re-try + like this: + </p> + <pre> +my_uniform(State) -> + case rand:uniform(State) of + {0.0, NewState} -> my_uniform(NewState); + Result -> Result + end +end.</pre> + </warning> </desc> </func> diff --git a/lib/stdlib/doc/src/string.xml b/lib/stdlib/doc/src/string.xml index 9d5edd9ecf..130fc74a28 100644 --- a/lib/stdlib/doc/src/string.xml +++ b/lib/stdlib/doc/src/string.xml @@ -109,10 +109,8 @@ <p>This module has been reworked in Erlang/OTP 20 to handle <seealso marker="unicode#type-chardata"> <c>unicode:chardata()</c></seealso> and operate on grapheme - clusters. The <seealso marker="#oldapi"> <c>old - functions</c></seealso> that only work on Latin-1 lists as input - are still available but should not be - used. They will be deprecated in Erlang/OTP 21. + clusters. The <c>old functions</c> that only work on Latin-1 lists as input + are kept for backwards compatibility reasons but should not be used. </p> </description> @@ -594,7 +592,7 @@ ÖÄÅ</pre> or <c>both</c>, indicates from which direction characters are to be removed. </p> - <p> Default <c><anno>Characters</anno></c> are the set of + <p> Default <c><anno>Characters</anno></c> is the set of nonbreakable whitespace codepoints, defined as Pattern_White_Space in <url href="http://unicode.org/reports/tr31/">Unicode Standard Annex #31</url>. @@ -631,393 +629,5 @@ ÖÄÅ</pre> </func> </funcs> - - <section> - <marker id="oldapi"/> - <title>Obsolete API functions</title> - <p>Here follows the function of the old API. - These functions only work on a list of Latin-1 characters. - </p> - <note><p> - The functions are kept for backward compatibility, but are - not recommended. - They will be deprecated in Erlang/OTP 21. - </p> - <p>Any undocumented functions in <c>string</c> are not to be used.</p> - </note> - </section> - - <funcs> - <func> - <name name="centre" arity="2"/> - <name name="centre" arity="3"/> - <fsummary>Center a string.</fsummary> - <desc> - <p>Returns a string, where <c><anno>String</anno></c> is centered in the - string and surrounded by blanks or <c><anno>Character</anno></c>. - The resulting string has length <c><anno>Number</anno></c>.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="#pad/3"><c>pad/3</c></seealso>. - </p> - </desc> - </func> - - <func> - <name name="chars" arity="2"/> - <name name="chars" arity="3"/> - <fsummary>Return a string consisting of numbers of characters.</fsummary> - <desc> - <p>Returns a string consisting of <c><anno>Number</anno></c> characters - <c><anno>Character</anno></c>. Optionally, the string can end with - string <c><anno>Tail</anno></c>.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="lists#duplicate/2"><c>lists:duplicate/2</c></seealso>.</p> - </desc> - </func> - - <func> - <name name="chr" arity="2"/> - <fsummary>Return the index of the first occurrence of - a character in a string.</fsummary> - <desc> - <p>Returns the index of the first occurrence of - <c><anno>Character</anno></c> in <c><anno>String</anno></c>. Returns - <c>0</c> if <c><anno>Character</anno></c> does not occur.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="#find/2"><c>find/2</c></seealso>.</p> - </desc> - </func> - - <func> - <name name="concat" arity="2"/> - <fsummary>Concatenate two strings.</fsummary> - <desc> - <p>Concatenates <c><anno>String1</anno></c> and - <c><anno>String2</anno></c> to form a new string - <c><anno>String3</anno></c>, which is returned.</p> - <p> - This function is <seealso marker="#oldapi">obsolete</seealso>. - Use <c>[<anno>String1</anno>, <anno>String2</anno>]</c> as - <c>Data</c> argument, and call - <seealso marker="unicode#characters_to_list/2"> - <c>unicode:characters_to_list/2</c></seealso> or - <seealso marker="unicode#characters_to_binary/2"> - <c>unicode:characters_to_binary/2</c></seealso> - to flatten the output. - </p> - </desc> - </func> - - <func> - <name name="copies" arity="2"/> - <fsummary>Copy a string.</fsummary> - <desc> - <p>Returns a string containing <c><anno>String</anno></c> repeated - <c><anno>Number</anno></c> times.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="lists#duplicate/2"><c>lists:duplicate/2</c></seealso>.</p> - </desc> - </func> - - <func> - <name name="cspan" arity="2"/> - <fsummary>Span characters at start of a string.</fsummary> - <desc> - <p>Returns the length of the maximum initial segment of - <c><anno>String</anno></c>, which consists entirely of characters - not from <c><anno>Chars</anno></c>.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="#take/3"><c>take/3</c></seealso>.</p> - <p><em>Example:</em></p> - <code type="none"> -> string:cspan("\t abcdef", " \t"). -0</code> - </desc> - </func> - - <func> - <name name="join" arity="2"/> - <fsummary>Join a list of strings with separator.</fsummary> - <desc> - <p>Returns a string with the elements of <c><anno>StringList</anno></c> - separated by the string in <c><anno>Separator</anno></c>.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="lists#join/2"><c>lists:join/2</c></seealso>.</p> - <p><em>Example:</em></p> - <code type="none"> -> join(["one", "two", "three"], ", "). -"one, two, three"</code> - </desc> - </func> - - <func> - <name name="left" arity="2"/> - <name name="left" arity="3"/> - <fsummary>Adjust left end of a string.</fsummary> - <desc> - <p>Returns <c><anno>String</anno></c> with the length adjusted in - accordance with <c><anno>Number</anno></c>. The left margin is - fixed. If <c>length(<anno>String</anno>)</c> < - <c><anno>Number</anno></c>, then <c><anno>String</anno></c> is padded - with blanks or <c><anno>Character</anno></c>s.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="#pad/2"><c>pad/2</c></seealso> or - <seealso marker="#pad/3"><c>pad/3</c></seealso>.</p> - <p><em>Example:</em></p> - <code type="none"> -> string:left("Hello",10,$.). -"Hello....."</code> - </desc> - </func> - - <func> - <name name="len" arity="1"/> - <fsummary>Return the length of a string.</fsummary> - <desc> - <p>Returns the number of characters in <c><anno>String</anno></c>.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="#length/1"><c>length/1</c></seealso>.</p> - </desc> - </func> - - <func> - <name name="rchr" arity="2"/> - <fsummary>Return the index of the last occurrence of - a character in a string.</fsummary> - <desc> - <p>Returns the index of the last occurrence of - <c><anno>Character</anno></c> in <c><anno>String</anno></c>. Returns - <c>0</c> if <c><anno>Character</anno></c> does not occur.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="#find/3"><c>find/3</c></seealso>.</p> - </desc> - </func> - - <func> - <name name="right" arity="2"/> - <name name="right" arity="3"/> - <fsummary>Adjust right end of a string.</fsummary> - <desc> - <p>Returns <c><anno>String</anno></c> with the length adjusted in - accordance with <c><anno>Number</anno></c>. The right margin is - fixed. If the length of <c>(<anno>String</anno>)</c> < - <c><anno>Number</anno></c>, then <c><anno>String</anno></c> is padded - with blanks or <c><anno>Character</anno></c>s.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="#pad/3"><c>pad/3</c></seealso>.</p> - <p><em>Example:</em></p> - <code type="none"> -> string:right("Hello", 10, $.). -".....Hello"</code> - </desc> - </func> - - <func> - <name name="rstr" arity="2"/> - <fsummary>Find the index of a substring.</fsummary> - <desc> - <p>Returns the position where the last occurrence of - <c><anno>SubString</anno></c> begins in <c><anno>String</anno></c>. - Returns <c>0</c> if <c><anno>SubString</anno></c> - does not exist in <c><anno>String</anno></c>.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="#find/3"><c>find/3</c></seealso>.</p> - <p><em>Example:</em></p> - <code type="none"> -> string:rstr(" Hello Hello World World ", "Hello World"). -8</code> - </desc> - </func> - - <func> - <name name="span" arity="2"/> - <fsummary>Span characters at start of a string.</fsummary> - <desc> - <p>Returns the length of the maximum initial segment of - <c><anno>String</anno></c>, which consists entirely of characters - from <c><anno>Chars</anno></c>.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="#take/2"><c>take/2</c></seealso>.</p> - <p><em>Example:</em></p> - <code type="none"> -> string:span("\t abcdef", " \t"). -5</code> - </desc> - </func> - - <func> - <name name="str" arity="2"/> - <fsummary>Find the index of a substring.</fsummary> - <desc> - <p>Returns the position where the first occurrence of - <c><anno>SubString</anno></c> begins in <c><anno>String</anno></c>. - Returns <c>0</c> if <c><anno>SubString</anno></c> - does not exist in <c><anno>String</anno></c>.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="#find/2"><c>find/2</c></seealso>.</p> - <p><em>Example:</em></p> - <code type="none"> -> string:str(" Hello Hello World World ", "Hello World"). -8</code> - </desc> - </func> - - <func> - <name name="strip" arity="1"/> - <name name="strip" arity="2"/> - <name name="strip" arity="3"/> - <fsummary>Strip leading or trailing characters.</fsummary> - <desc> - <p>Returns a string, where leading or trailing, or both, blanks or a - number of <c><anno>Character</anno></c> have been removed. - <c><anno>Direction</anno></c>, which can be <c>left</c>, <c>right</c>, - or <c>both</c>, indicates from which direction blanks are to be - removed. <c>strip/1</c> is equivalent to - <c>strip(String, both)</c>.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="#trim/3"><c>trim/3</c></seealso>.</p> - <p><em>Example:</em></p> - <code type="none"> -> string:strip("...Hello.....", both, $.). -"Hello"</code> - </desc> - </func> - - <func> - <name name="sub_string" arity="2"/> - <name name="sub_string" arity="3"/> - <fsummary>Extract a substring.</fsummary> - <desc> - <p>Returns a substring of <c><anno>String</anno></c>, starting at - position <c><anno>Start</anno></c> to the end of the string, or to - and including position <c><anno>Stop</anno></c>.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="#slice/3"><c>slice/3</c></seealso>.</p> - <p><em>Example:</em></p> - <code type="none"> -sub_string("Hello World", 4, 8). -"lo Wo"</code> - </desc> - </func> - - <func> - <name name="substr" arity="2"/> - <name name="substr" arity="3"/> - <fsummary>Return a substring of a string.</fsummary> - <desc> - <p>Returns a substring of <c><anno>String</anno></c>, starting at - position <c><anno>Start</anno></c>, and ending at the end of the - string or at length <c><anno>Length</anno></c>.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="#slice/3"><c>slice/3</c></seealso>.</p> - <p><em>Example:</em></p> - <code type="none"> -> substr("Hello World", 4, 5). -"lo Wo"</code> - </desc> - </func> - - <func> - <name name="sub_word" arity="2"/> - <name name="sub_word" arity="3"/> - <fsummary>Extract subword.</fsummary> - <desc> - <p>Returns the word in position <c><anno>Number</anno></c> of - <c><anno>String</anno></c>. Words are separated by blanks or - <c><anno>Character</anno></c>s.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="#nth_lexeme/3"><c>nth_lexeme/3</c></seealso>.</p> - <p><em>Example:</em></p> - <code type="none"> -> string:sub_word(" Hello old boy !",3,$o). -"ld b"</code> - </desc> - </func> - - <func> - <name name="to_lower" arity="1" clause_i="1"/> - <name name="to_lower" arity="1" clause_i="2"/> - <name name="to_upper" arity="1" clause_i="1"/> - <name name="to_upper" arity="1" clause_i="2"/> - <fsummary>Convert case of string (ISO/IEC 8859-1).</fsummary> - <type variable="String" name_i="1"/> - <type variable="Result" name_i="1"/> - <type variable="Char"/> - <type variable="CharResult"/> - <desc> - <p>The specified string or character is case-converted. Notice that - the supported character set is ISO/IEC 8859-1 (also called Latin 1); - all values outside this set are unchanged</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso> use - <seealso marker="#lowercase/1"><c>lowercase/1</c></seealso>, - <seealso marker="#uppercase/1"><c>uppercase/1</c></seealso>, - <seealso marker="#titlecase/1"><c>titlecase/1</c></seealso> or - <seealso marker="#casefold/1"><c>casefold/1</c></seealso>.</p> - </desc> - </func> - - <func> - <name name="tokens" arity="2"/> - <fsummary>Split string into tokens.</fsummary> - <desc> - <p>Returns a list of tokens in <c><anno>String</anno></c>, separated - by the characters in <c><anno>SeparatorList</anno></c>.</p> - <p><em>Example:</em></p> - <code type="none"> -> tokens("abc defxxghix jkl", "x "). -["abc", "def", "ghi", "jkl"]</code> - <p>Notice that, as shown in this example, two or more - adjacent separator characters in <c><anno>String</anno></c> - are treated as one. That is, there are no empty - strings in the resulting list of tokens.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="#lexemes/2"><c>lexemes/2</c></seealso>.</p> - </desc> - </func> - - <func> - <name name="words" arity="1"/> - <name name="words" arity="2"/> - <fsummary>Count blank separated words.</fsummary> - <desc> - <p>Returns the number of words in <c><anno>String</anno></c>, separated - by blanks or <c><anno>Character</anno></c>.</p> - <p>This function is <seealso marker="#oldapi">obsolete</seealso>. - Use - <seealso marker="#lexemes/2"><c>lexemes/2</c></seealso>.</p> - <p><em>Example:</em></p> - <code type="none"> -> words(" Hello old boy!", $o). -4</code> - </desc> - </func> - </funcs> - - <section> - <title>Notes</title> - <p>Some of the general string functions can seem to overlap each - other. The reason is that this string package is the - combination of two earlier packages and all functions of - both packages have been retained.</p> - </section> - </erlref> diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index 31d0d499e3..00e6a10d8a 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -479,7 +479,7 @@ com_enc(_B, _Fun, _N, L, Ps) -> com_enc_end([L | Ps]). com_enc_end(Ps0) -> - Ps = lists:reverse([lists:reverse(string:to_lower(P)) || P <- Ps0]), + Ps = lists:reverse([lists:reverse(lowercase(P)) || P <- Ps0]), com_encoding(Ps). com_encoding(["latin","1"|_]) -> @@ -489,6 +489,9 @@ com_encoding(["utf","8"|_]) -> com_encoding(_) -> throw(no). % Don't try any further +lowercase(S) -> + unicode:characters_to_list(string:lowercase(S)). + normalize_typed_record_fields([]) -> {typed, []}; normalize_typed_record_fields(Fields) -> diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index 9cd4727dc3..f58cb35cea 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -3910,10 +3910,9 @@ check_format_string(Fmt) -> extract_sequences(Fmt, []). extract_sequences(Fmt, Need0) -> - case string:chr(Fmt, $~) of - 0 -> {ok,lists:reverse(Need0)}; %That's it - Pos -> - Fmt1 = string:substr(Fmt, Pos+1), %Skip ~ + case string:find(Fmt, [$~]) of + nomatch -> {ok,lists:reverse(Need0)}; %That's it + [$~|Fmt1] -> case extract_sequence(1, Fmt1, Need0) of {ok,Need1,Rest} -> extract_sequences(Rest, Need1); Error -> Error diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl index b0064aadb8..367dbefb82 100644 --- a/lib/stdlib/src/erl_pp.erl +++ b/lib/stdlib/src/erl_pp.erl @@ -237,13 +237,20 @@ lform({attribute,Line,Name,Arg}, Opts) -> lform({function,Line,Name,Arity,Clauses}, Opts) -> lfunction({function,Line,Name,Arity,Clauses}, Opts); %% These are specials to make it easier for the compiler. -lform({error,E}, _Opts) -> - leaf(format("~p\n", [{error,E}])); -lform({warning,W}, _Opts) -> - leaf(format("~p\n", [{warning,W}])); +lform({error,_}=E, Opts) -> + message(E, Opts); +lform({warning,_}=W, Opts) -> + message(W, Opts); lform({eof,_Line}, _Opts) -> $\n. +message(M, #options{encoding = Encoding}) -> + F = case Encoding of + latin1 -> "~p\n"; + unicode -> "~tp\n" + end, + leaf(format(F, [M])). + lattribute({attribute,_Line,type,Type}, Opts) -> [typeattr(type, Type, Opts),leaf(".\n")]; lattribute({attribute,_Line,opaque,Type}, Opts) -> @@ -902,7 +909,7 @@ maybe_paren(_P, _Prec, Expr) -> Expr. leaf(S) -> - {leaf,chars_size(S),S}. + {leaf,string:length(S),S}. %%% Do the formatting. Currently nothing fancy. Could probably have %%% done it in one single pass. @@ -962,7 +969,7 @@ f({seq,Before,After,Sep,LItems}, I0, ST, WT, PP) -> Sizes = BSizeL ++ SizeL, NSepChars = if is_list(Sep), Sep =/= [] -> - erlang:max(0, length(CharsL)-1); + erlang:max(0, length(CharsL)-1); % not string:length true -> 0 end, @@ -1118,7 +1125,7 @@ incr(I, Incr) -> I+Incr. indentation(E, I) when I < 0 -> - chars_size(E); + string:length(E); indentation(E, I0) -> I = io_lib_format:indentation(E, I0), case has_nl(E) of @@ -1155,19 +1162,19 @@ write_a_string(S, I, PP) -> write_a_string([], _N, _Len, _PP) -> []; write_a_string(S, N, Len, PP) -> - SS = string:sub_string(S, 1, N), + SS = string:slice(S, 0, N), Sl = write_string(SS, PP), - case (chars_size(Sl) > Len) and (N > ?MIN_SUBSTRING) of + case (string:length(Sl) > Len) and (N > ?MIN_SUBSTRING) of true -> write_a_string(S, N-1, Len, PP); false -> [flat_leaf(Sl) | - write_a_string(lists:nthtail(length(SS), S), Len, Len, PP)] + write_a_string(string:slice(S, string:length(SS)), Len, Len, PP)] end. flat_leaf(S) -> L = lists:flatten(S), - {leaf,length(L),L}. + {leaf,string:length(L),L}. write_value(V, PP) -> (PP#pp.value_fun)(V). @@ -1188,15 +1195,6 @@ write_char(C, PP) -> a0() -> erl_anno:new(0). -chars_size([C | Es]) when is_integer(C) -> - 1 + chars_size(Es); -chars_size([E | Es]) -> - chars_size(E) + chars_size(Es); -chars_size([]) -> - 0; -chars_size(B) when is_binary(B) -> - byte_size(B). - -define(N_SPACES, 30). spacetab() -> diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl index 47223b129c..4774c4bf19 100644 --- a/lib/stdlib/src/erl_scan.erl +++ b/lib/stdlib/src/erl_scan.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2015. All Rights Reserved. +%% Copyright Ericsson AB 1996-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -752,7 +752,7 @@ scan_string(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0}) -> {char_error,Ncs,Error,Nline,Ncol,EndCol} -> scan_error(Error, Nline, Ncol, Nline, EndCol, Ncs); {error,Nline,Ncol,Nwcs,Ncs} -> - Estr = string:substr(Nwcs, 1, 16), % Expanded escape chars. + Estr = string:slice(Nwcs, 0, 16), % Expanded escape chars. scan_error({string,$\",Estr}, Line0, Col0, Nline, Ncol, Ncs); %" {Ncs,Nline,Ncol,Nstr,Nwcs} -> Anno = anno(Line0, Col0, St, Nstr), @@ -767,7 +767,7 @@ scan_qatom(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0}) -> {char_error,Ncs,Error,Nline,Ncol,EndCol} -> scan_error(Error, Nline, Ncol, Nline, EndCol, Ncs); {error,Nline,Ncol,Nwcs,Ncs} -> - Estr = string:substr(Nwcs, 1, 16), % Expanded escape chars. + Estr = string:slice(Nwcs, 0, 16), % Expanded escape chars. scan_error({string,$\',Estr}, Line0, Col0, Nline, Ncol, Ncs); %' {Ncs,Nline,Ncol,Nstr,Nwcs} -> case catch list_to_atom(Nwcs) of diff --git a/lib/stdlib/src/escript.erl b/lib/stdlib/src/escript.erl index 2b9d8ff65b..132f8efbbe 100644 --- a/lib/stdlib/src/escript.erl +++ b/lib/stdlib/src/escript.erl @@ -224,8 +224,8 @@ return_sections(S, Bin) -> normalize_section(Name, undefined) -> {Name, undefined}; normalize_section(shebang, "#!" ++ Chars) -> - Chopped = string:strip(Chars, right, $\n), - Stripped = string:strip(Chopped, both), + Chopped = string:trim(Chars, trailing, "$\n"), + Stripped = string:trim(Chopped, both), if Stripped =:= ?SHEBANG -> {shebang, default}; @@ -233,8 +233,8 @@ normalize_section(shebang, "#!" ++ Chars) -> {shebang, Stripped} end; normalize_section(comment, Chars) -> - Chopped = string:strip(Chars, right, $\n), - Stripped = string:strip(string:strip(Chopped, left, $%), both), + Chopped = string:trim(Chars, trailing, "$\n"), + Stripped = string:trim(string:trim(Chopped, leading, "$%"), both), if Stripped =:= ?COMMENT -> {comment, default}; @@ -242,8 +242,8 @@ normalize_section(comment, Chars) -> {comment, Stripped} end; normalize_section(emu_args, "%%!" ++ Chars) -> - Chopped = string:strip(Chars, right, $\n), - Stripped = string:strip(Chopped, both), + Chopped = string:trim(Chars, trailing, "$\n"), + Stripped = string:trim(Chopped, both), {emu_args, Stripped}; normalize_section(Name, Chars) -> {Name, Chars}. diff --git a/lib/stdlib/src/ets.erl b/lib/stdlib/src/ets.erl index b5d3cd3c8d..4858c8d13c 100644 --- a/lib/stdlib/src/ets.erl +++ b/lib/stdlib/src/ets.erl @@ -1717,7 +1717,7 @@ get_line(P, Default) -> line_string(Binary) when is_binary(Binary) -> unicode:characters_to_list(Binary); line_string(Other) -> Other. -nonl(S) -> string:strip(S, right, $\n). +nonl(S) -> string:trim(S, trailing, "$\n"). print_number(Tab, Key, Num) -> Os = ets:lookup(Tab, Key), @@ -1746,7 +1746,7 @@ do_display_item(_Height, Width, I, Opos) -> L = to_string(I), L2 = if length(L) > Width - 8 -> - string:substr(L, 1, Width-13) ++ " ..."; + string:slice(L, 0, Width-13) ++ " ..."; true -> L end, diff --git a/lib/stdlib/src/filename.erl b/lib/stdlib/src/filename.erl index 9bf4290916..63cfeae57b 100644 --- a/lib/stdlib/src/filename.erl +++ b/lib/stdlib/src/filename.erl @@ -1036,10 +1036,10 @@ basedir_linux(Type) -> user_log -> getenv("XDG_CACHE_HOME", ?basedir_linux_user_log, true); site_data -> Base = getenv("XDG_DATA_DIRS",?basedir_linux_site_data,false), - string:tokens(Base,":"); + string:lexemes(Base, ":"); site_config -> Base = getenv("XDG_CONFIG_DIRS",?basedir_linux_site_config,false), - string:tokens(Base,":") + string:lexemes(Base, ":") end. -define(basedir_darwin_user_data, "Library/Application Support"). diff --git a/lib/stdlib/src/io_lib_format.erl b/lib/stdlib/src/io_lib_format.erl index 4b2d15c8b3..e345810ca0 100644 --- a/lib/stdlib/src/io_lib_format.erl +++ b/lib/stdlib/src/io_lib_format.erl @@ -380,7 +380,7 @@ float_e(_Fl, {Ds,E}, P) -> {Fs,false} -> [Fs|float_exp(E-1)] end. -%% float_man([Digit], Icount, Dcount) -> {[Chars],CarryFlag}. +%% float_man([Digit], Icount, Dcount) -> {[Char],CarryFlag}. %% Generate the characters in the mantissa from the digits with Icount %% characters before the '.' and Dcount decimals. Handle carry and let %% caller decide what to do at top. @@ -395,7 +395,7 @@ float_man([D|Ds], I, Dc) -> {Cs,false} -> {[D|Cs],false} end; float_man([], I, Dc) -> %Pad with 0's - {string:chars($0, I, [$.|string:chars($0, Dc)]),false}. + {lists:duplicate(I, $0) ++ [$.|lists:duplicate(Dc, $0)],false}. float_man([D|_], 0) when D >= $5 -> {[],true}; float_man([_|_], 0) -> {[],false}; @@ -405,7 +405,7 @@ float_man([D|Ds], Dc) -> {Cs,true} -> {[D+1|Cs],false}; {Cs,false} -> {[D|Cs],false} end; -float_man([], Dc) -> {string:chars($0, Dc),false}. %Pad with 0's +float_man([], Dc) -> {lists:duplicate(Dc, $0),false}. %Pad with 0's %% float_exp(Exponent) -> [Char]. %% Generate the exponent of a floating point number. Always include sign. @@ -429,7 +429,7 @@ fwrite_f(Fl, F, Adj, P, Pad) when P >= 1 -> float_f(Fl, Fd, P) when Fl < 0.0 -> [$-|float_f(-Fl, Fd, P)]; float_f(Fl, {Ds,E}, P) when E =< 0 -> - float_f(Fl, {string:chars($0, -E+1, Ds),1}, P); %Prepend enough 0's + float_f(Fl, {lists:duplicate(-E+1, $0)++Ds,1}, P); %Prepend enough 0's float_f(_Fl, {Ds,E}, P) -> case float_man(Ds, E, P) of {Fs,true} -> "1" ++ Fs; %Handle carry @@ -751,7 +751,7 @@ adjust(Data, Pad, right) -> [Pad|Data]. flat_trunc(List, N) when is_integer(N), N >= 0 -> string:slice(List, 0, N). -%% A deep version of string:chars/2,3 +%% A deep version of lists:duplicate/2 chars(_C, 0) -> []; diff --git a/lib/stdlib/src/lib.erl b/lib/stdlib/src/lib.erl index c6eb0d7915..a7980cc294 100644 --- a/lib/stdlib/src/lib.erl +++ b/lib/stdlib/src/lib.erl @@ -646,7 +646,7 @@ pp_arguments(PF, As, I, Enc) -> Ll = length(L), A = list_to_atom(lists:duplicate(Ll, $a)), S0 = unicode:characters_to_list(PF([A | T], I+1), Enc), - brackets_to_parens([$[,L,string:sub_string(S0, 2+Ll)], Enc); + brackets_to_parens([$[,L,string:slice(S0, 1+Ll)], Enc); _ -> brackets_to_parens(PF(As, I+1), Enc) end. diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index c59db903dc..122b476ddb 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -466,8 +466,6 @@ obsolete_1(inviso, _, _) -> {removed,"the inviso application was removed in R16"}; %% Added in R15B01. -obsolete_1(gs, _, _) -> - {removed,"the gs application has been removed; use the wx application instead"}; obsolete_1(ssh, sign_data, 2) -> {removed,"removed in R16A; use public_key:pem_decode/1, public_key:pem_entry_decode/1 " "and public_key:sign/3 instead"}; @@ -611,6 +609,52 @@ obsolete_1(filename, find_src, 2) -> obsolete_1(erlang, hash, 2) -> {removed, {erlang, phash2, 2}, "20.0"}; +%% Added in OTP-21 +obsolete_1(string, len, 1) -> + {deprecated, "deprecated; use string:length/3 instead"}; +obsolete_1(string, concat, 2) -> + {deprecated, "deprecated; use [Str1,Str2] instead"}; +obsolete_1(string, str, 2) -> + {deprecated, "deprecated; use string:find/2 instead"}; +obsolete_1(string, rstr, 2) -> + {deprecated, "deprecated; use string:find/3 instead"}; +obsolete_1(string, chr, 2) -> + {deprecated, "deprecated; use string:find/2 instead"}; +obsolete_1(string, rchr, 2) -> + {deprecated, "deprecated; use string:find/3 instead"}; +obsolete_1(string, span, 2) -> + {deprecated, "deprecated; use string:take/2 instead"}; +obsolete_1(string, cspan, 2) -> + {deprecated, "deprecated; use string:take/3 instead"}; +obsolete_1(string, substr, _) -> + {deprecated, "deprecated; use string:slice/3 instead"}; +obsolete_1(string, tokens, 2) -> + {deprecated, "deprecated; use string:lexemes/2 instead"}; +obsolete_1(string, chars, _) -> + {deprecated, "deprecated; use lists:duplicate/2 instead"}; +obsolete_1(string, copies, _) -> + {deprecated, "deprecated; use lists:duplicate/2 instead"}; +obsolete_1(string, words, _) -> + {deprecated, "deprecated; use string:lexemes/2 instead"}; +obsolete_1(string, strip, _) -> + {deprecated, "deprecated; use string:trim/3 instead"}; +obsolete_1(string, sub_word, _) -> + {deprecated, "deprecated; use string:nth_lexeme/3 instead"}; +obsolete_1(string, sub_string, _) -> + {deprecated, "deprecated; use string:slice/3 instead"}; +obsolete_1(string, left, _) -> + {deprecated, "deprecated; use string:pad/3 instead"}; +obsolete_1(string, right, _) -> + {deprecated, "deprecated; use string:pad/3 instead"}; +obsolete_1(string, centre, _) -> + {deprecated, "deprecated; use string:pad/3 instead"}; +obsolete_1(string, join, _) -> + {deprecated, "deprecated; use lists:join/2 instead"}; +obsolete_1(string, to_upper, _) -> + {deprecated, "deprecated; use string:uppercase/1 or string:titlecase/1 instead"}; +obsolete_1(string, to_lower, _) -> + {deprecated, "deprecated; use string:lowercase/1 or string:casefold/1 instead"}; + %% not obsolete obsolete_1(_, _, _) -> diff --git a/lib/stdlib/src/pool.erl b/lib/stdlib/src/pool.erl index 05950a1d7c..b12ff205b1 100644 --- a/lib/stdlib/src/pool.erl +++ b/lib/stdlib/src/pool.erl @@ -25,7 +25,7 @@ %% with the least load !!!! %% This function is callable from any node including the master %% That is part of the pool -%% nodes are scheduled on a per usgae basis and per load basis, +%% nodes are scheduled on a per usage basis and per load basis, %% Whenever we use a node, we put at the end of the queue, and whenever %% a node report a change in load, we insert it accordingly @@ -197,7 +197,7 @@ pure_insert({Load,Node},[{L,N}|Tail]) when Load < L -> pure_insert(L,[H|T]) -> [H|pure_insert(L,T)]. %% Really should not measure the contributions from -%% the back ground processes here .... which we do :-( +%% the background processes here .... which we do :-( %% We don't have to monitor the master, since we're slaves anyway statistic_collector() -> @@ -213,7 +213,7 @@ statistic_collector(I) -> stat_loop(M, 999999) end. -%% Do not tell the master about our load if it has not changed +%% Do not tell the master about our load if it has not changed stat_loop(M, Old) -> sleep(2000), diff --git a/lib/stdlib/src/slave.erl b/lib/stdlib/src/slave.erl index d7cf6386f5..b3f3206d67 100644 --- a/lib/stdlib/src/slave.erl +++ b/lib/stdlib/src/slave.erl @@ -320,7 +320,7 @@ mk_cmd(Host, Name, Args, Waiter, Prog0) -> %% emulator and flags as the test node. The return from lib:progname() %% could then typically be '/<full_path_to>/cerl -gcov'). quote_progname(Progname) -> - do_quote_progname(string:tokens(to_list(Progname)," ")). + do_quote_progname(string:lexemes(to_list(Progname)," ")). do_quote_progname([Prog]) -> "\""++Prog++"\""; diff --git a/lib/stdlib/src/string.erl b/lib/stdlib/src/string.erl index 4972da297d..5a4d2df2a6 100644 --- a/lib/stdlib/src/string.erl +++ b/lib/stdlib/src/string.erl @@ -87,6 +87,16 @@ %%% May be removed -export([list_to_float/1, list_to_integer/1]). +-deprecated([{len,1},{concat,2}, + {str,2},{chr,2},{rchr,2},{rstr,2}, + {span,2},{cspan,2},{substr,'_'},{tokens,2}, + {chars,'_'}, + {copies,2},{words,'_'},{strip,'_'}, + {sub_word,'_'},{left,'_'},{right,'_'}, + {sub_string,'_'},{centre,'_'},{join,2}, + {to_upper,1}, {to_lower,1} + ]). + %% Uses bifs: string:list_to_float/1 and string:list_to_integer/1 -spec list_to_float(String) -> {Float, Rest} | {'error', Reason} when String :: string(), diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile index 7b79dcf04d..523cb95065 100644 --- a/lib/stdlib/test/Makefile +++ b/lib/stdlib/test/Makefile @@ -69,6 +69,7 @@ MODULES= \ sets_test_lib \ sofs_SUITE \ stdlib_SUITE \ + stdlib_bench_SUITE \ string_SUITE \ supervisor_1 \ supervisor_2 \ @@ -146,7 +147,7 @@ release_spec: opt release_tests_spec: make_emakefile $(INSTALL_DIR) "$(RELSYSDIR)" - $(INSTALL_DATA) stdlib.spec $(EMAKEFILE) \ + $(INSTALL_DATA) stdlib.spec stdlib_bench.spec $(EMAKEFILE) \ $(ERL_FILES) $(COVERFILE) "$(RELSYSDIR)" chmod -R u+w "$(RELSYSDIR)" @tar cf - *_SUITE_data | (cd "$(RELSYSDIR)"; tar xf -) diff --git a/lib/stdlib/test/stdlib.spec b/lib/stdlib/test/stdlib.spec index 3768e494b2..91712b8963 100644 --- a/lib/stdlib/test/stdlib.spec +++ b/lib/stdlib/test/stdlib.spec @@ -1 +1,2 @@ {suites,"../stdlib_test",all}. +{skip_suites,"../stdlib_test",stdlib_bench_SUITE, "bench only"}. diff --git a/lib/stdlib/test/stdlib_bench.spec b/lib/stdlib/test/stdlib_bench.spec new file mode 100644 index 0000000000..a5d1e1db80 --- /dev/null +++ b/lib/stdlib/test/stdlib_bench.spec @@ -0,0 +1,7 @@ +%% Needed to compile ,unicode_util_SUITE and string_SUITE... +{cases,"../stdlib_test",unicode_util_SUITE, []}. +{cases,"../stdlib_test",string_SUITE, []}. +{skip_suites,"../stdlib_test",unicode_util_SUITE, "bench only"}. +{skip_suites,"../stdlib_test",string_SUITE, "bench only"}. + +{suites,"../stdlib_test",[stdlib_bench_SUITE]}. diff --git a/lib/stdlib/test/stdlib_bench_SUITE.erl b/lib/stdlib/test/stdlib_bench_SUITE.erl new file mode 100644 index 0000000000..8670e7029c --- /dev/null +++ b/lib/stdlib/test/stdlib_bench_SUITE.erl @@ -0,0 +1,107 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2012-2016. All Rights Reserved. +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. +%% +%% %CopyrightEnd% +%% + +%% +-module(stdlib_bench_SUITE). +-compile([export_all, nowarn_export_all]). +-include_lib("common_test/include/ct_event.hrl"). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +suite() -> [{ct_hooks,[{ts_install_cth,[{nodenames,2}]}]}]. + + +all() -> + [{group,unicode}]. + +groups() -> + [{unicode,[{repeat,5}], + [norm_nfc_list, norm_nfc_deep_l, norm_nfc_binary, + string_lexemes_list, string_lexemes_binary + ]}]. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +init_per_suite(Config) -> + Config. + +end_per_suite(Config) -> + Config. + +init_per_testcase(_Func, Conf) -> + Conf. + +end_per_testcase(_Func, _Conf) -> + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-define(REPEAT_NORM, 5). + +norm_nfc_list(Config) -> + Bin = norm_data(Config), + {_N, Mean, _Stddev, Res} = unicode_util_SUITE:time_count(nfc, list, Bin, ?REPEAT_NORM), + report(1000.0*Res / Mean). + +norm_nfc_deep_l(Config) -> + Bin = norm_data(Config), + {_N, Mean, _Stddev, Res} = unicode_util_SUITE:time_count(nfc, deep_l, Bin, ?REPEAT_NORM), + report(1000.0*Res / Mean). + +norm_nfc_binary(Config) -> + Bin = norm_data(Config), + {_N, Mean, _Stddev, Res} = unicode_util_SUITE:time_count(nfc, binary, Bin, ?REPEAT_NORM), + report(1000.0*Res / Mean). + + +string_lexemes_list(Config) -> + %% Use nth_lexeme instead of lexemes to avoid building a result of + %% large lists which causes large differences between test runs, gc? + Bin = norm_data(Config), + Fun = fun(Str) -> string:nth_lexeme(Str, 200000, [$;,$\n,$\r]), 200000 end, + {_N, Mean, _Stddev, Res} = string_SUITE:time_func(Fun, list, Bin, 15), + report(1000.0*Res / Mean). + +string_lexemes_binary(Config) -> + %% Use nth_lexeme instead of lexemes to avoid building a result of + %% large lists which causes large differences between test runs, gc? + Bin = norm_data(Config), + Fun = fun(Str) -> string:nth_lexeme(Str, 200000, [$;,$\n,$\r]), 200000 end, + {_N, Mean, _Stddev, Res} = string_SUITE:time_func(Fun, binary, Bin, ?REPEAT_NORM), + report(1000.0*Res / Mean). + +%%% +report(Tps) -> + ct_event:notify(#event{name = benchmark_data, + data = [{suite,"stdlib_unicode"},{value,round(Tps)}]}), + Tps. + +norm_data(Config) -> + DataDir0 = proplists:get_value(data_dir, Config), + DataDir = filename:join(lists:droplast(filename:split(DataDir0))), + File = filename:join([DataDir,"unicode_util_SUITE_data","NormalizationTest.txt"]), + {ok, Bin} = file:read_file(File), + Bin. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/lib/stdlib/test/string_SUITE.erl b/lib/stdlib/test/string_SUITE.erl index 90f980c0e5..05f18ef238 100644 --- a/lib/stdlib/test/string_SUITE.erl +++ b/lib/stdlib/test/string_SUITE.erl @@ -47,7 +47,7 @@ -export([to_upper_to_lower/1]). %% Run tests when debugging them --export([debug/0]). +-export([debug/0, time_func/4]). suite() -> [{ct_hooks,[ts_install_cth]}, @@ -728,7 +728,7 @@ do_measure(TestDir) -> {ok, Bin} = file:read_file(File), io:format("~p~n",[byte_size(Bin)]), Do = fun(Name, Func, Mode) -> - {N, Mean, Stddev, _} = time_func(Func, Mode, Bin), + {N, Mean, Stddev, _} = time_func(Func, Mode, Bin, 50), io:format("~10w ~6w ~6.2fms ±~4.2fms #~.2w gc included~n", [Name, Mode, Mean/1000, Stddev/1000, N]) end, @@ -938,19 +938,19 @@ needs_check(_) -> true. %%%% Timer stuff -time_func(Fun, Mode, Bin) -> +time_func(Fun, Mode, Bin, Repeat) -> timer:sleep(100), %% Let emulator catch up and clean things before test runs Self = self(), Pid = spawn_link(fun() -> Str = mode(Mode, Bin), - Self ! {self(),time_func(0,0,0, Fun, Str, undefined)} + Self ! {self(),time_func(0,0,0, Fun, Str, undefined, Repeat)} end), receive {Pid,Msg} -> Msg end. -time_func(N,Sum,SumSq, Fun, Str, _) when N < 50 -> +time_func(N,Sum,SumSq, Fun, Str, _, Repeat) when N < Repeat -> {Time, Res} = timer:tc(fun() -> Fun(Str) end), - time_func(N+1,Sum+Time,SumSq+Time*Time, Fun, Str, Res); -time_func(N,Sum,SumSq, _, _, Res) -> + time_func(N+1,Sum+Time,SumSq+Time*Time, Fun, Str, Res, Repeat); +time_func(N,Sum,SumSq, _, _, Res, _) -> Mean = round(Sum / N), Stdev = round(math:sqrt((SumSq - (Sum*Sum/N))/(N - 1))), {N, Mean, Stdev, Res}. diff --git a/lib/stdlib/test/unicode_util_SUITE.erl b/lib/stdlib/test/unicode_util_SUITE.erl index 03c24c7027..7dba0a2fd0 100644 --- a/lib/stdlib/test/unicode_util_SUITE.erl +++ b/lib/stdlib/test/unicode_util_SUITE.erl @@ -29,7 +29,9 @@ get/1, count/1]). --export([debug/0, id/1, bin_split/1, uc_loaded_size/0]). +-export([debug/0, id/1, bin_split/1, uc_loaded_size/0, + time_count/4 %% Used by stdlib_bench_SUITE + ]). suite() -> [{ct_hooks,[ts_install_cth]}, @@ -323,7 +325,7 @@ do_measure(Config) -> File = DataDir ++ "/NormalizationTest.txt", {ok, Bin} = file:read_file(File), Do = fun(Func, Mode) -> - {N, Mean, Stddev, Res} = time_count(Func, Mode, Bin), + {N, Mean, Stddev, Res} = time_count(Func, Mode, Bin, 10), io:format("~4w ~6w ~.10w ~.6wms ±~.2wms #~.2w~n", [Func, Mode, Res, Mean div 1000, Stddev div 1000, N]) end, @@ -345,19 +347,19 @@ uc_loaded_size([_|Rest]) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -time_count(Fun, Mode, Bin) -> +time_count(Fun, Mode, Bin, Repeat) -> timer:sleep(100), %% Let emulator catch up and clean things before test runs Self = self(), Pid = spawn_link(fun() -> Str = mode(Mode, Bin), - Self ! {self(),do_count(0,0,0, Fun, Str, undefined)} + Self ! {self(),do_count(0,0,0, Fun, Str, undefined, Repeat)} end), receive {Pid,Msg} -> Msg end. -do_count(N,Sum,SumSq, Fun, Str, _) when N < 10 -> +do_count(N,Sum,SumSq, Fun, Str, _, Repeat) when N < Repeat -> {Time, Res} = do_count(Fun, Str), - do_count(N+1,Sum+Time,SumSq+Time*Time, Fun, Str, Res); -do_count(N,Sum,SumSq, _, _, Res) -> + do_count(N+1,Sum+Time,SumSq+Time*Time, Fun, Str, Res, Repeat); +do_count(N,Sum,SumSq, _, _, Res, _) -> Mean = round(Sum / N), Stdev = round(math:sqrt((SumSq - (Sum*Sum/N))/(N - 1))), {N, Mean, Stdev, Res}. diff --git a/lib/stdlib/uc_spec/gen_unicode_mod.escript b/lib/stdlib/uc_spec/gen_unicode_mod.escript index 5b8763f576..674e5a0628 100755 --- a/lib/stdlib/uc_spec/gen_unicode_mod.escript +++ b/lib/stdlib/uc_spec/gen_unicode_mod.escript @@ -65,7 +65,7 @@ main(_) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% parse_unicode_data(Line0, Acc) -> - Line = string:strip(Line0, right, $\n), + Line = string:chomp(Line0), [CodePoint,Name,_Cat,Class,_BiDi,Decomp, _N1,_N2,_N3,_BDMirror,_Uni1,_Iso|Case] = tokens(Line, ";"), {Dec,Comp} = case to_decomp(Decomp) of @@ -78,14 +78,14 @@ parse_unicode_data(Line0, Acc) -> |Acc]. to_class(String) -> - list_to_integer(string:strip(String, both)). + list_to_integer(string:trim(String, both)). to_decomp("") -> []; to_decomp("<" ++ Str) -> - [Tag,Rest] = string:tokens(Str, ">"), + [Tag,Rest] = string:lexemes(Str, ">"), {list_to_atom(Tag), to_decomp(Rest)}; to_decomp(CodePoints) -> - CPL = string:tokens(CodePoints, " "), + CPL = string:lexemes(CodePoints, " "), [hex_to_int(CP) || CP <- CPL]. to_case(["","",""]) -> []; @@ -105,20 +105,20 @@ parse_special_casing(Line, Table) -> array:set(CP, Entry#cp{cs=Case}, Table). to_scase([Lower,Title,Upper|_]) -> - {unlist([hex_to_int(CP) || CP <- string:strip(string:tokens(Upper, " "), both)]), - unlist([hex_to_int(CP) || CP <- string:strip(string:tokens(Lower, " "), both)]), - unlist([hex_to_int(CP) || CP <- string:strip(string:tokens(Title, " "), both)]), + {unlist([hex_to_int(CP) || CP <- string:lexemes(Upper, " ")]), + unlist([hex_to_int(CP) || CP <- string:lexemes(Lower, " ")]), + unlist([hex_to_int(CP) || CP <- string:lexemes(Title, " ")]), []}. parse_case_folding(Line, Table) -> [CodePoint, Class0, CaseStr |_Comments] = tokens(Line, ";"), - Class = string:strip(Class0, both), + Class = string:trim(Class0, both), if Class =:= "T" -> Table; %% Do not support localization yet Class =:= "S" -> Table; %% Ignore simple true -> CP = hex_to_int(CodePoint), Case = unlist([hex_to_int(CPC) || - CPC <- string:strip(string:tokens(CaseStr, " "), both)]), + CPC <- string:lexemes(CaseStr, " ")]), #cp{cs={U,L,T,_}} = Entry = array:get(CP, Table), array:set(CP, Entry#cp{cs={U,L,T,Case}}, Table) end. @@ -869,10 +869,10 @@ optimize_ranges_1(Rs) -> hex_to_int([]) -> []; hex_to_int(HexStr) -> - list_to_integer(string:strip(HexStr, both), 16). + list_to_integer(string:trim(HexStr, both), 16). to_atom(Str) -> - list_to_atom(string:to_lower(string:strip(Str, both))). + list_to_atom(string:lowercase(string:trim(Str, both))). foldl(Fun, Acc, Fd) -> Get = fun() -> file:read_line(Fd) end, @@ -892,7 +892,7 @@ foldl_1(Fun, Acc, Get) -> -%% Differs from string:tokens, it returns empty string as token between two delimiters +%% Differs from string:lexemes, it returns empty string as token between two delimiters tokens(S, [C]) -> tokens(lists:reverse(S), C, []). diff --git a/lib/stdlib/vsn.mk b/lib/stdlib/vsn.mk index 8a83cdec1e..48db5dc900 100644 --- a/lib/stdlib/vsn.mk +++ b/lib/stdlib/vsn.mk @@ -1 +1 @@ -STDLIB_VSN = 3.4.1 +STDLIB_VSN = 3.4.2 diff --git a/lib/syntax_tools/doc/src/notes.xml b/lib/syntax_tools/doc/src/notes.xml index f85d963919..8c91f01e3b 100644 --- a/lib/syntax_tools/doc/src/notes.xml +++ b/lib/syntax_tools/doc/src/notes.xml @@ -32,6 +32,27 @@ <p>This document describes the changes made to the Syntax_Tools application.</p> +<section><title>Syntax_Tools 2.1.3</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + General Unicode improvements.</p> + <p> + Own Id: OTP-14462</p> + </item> + <item> + <p> A process trapping exits and calling <c>erl_tidy</c> + no longer hangs if an error occurs. </p> + <p> + Own Id: OTP-14471 Aux Id: ERL-413 </p> + </item> + </list> + </section> + +</section> + <section><title>Syntax_Tools 2.1.2</title> <section><title>Improvements and New Features</title> diff --git a/lib/syntax_tools/src/erl_comment_scan.erl b/lib/syntax_tools/src/erl_comment_scan.erl index 07e501e553..e3eb95b819 100644 --- a/lib/syntax_tools/src/erl_comment_scan.erl +++ b/lib/syntax_tools/src/erl_comment_scan.erl @@ -208,7 +208,7 @@ scan_comment([], Cs1, L, Col, M, Ack) -> seen_comment(Cs, Cs1, L, Col, M, Ack) -> %% Compute indentation and strip trailing spaces N = Col - M, - Text = lists:reverse(string:strip(Cs1, left)), + Text = lists:reverse(string:trim(Cs1, leading)), Ack1 = [{L, Col + 1, N, Text} | Ack], scan_lines(Cs, L + 1, 0, 0, Ack1). diff --git a/lib/syntax_tools/src/merl_transform.erl b/lib/syntax_tools/src/merl_transform.erl index b298bc407f..571d7e4d86 100644 --- a/lib/syntax_tools/src/merl_transform.erl +++ b/lib/syntax_tools/src/merl_transform.erl @@ -196,7 +196,7 @@ var_name(V) -> V. var_to_tag(V) when is_integer(V) -> V; var_to_tag(V) -> - list_to_atom(string:to_lower(atom_to_list(V))). + list_to_atom(string:lowercase(atom_to_list(V))). pre_expand_case(Expr, Clauses, Line) -> merl:qquote(Line, "merl:switch(_@expr, _@clauses)", diff --git a/lib/syntax_tools/src/syntax_tools.app.src b/lib/syntax_tools/src/syntax_tools.app.src index 5c6008a5f0..af50b7495b 100644 --- a/lib/syntax_tools/src/syntax_tools.app.src +++ b/lib/syntax_tools/src/syntax_tools.app.src @@ -18,4 +18,4 @@ {applications, [stdlib]}, {env, []}, {runtime_dependencies, - ["compiler-7.0","erts-8.0","kernel-5.0","stdlib-3.0"]}]}. + ["compiler-7.0","erts-9.0","kernel-5.0","stdlib-3.4"]}]}. diff --git a/lib/syntax_tools/vsn.mk b/lib/syntax_tools/vsn.mk index 9b33f1e1f4..e0880d61ee 100644 --- a/lib/syntax_tools/vsn.mk +++ b/lib/syntax_tools/vsn.mk @@ -1 +1 @@ -SYNTAX_TOOLS_VSN = 2.1.2 +SYNTAX_TOOLS_VSN = 2.1.3 diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml index f0df43bf2b..3eaa2058a0 100644 --- a/lib/tools/doc/src/notes.xml +++ b/lib/tools/doc/src/notes.xml @@ -31,6 +31,75 @@ </header> <p>This document describes the changes made to the Tools application.</p> +<section><title>Tools 2.11</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> The predefined Xref analysis <c>locals_not_used</c> + no longer reports unused functions with the + <c>-on_load()</c> attribute.</p> <p> The new predefined + Xref variable <c>OL</c> holds all functions with the + <c>-on_load()</c> attribute. </p> + <p> + Own Id: OTP-14344</p> + </item> + <item> + <p> + In fprof when sampling multiple processes and analyzing + with totals set to true, the output now sums together all + caller and callee entries which concerns the same + function. Previous behaviour was to report each + contributing entry separately.</p> + <p> + Own Id: OTP-14500</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>Lock counting can now be fully toggled at runtime in + the lock counting emulator (<c>-emu_type lcnt</c>). + Everything is enabled by default to match the old + behavior, but specific categories can be toggled at will + with minimal runtime overhead when disabled. Refer to the + documentation on <c>lcnt:rt_mask/1</c> for details.</p> + <p> + Own Id: OTP-13170</p> + </item> + <item> + <p><c>lcnt:collect</c> and <c>lcnt:clear</c> will no + longer block all other threads in the runtime system.</p> + <p> + Own Id: OTP-14412</p> + </item> + <item> + <p> + General Unicode improvements.</p> + <p> + Own Id: OTP-14462</p> + </item> + <item> + <p> + Tools are updated to show Unicode atoms correctly.</p> + <p> + Own Id: OTP-14464</p> + </item> + <item> + <p>Add <c>erlang:iolist_to_iovec/1</c>, which converts an + iolist() to an erlang:iovec(), which suitable for use + with <c>enif_inspect_iovec</c>.</p> + <p> + Own Id: OTP-14520</p> + </item> + </list> + </section> + +</section> + <section><title>Tools 2.10.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl index 5517882ffa..801bbc7461 100644 --- a/lib/tools/src/cover.erl +++ b/lib/tools/src/cover.erl @@ -2439,11 +2439,11 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) -> Timestamp = io_lib:format("~p-~s-~s at ~s:~s:~s", [Y, - string:right(integer_to_list(Mo), 2, $0), - string:right(integer_to_list(D), 2, $0), - string:right(integer_to_list(H), 2, $0), - string:right(integer_to_list(Mi), 2, $0), - string:right(integer_to_list(S), 2, $0)]), + string:pad(integer_to_list(Mo), 2, leading, $0), + string:pad(integer_to_list(D), 2, leading, $0), + string:pad(integer_to_list(H), 2, leading, $0), + string:pad(integer_to_list(Mi), 2, leading, $0), + string:pad(integer_to_list(S), 2, leading, $0)]), H2Bin = unicode:characters_to_binary( ["File generated from ",ErlFile," by COVER ", @@ -2493,12 +2493,12 @@ print_lines(Module, CovLines, InFd, OutFd, L, HTML) -> if N=:=0, HTML=:=true -> LineNoNL = Line -- "\n", Str = " 0", - %%Str = string:right("0", 6, 32), + %%Str = string:pad("0", 6, leading, $\s), RedLine = ["<font color=red>",Str,fill1(), LineNoNL,"</font>\n"], ok = file:write(OutFd, RedLine); N < 1000000 -> - Str = string:right(integer_to_list(N), 6, 32), + Str = string:pad(integer_to_list(N), 6, leading, $\s), ok = file:write(OutFd, [Str,fill1(),Line]); N < 10000000 -> Str = integer_to_list(N), diff --git a/lib/tools/src/fprof.erl b/lib/tools/src/fprof.erl index 2fe42beb03..fb657c2928 100644 --- a/lib/tools/src/fprof.erl +++ b/lib/tools/src/fprof.erl @@ -1136,7 +1136,7 @@ ensure_open(Pid, _Options) when is_pid(Pid) -> ensure_open([], _Options) -> {already_open, undefined}; ensure_open(Filename, Options) when is_atom(Filename); is_list(Filename) -> - file:open(Filename, Options). + file:open(Filename, [{encoding, utf8} | Options]). %%%--------------------------------- %%% Fairly generic utility functions diff --git a/lib/tools/src/tools.app.src b/lib/tools/src/tools.app.src index 8beef49bf9..f8c6aa22cb 100644 --- a/lib/tools/src/tools.app.src +++ b/lib/tools/src/tools.app.src @@ -40,7 +40,7 @@ {env, [{file_util_search_methods,[{"", ""}, {"ebin", "esrc"}, {"ebin", "src"}]} ] }, - {runtime_dependencies, ["stdlib-3.1","runtime_tools-1.8.14", + {runtime_dependencies, ["stdlib-3.4","runtime_tools-1.8.14", "kernel-5.4","erts-9.1","compiler-5.0"]} ] }. diff --git a/lib/tools/src/xref_utils.erl b/lib/tools/src/xref_utils.erl index 02e207d40c..eca751337b 100644 --- a/lib/tools/src/xref_utils.erl +++ b/lib/tools/src/xref_utils.erl @@ -557,12 +557,9 @@ subdir(Dir, SubDir, true) -> %% Avoid "App-01.01" - the zeroes will be lost. filename2appl(File) -> - Pos = string:rstr(File, "-"), - true = Pos > 1, - V = string:sub_string(File, Pos+1), - true = string:len(V) > 0, - VsnT = string:tokens(V, "."), - ApplName = string:sub_string(File, 1, Pos-1), + [ApplName, V] = string:split(File, "-", trailing), + true = string:length(V) > 0, + VsnT = string:lexemes(V, "."), Vsn = [list_to_integer(Vsn) || Vsn <- VsnT], {list_to_atom(ApplName),Vsn}. diff --git a/lib/tools/test/fprof_SUITE.erl b/lib/tools/test/fprof_SUITE.erl index affb45b7a6..8fd164a4b3 100644 --- a/lib/tools/test/fprof_SUITE.erl +++ b/lib/tools/test/fprof_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2016. All Rights Reserved. +%% Copyright Ericsson AB 2001-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -27,7 +27,7 @@ %% Test suites -export([stack_seq/1, tail_seq/1, create_file_slow/1, spawn_simple/1, imm_tail_seq/1, imm_create_file_slow/1, imm_compile/1, - cpu_create_file_slow/1]). + cpu_create_file_slow/1, unicode/1]). %% Other exports -export([create_file_slow/2]). @@ -59,7 +59,7 @@ all() -> false -> [stack_seq, tail_seq, create_file_slow, spawn_simple, imm_tail_seq, imm_create_file_slow, imm_compile, - cpu_create_file_slow] + cpu_create_file_slow, unicode] end. @@ -533,6 +533,17 @@ cpu_create_file_slow(Config) when is_list(Config) -> TestResult. +unicode(Config) when is_list(Config) -> + DataDir = proplists:get_value(data_dir, Config), + SourceFile = filename:join(DataDir, "fprof_unicode.erl"), + PrivDir = proplists:get_value(priv_dir, Config), + AnalysisFile = filename:join(PrivDir, "fprof_unicode.analysis"), + {ok, fprof_unicode} = compile:file(SourceFile, [{outdir, PrivDir}]), + true = code:add_path(PrivDir), + fprof:apply(fprof_unicode, t, []), + ok = fprof:profile(dump, AnalysisFile), + ok = fprof:analyse(dest, AnalysisFile). + %%%--------------------------------------------------------------------- %%% Functions to test %%%--------------------------------------------------------------------- diff --git a/lib/tools/test/fprof_SUITE_data/fprof_unicode.erl b/lib/tools/test/fprof_SUITE_data/fprof_unicode.erl new file mode 100644 index 0000000000..8b58efc5fe --- /dev/null +++ b/lib/tools/test/fprof_SUITE_data/fprof_unicode.erl @@ -0,0 +1,36 @@ +-module(fprof_unicode). + +-export([t/0, 'кирилли́ческий атом'/0, annan/0, c_break/1, + 'кирилли́ческий атомB'/1]). + +t() -> + _Atom = 'кирилли́ческий атом', + 'кирилли́ческий атом'(). + +'кирилли́ческий атом'() -> + 'кирилли́ческий атом'('кирилли́ческий атом'). + +'кирилли́ческий атом'(_Atom) -> + self() ! 'кирилли́ческий атом', + G = fun (X) -> + catch foo:bar() + end, + G("кирилли́ческий атом"), % line 17 + Pid = spawn_link(fun() -> waiting() end), + true = register('кирилли́ческий атом', Pid), + F = fun() -> 'кирилли́ческий атом' end, + F(). + +annan() -> + foo. + +waiting() -> + receive + X -> X + end. + +c_break(_B) -> + true. + +'кирилли́ческий атомB'(_B) -> + true. diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk index 831d850217..b9249ae45c 100644 --- a/lib/tools/vsn.mk +++ b/lib/tools/vsn.mk @@ -1 +1 @@ -TOOLS_VSN = 2.10.1 +TOOLS_VSN = 2.11 diff --git a/lib/wx/api_gen/gl_gen_erl.erl b/lib/wx/api_gen/gl_gen_erl.erl index 3ad14825dd..45f5fd8f4c 100644 --- a/lib/wx/api_gen/gl_gen_erl.erl +++ b/lib/wx/api_gen/gl_gen_erl.erl @@ -35,6 +35,9 @@ open_write/1, open_write/2, close/0, erl_copyright/0, w/2, args/3, args/4, strip_name/2]). + +-define(HTTP_TOP, "https://www.khronos.org/registry/OpenGL-Refpages/"). + gl_defines(Defs) -> open_write("../include/gl.hrl"), erl_copyright(), @@ -96,7 +99,7 @@ gl_api(Fs) -> w("~n%% OPENGL API~n~n", []), w("%% This file is generated DO NOT EDIT~n~n", []), w("%% @doc Standard OpenGL api.~n", []), - w("%% See <a href=\"http://www.opengl.org/sdk/docs/man/\">www.opengl.org</a>~n",[]), + w("%% See <a href=\""++ ?HTTP_TOP ++ "\">www.khronos.org</a>~n",[]), w("%%~n", []), w("%% Booleans are represented by integers 0 and 1.~n~n", []), @@ -158,7 +161,7 @@ glu_api(Fs) -> w("~n%% OPENGL UTILITY API~n~n", []), w("%% This file is generated DO NOT EDIT~n~n", []), w("%% @doc A part of the standard OpenGL Utility api.~n", []), - w("%% See <a href=\"http://www.opengl.org/sdk/docs/man/\">www.opengl.org</a>~n",[]), + w("%% See <a href=\""++ ?HTTP_TOP ++ "\">www.khronos.org</a>~n",[]), w("%%~n", []), w("%% Booleans are represented by integers 0 and 1.~n~n", []), @@ -300,8 +303,7 @@ gen_doc(Name0, Alt, Export) -> Name = doc_name(Name0, Alt), case get({doc, Name}) of undefined -> - GLDoc = "http://www.opengl.org/sdk/docs/man/xhtml/", - case parse_doc(Name, _Dir1 ="gl_man4", _Dir2="gl_man2") of + case parse_doc(Name, Dir1 ="gl_man4", Dir2="gl_man2") of {error, _} -> case reverse(Name) of "BRA" ++ _ -> ok; @@ -311,13 +313,18 @@ gen_doc(Name0, Alt, Export) -> %% [Name, Name0, Dir1, Dir2]), ok end, - w("%% @doc ~s~n%%~n%% See <a href=\"~s~s.xml\">external</a> documentation.~n", - [Name, GLDoc, Name]); - Doc -> + w("%% @doc ~s~n%%~n" + "%% See <a href=\"~s\">external</a> documentation.~n", + [Name, ?HTTP_TOP]); + {Found, Doc} -> + {Dir,Ext} = case Found of + Dir1 -> {"gl4/html", "xhtml"}; + Dir2 -> {"gl2.1/xhtml", "xml"} + end, put({doc, Name}, Export), format_doc(Doc, ?LINE_LEN), - w("~n%%~n%% See <a href=\"~s~s.xml\">external</a> documentation.~n", - [GLDoc, Name]) + w("~n%%~n%% See <a href=\"~s~s/~s.~s\">external</a> documentation.~n", + [?HTTP_TOP, Dir, Name, Ext]) end; Where -> w("%% @doc ~n", []), @@ -327,9 +334,12 @@ gen_doc(Name0, Alt, Export) -> parse_doc(Name, Dir1, Dir2) -> case gl_scan_doc:file(filename:join(Dir1, Name++".xml"), []) of {error, {_, "no such" ++ _}} -> - gl_scan_doc:file(filename:join(Dir2, Name++".xml"), []); + case gl_scan_doc:file(filename:join(Dir2, Name++".xml"), []) of + {error, _} = Err -> Err; + Doc -> {Dir2, Doc} + end; Doc -> - Doc + {Dir1, Doc} end. format_doc(Strs, Count) when Count < 0 -> diff --git a/lib/wx/api_gen/gl_scan_doc.erl b/lib/wx/api_gen/gl_scan_doc.erl index 0a1c25ae13..6ed5438608 100644 --- a/lib/wx/api_gen/gl_scan_doc.erl +++ b/lib/wx/api_gen/gl_scan_doc.erl @@ -209,6 +209,10 @@ gen_output({startElement, _Uri, "para", _QName, _Attributes}, #state{gen_output= State#state{str=[para|Str]} end; +gen_output({endElement, _Uri, "para", _QName}, #state{gen_output=true, str=Str} = State) -> + %% Pick only the first paragraph in the descriptions + State#state{gen_output=false}; + %% gen_output({startElement, _Uri, What, _QName, _Attributes}, State) -> %% io:format("Skipped ~s~n",[What]), %% State; diff --git a/lib/wx/doc/src/notes.xml b/lib/wx/doc/src/notes.xml index d300ab5128..599b5b64fd 100644 --- a/lib/wx/doc/src/notes.xml +++ b/lib/wx/doc/src/notes.xml @@ -32,6 +32,36 @@ <p>This document describes the changes made to the wxErlang application.</p> +<section><title>Wx 1.8.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Do not deprecate + <c>wxGraphicsContext:createLinearGradientBrush/7</c> and + <c>wxGraphicsContext:createRadialGradientBrush/8</c> + which are still available in wxWidgets-3.0.</p> + <p> + Own Id: OTP-14539</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + General Unicode improvements.</p> + <p> + Own Id: OTP-14462</p> + </item> + </list> + </section> + +</section> + <section><title>Wx 1.8.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/wx/examples/simple/hello.erl b/lib/wx/examples/simple/hello.erl index 36bce56329..bf870c6f3e 100644 --- a/lib/wx/examples/simple/hello.erl +++ b/lib/wx/examples/simple/hello.erl @@ -29,7 +29,6 @@ -include_lib("wx/include/wx.hrl"). -export([start/0]). --compile(export_all). start() -> Wx = wx:new(), diff --git a/lib/wx/examples/simple/hello2.erl b/lib/wx/examples/simple/hello2.erl index 671b23d892..b9da622b6b 100644 --- a/lib/wx/examples/simple/hello2.erl +++ b/lib/wx/examples/simple/hello2.erl @@ -29,8 +29,9 @@ -module(hello2). -include_lib("wx/include/wx.hrl"). --export([start/0]). --compile(export_all). +-export([start/0, + init/1, handle_info/2, handle_event/2, handle_call/3, + code_change/3, terminate/2]). -behavoiur(wx_object). diff --git a/lib/wx/examples/simple/menu.erl b/lib/wx/examples/simple/menu.erl index 479df1ef98..93573fb97d 100644 --- a/lib/wx/examples/simple/menu.erl +++ b/lib/wx/examples/simple/menu.erl @@ -29,7 +29,6 @@ -include_lib("wx/include/wx.hrl"). -export([start/0]). --compile(export_all). %%%Lots of IDs to declare! -define(menuID_FILE_QUIT, ?wxID_EXIT). @@ -228,36 +227,6 @@ create_menubar_menu() -> %% %% %% -create_submenu_menu() -> - SubMenuMenu = wxMenu:new(), - wxMenu:append(SubMenuMenu, wxMenuItem:new([ - {id, ?menuID_SUBMENU_NORMAL}, - {text, "&Normal submenu item"}, - {help, "Disabled submenu item"} - ])), - %% note different way of adding check menu item - wxMenu:appendCheckItem(SubMenuMenu, - ?menuID_SUBMENU_CHECK, - "&Check submenu item", - [{help, "Check submenu item"}]), - wxMenu:appendRadioItem(SubMenuMenu, - ?menuID_SUBMENU_RADIO_1, - "Radio item &1", - [{help, "Radio item"}]), - wxMenu:appendRadioItem(SubMenuMenu, - ?menuID_SUBMENU_RADIO_2, - "Radio item &2", - [{help, "Radio item"}]), - wxMenu:appendRadioItem(SubMenuMenu, - ?menuID_SUBMENU_RADIO_3, - "Radio item &3", - [{help, "Radio item"}]), - SubMenuMenu. - - -%% -%% -%% create_menu_menu() -> MenuMenu = wxMenu:new(), wxMenu:append(MenuMenu, wxMenuItem:new([ diff --git a/lib/wx/examples/simple/minimal.erl b/lib/wx/examples/simple/minimal.erl index 9f6365e008..346f86433a 100644 --- a/lib/wx/examples/simple/minimal.erl +++ b/lib/wx/examples/simple/minimal.erl @@ -29,7 +29,7 @@ -include_lib("wx/include/wx.hrl"). -export([start/0]). --compile(export_all). + start() -> Wx = wx:new(), diff --git a/lib/wx/examples/sudoku/sudoku.erl b/lib/wx/examples/sudoku/sudoku.erl index 97f35870de..353f90d86f 100644 --- a/lib/wx/examples/sudoku/sudoku.erl +++ b/lib/wx/examples/sudoku/sudoku.erl @@ -26,9 +26,8 @@ -module(sudoku). --export([go/0]). +-export([go/0, start/0]). --compile(export_all). -include("sudoku.hrl"). diff --git a/lib/wx/examples/sudoku/sudoku_game.erl b/lib/wx/examples/sudoku/sudoku_game.erl index 1e579a7c88..aa15c05653 100644 --- a/lib/wx/examples/sudoku/sudoku_game.erl +++ b/lib/wx/examples/sudoku/sudoku_game.erl @@ -18,7 +18,9 @@ %% %CopyrightEnd% -module(sudoku_game). --compile(export_all). + +-export([init/1, + indx/1, rcm/1, level/1]). -include("sudoku.hrl"). init(GFX) -> @@ -128,17 +130,6 @@ rebuild_all(_, S0) -> add(rcm(Indx),Val,Acc) end, S1, Solved). -is_ok({RI,CI,MI}, Vals) -> - [Ri,Ci,Mi] = all(RI,CI,MI), - case element(indx(RI,CI),Vals) of - 0 -> true; - Val -> - Vs = [[element(indx(R,C),Vals)||{R,C} <- Obs, - not ((R == RI) and (C == CI))] - || Obs <- [Ri,Ci,Mi]], - not lists:member(Val,lists:flatten(Vs)) - end. - test() -> %% Known to solvable [{{1,2},6}, {{1,4},1}, {{1,6},4}, {{1,8},5}, {{2,3},8}, {{2,4},3}, {{2,6},5}, {{2,7},6}, @@ -377,14 +368,6 @@ get_poss([H|R],What,Tot) -> %% io:format("~p~n",[H]), get_poss(R,What, gb_sets:union(element(H,What),Tot)). -r2rs(R) -> - R0 = (R-1)*3, - [R0+1,R0+2,R0+3]. - -c2cs(C) -> - C0 = (C-1) rem 9, - [C0+1, C0+10, C0+19]. - mindx(row,Indx) -> {R,_C,M} = rcm(Indx), mindx(R,M); diff --git a/lib/wx/examples/sudoku/sudoku_gui.erl b/lib/wx/examples/sudoku/sudoku_gui.erl index 81d20814e1..4c4ad83cd7 100644 --- a/lib/wx/examples/sudoku/sudoku_gui.erl +++ b/lib/wx/examples/sudoku/sudoku_gui.erl @@ -28,7 +28,7 @@ -export([init/1, handle_info/2, handle_call/3, handle_cast/2, handle_event/2, terminate/2, code_change/3]). --compile(export_all). +-export([new/1]). -behaviour(wx_object). diff --git a/lib/wx/examples/xrc/xrc.erl b/lib/wx/examples/xrc/xrc.erl index 729f4ad0db..7e967777d2 100644 --- a/lib/wx/examples/xrc/xrc.erl +++ b/lib/wx/examples/xrc/xrc.erl @@ -23,7 +23,7 @@ %%%------------------------------------------------------------------- -module(xrc). --compile(export_all). +-export([start/0]). -include("../../include/wx.hrl"). diff --git a/lib/wx/src/gen/gl.erl b/lib/wx/src/gen/gl.erl index 4a178ea1e4..47afb25c5d 100644 --- a/lib/wx/src/gen/gl.erl +++ b/lib/wx/src/gen/gl.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2016. All Rights Reserved. +%% Copyright Ericsson AB 2008-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -22,7 +22,7 @@ %% This file is generated DO NOT EDIT %% @doc Standard OpenGL api. -%% See <a href="http://www.opengl.org/sdk/docs/man/">www.opengl.org</a> +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">www.khronos.org</a> %% %% Booleans are represented by integers 0 and 1. @@ -324,7 +324,7 @@ send_bin(Tuple) when is_tuple(Tuple) -> %% value is then masked with 2 m-1, where m is the number of bits in a color index stored %% in the frame buffer. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearIndex.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glClearIndex.xml">external</a> documentation. -spec clearIndex(C) -> 'ok' when C :: float(). clearIndex(C) -> cast(5037, <<C:?GLfloat>>). @@ -335,7 +335,7 @@ clearIndex(C) -> %% to clear the color buffers. Values specified by ``gl:clearColor'' are clamped to the %% range [0 1]. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearColor.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glClearColor.xhtml">external</a> documentation. -spec clearColor(Red, Green, Blue, Alpha) -> 'ok' when Red :: clamp(),Green :: clamp(),Blue :: clamp(),Alpha :: clamp(). clearColor(Red,Green,Blue,Alpha) -> cast(5038, <<Red:?GLclampf,Green:?GLclampf,Blue:?GLclampf,Alpha:?GLclampf>>). @@ -346,26 +346,7 @@ clearColor(Red,Green,Blue,Alpha) -> %% , ``gl:clearDepth'', and ``gl:clearStencil''. Multiple color buffers can be cleared %% simultaneously by selecting more than one buffer at a time using {@link gl:drawBuffer/1} . %% -%% The pixel ownership test, the scissor test, dithering, and the buffer writemasks affect -%% the operation of ``gl:clear''. The scissor box bounds the cleared region. Alpha function, -%% blend function, logical operation, stenciling, texture mapping, and depth-buffering are -%% ignored by ``gl:clear''. -%% -%% ``gl:clear'' takes a single argument that is the bitwise OR of several values indicating -%% which buffer is to be cleared. -%% -%% The values are as follows: -%% -%% `?GL_COLOR_BUFFER_BIT': Indicates the buffers currently enabled for color writing. -%% -%% `?GL_DEPTH_BUFFER_BIT': Indicates the depth buffer. -%% -%% `?GL_STENCIL_BUFFER_BIT': Indicates the stencil buffer. -%% -%% The value to which each buffer is cleared depends on the setting of the clear value for -%% that buffer. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClear.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glClear.xhtml">external</a> documentation. -spec clear(Mask) -> 'ok' when Mask :: integer(). clear(Mask) -> cast(5039, <<Mask:?GLbitfield>>). @@ -378,11 +359,7 @@ clear(Mask) -> %% to the corresponding bit in the color index buffer (or buffers). Where a 0 (zero) appears, %% the corresponding bit is write-protected. %% -%% This mask is used only in color index mode, and it affects only the buffers currently -%% selected for writing (see {@link gl:drawBuffer/1} ). Initially, all bits are enabled for -%% writing. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIndexMask.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glIndexMask.xml">external</a> documentation. -spec indexMask(Mask) -> 'ok' when Mask :: integer(). indexMask(Mask) -> cast(5040, <<Mask:?GLuint>>). @@ -395,10 +372,7 @@ indexMask(Mask) -> %% is `?GL_FALSE', for example, no change is made to the red component of any pixel %% in any of the color buffers, regardless of the drawing operation attempted. %% -%% Changes to individual bits of components cannot be controlled. Rather, changes are either -%% enabled or disabled for entire color components. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorMask.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glColorMask.xhtml">external</a> documentation. -spec colorMask(Red, Green, Blue, Alpha) -> 'ok' when Red :: 0|1,Green :: 0|1,Blue :: 0|1,Alpha :: 0|1. colorMask(Red,Green,Blue,Alpha) -> cast(5041, <<Red:?GLboolean,Green:?GLboolean,Blue:?GLboolean,Alpha:?GLboolean>>). @@ -411,37 +385,7 @@ colorMask(Red,Green,Blue,Alpha) -> %% testing is enabled. By default, it is not enabled. (See {@link gl:enable/1} and {@link gl:enable/1} %% of `?GL_ALPHA_TEST'.) %% -%% `Func' and `Ref' specify the conditions under which the pixel is drawn. The -%% incoming alpha value is compared to `Ref' using the function specified by `Func' . -%% If the value passes the comparison, the incoming fragment is drawn if it also passes subsequent -%% stencil and depth buffer tests. If the value fails the comparison, no change is made to -%% the frame buffer at that pixel location. The comparison functions are as follows: -%% -%% `?GL_NEVER': Never passes. -%% -%% `?GL_LESS': Passes if the incoming alpha value is less than the reference value. -%% -%% `?GL_EQUAL': Passes if the incoming alpha value is equal to the reference value. -%% -%% `?GL_LEQUAL': Passes if the incoming alpha value is less than or equal to the reference -%% value. -%% -%% `?GL_GREATER': Passes if the incoming alpha value is greater than the reference -%% value. -%% -%% `?GL_NOTEQUAL': Passes if the incoming alpha value is not equal to the reference -%% value. -%% -%% `?GL_GEQUAL': Passes if the incoming alpha value is greater than or equal to the -%% reference value. -%% -%% `?GL_ALWAYS': Always passes (initial value). -%% -%% ``gl:alphaFunc'' operates on all pixel write operations, including those resulting from -%% the scan conversion of points, lines, polygons, and bitmaps, and from pixel draw and copy -%% operations. ``gl:alphaFunc'' does not affect screen clear operations. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAlphaFunc.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glAlphaFunc.xml">external</a> documentation. -spec alphaFunc(Func, Ref) -> 'ok' when Func :: enum(),Ref :: clamp(). alphaFunc(Func,Ref) -> cast(5042, <<Func:?GLenum,Ref:?GLclampf>>). @@ -453,70 +397,7 @@ alphaFunc(Func,Ref) -> %% is initially disabled. Use {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_BLEND' %% to enable and disable blending. %% -%% ``gl:blendFunc'' defines the operation of blending for all draw buffers when it is enabled. -%% ``gl:blendFunci'' defines the operation of blending for a single draw buffer specified -%% by `Buf' when enabled for that draw buffer. `Sfactor' specifies which method -%% is used to scale the source color components. `Dfactor' specifies which method is -%% used to scale the destination color components. Both parameters must be one of the following -%% symbolic constants: `?GL_ZERO', `?GL_ONE', `?GL_SRC_COLOR', `?GL_ONE_MINUS_SRC_COLOR' -%% , `?GL_DST_COLOR', `?GL_ONE_MINUS_DST_COLOR', `?GL_SRC_ALPHA', `?GL_ONE_MINUS_SRC_ALPHA' -%% , `?GL_DST_ALPHA', `?GL_ONE_MINUS_DST_ALPHA', `?GL_CONSTANT_COLOR', `?GL_ONE_MINUS_CONSTANT_COLOR' -%% , `?GL_CONSTANT_ALPHA', `?GL_ONE_MINUS_CONSTANT_ALPHA', `?GL_SRC_ALPHA_SATURATE' -%% , `?GL_SRC1_COLOR', `?GL_ONE_MINUS_SRC1_COLOR', `?GL_SRC1_ALPHA', and `?GL_ONE_MINUS_SRC1_ALPHA' -%% . The possible methods are described in the following table. Each method defines four -%% scale factors, one each for red, green, blue, and alpha. In the table and in subsequent -%% equations, first source, second source and destination color components are referred to -%% as (R s0 G s0 B s0 A s0), (R s1 G s1 B s1 A s1) and (R d G d B d A d), respectively. The color specified by {@link gl:blendColor/4} is referred to -%% as (R c G c B c A c). They are understood to have integer values between 0 and (k R k G k B k A), where -%% -%% k c=2(m c)-1 -%% -%% and (m R m G m B m A) is the number of red, green, blue, and alpha bitplanes. -%% -%% Source and destination scale factors are referred to as (s R s G s B s A) and (d R d G d B d A). The scale factors described -%% in the table, denoted (f R f G f B f A), represent either source or destination factors. All scale factors -%% have range [0 1]. -%% -%% <table><tbody><tr><td>` Parameter '</td><td>(f R f G f B f A)</td></tr></tbody><tbody><tr><td>`?GL_ZERO' -%% </td><td>(0 0 0 0)</td></tr><tr><td>`?GL_ONE'</td><td>(1 1 1 1)</td></tr><tr><td>`?GL_SRC_COLOR'</td> -%% <td>(R s0 k/R G s0 k/G B s0 k/B A s0 k/A)</td></tr><tr><td>`?GL_ONE_MINUS_SRC_COLOR'</td><td>(1 1 1 1)-(R s0 k/R G s0 k/G B s0 k/B -%% A s0 k/A)</td></tr><tr><td>`?GL_DST_COLOR' -%% </td><td>(R d k/R G d k/G B d k/B A d k/A)</td></tr><tr><td>`?GL_ONE_MINUS_DST_COLOR'</td><td>(1 1 1 1)-(R d k/R G d k/G B d k/B -%% A d k/A)</td></tr><tr><td>`?GL_SRC_ALPHA' -%% </td><td>(A s0 k/A A s0 k/A A s0 k/A A s0 k/A)</td></tr><tr><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td>(1 1 1 1)-(A s0 k/A A s0 k/A A s0 -%% k/A A s0 k/A)</td></tr><tr><td>`?GL_DST_ALPHA' -%% </td><td>(A d k/A A d k/A A d k/A A d k/A)</td></tr><tr><td>`?GL_ONE_MINUS_DST_ALPHA'</td><td>(1 1 1 1)-(A d k/A A d k/A A d k/A -%% A d k/A)</td></tr><tr><td>`?GL_CONSTANT_COLOR' -%% </td><td>(R c G c B c A c)</td></tr><tr><td>`?GL_ONE_MINUS_CONSTANT_COLOR'</td><td>(1 1 1 1)-(R c G c B c A c)</td></tr><tr><td> -%% `?GL_CONSTANT_ALPHA'</td><td>(A c A c A c A c)</td></tr><tr><td>`?GL_ONE_MINUS_CONSTANT_ALPHA'</td> -%% <td>(1 1 1 1)-(A c A c A c A c)</td></tr><tr><td>`?GL_SRC_ALPHA_SATURATE'</td><td>(i i i 1)</td></tr><tr><td>`?GL_SRC1_COLOR' -%% </td><td>(R s1 k/R G s1 k/G B s1 k/B A s1 k/A)</td></tr><tr><td>`?GL_ONE_MINUS_SRC1_COLOR'</td><td>(1 1 1 1)-(R s1 k/R G s1 k/G B -%% s1 k/B A s1 k/A)</td></tr><tr><td>`?GL_SRC1_ALPHA' -%% </td><td>(A s1 k/A A s1 k/A A s1 k/A A s1 k/A)</td></tr><tr><td>`?GL_ONE_MINUS_SRC1_ALPHA'</td><td>(1 1 1 1)-(A s1 k/A A s1 k/A A -%% s1 k/A A s1 k/A)</td></tr></tbody></table> -%% -%% -%% In the table, -%% -%% i=min(A s k A-A d) k/A -%% -%% To determine the blended RGBA values of a pixel, the system uses the following equations: -%% -%% -%% R d=min(k R R s s R+R d d R) G d=min(k G G s s G+G d d G) B d=min(k B B s s B+B d d B) A d=min(k A A s s A+A d d A) -%% -%% Despite the apparent precision of the above equations, blending arithmetic is not exactly -%% specified, because blending operates with imprecise integer color values. However, a blend -%% factor that should be equal to 1 is guaranteed not to modify its multiplicand, and a blend -%% factor equal to 0 reduces its multiplicand to 0. For example, when `Sfactor' is `?GL_SRC_ALPHA' -%% , `Dfactor' is `?GL_ONE_MINUS_SRC_ALPHA', and A s is equal to k A, the equations -%% reduce to simple replacement: -%% -%% R d=R s G d=G s B d=B s A d=A s -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendFunc.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendFunc.xhtml">external</a> documentation. -spec blendFunc(Sfactor, Dfactor) -> 'ok' when Sfactor :: enum(),Dfactor :: enum(). blendFunc(Sfactor,Dfactor) -> cast(5043, <<Sfactor:?GLenum,Dfactor:?GLenum>>). @@ -528,25 +409,7 @@ blendFunc(Sfactor,Dfactor) -> %% buffer. To enable or disable the logical operation, call {@link gl:enable/1} and {@link gl:enable/1} %% using the symbolic constant `?GL_COLOR_LOGIC_OP'. The initial value is disabled. %% -%% <table><tbody><tr><td>` Opcode '</td><td>` Resulting Operation '</td></tr></tbody> -%% <tbody><tr><td>`?GL_CLEAR'</td><td> 0 </td></tr><tr><td>`?GL_SET'</td><td> 1 </td> -%% </tr><tr><td>`?GL_COPY'</td><td> s </td></tr><tr><td>`?GL_COPY_INVERTED'</td><td> -%% ~s </td></tr><tr><td>`?GL_NOOP'</td><td> d </td></tr><tr><td>`?GL_INVERT'</td><td> -%% ~d </td></tr><tr><td>`?GL_AND'</td><td> s & d </td></tr><tr><td>`?GL_NAND'</td> -%% <td> ~(s & d) </td></tr><tr><td>`?GL_OR'</td><td> s | d </td></tr><tr><td>`?GL_NOR' -%% </td><td> ~(s | d) </td></tr><tr><td>`?GL_XOR'</td><td> s ^ d </td></tr><tr><td>`?GL_EQUIV' -%% </td><td> ~(s ^ d) </td></tr><tr><td>`?GL_AND_REVERSE'</td><td> s & ~d </td></tr> -%% <tr><td>`?GL_AND_INVERTED'</td><td> ~s & d </td></tr><tr><td>`?GL_OR_REVERSE' -%% </td><td> s | ~d </td></tr><tr><td>`?GL_OR_INVERTED'</td><td> ~s | d </td></tr></tbody> -%% </table> -%% -%% `Opcode' is a symbolic constant chosen from the list above. In the explanation of -%% the logical operations, `s' represents the incoming color and `d' represents -%% the color in the frame buffer. Standard C-language operators are used. As these bitwise -%% operators suggest, the logical operation is applied independently to each bit pair of -%% the source and destination colors. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLogicOp.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glLogicOp.xhtml">external</a> documentation. -spec logicOp(Opcode) -> 'ok' when Opcode :: enum(). logicOp(Opcode) -> cast(5044, <<Opcode:?GLenum>>). @@ -559,10 +422,7 @@ logicOp(Opcode) -> %% commands with the argument `?GL_CULL_FACE'. Facets include triangles, quadrilaterals, %% polygons, and rectangles. %% -%% {@link gl:frontFace/1} specifies which of the clockwise and counterclockwise facets are -%% front-facing and back-facing. See {@link gl:frontFace/1} . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCullFace.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCullFace.xhtml">external</a> documentation. -spec cullFace(Mode) -> 'ok' when Mode :: enum(). cullFace(Mode) -> cast(5045, <<Mode:?GLenum>>). @@ -574,18 +434,7 @@ cullFace(Mode) -> %% rendering of the image. To enable and disable elimination of back-facing polygons, call {@link gl:enable/1} %% and {@link gl:enable/1} with argument `?GL_CULL_FACE'. %% -%% The projection of a polygon to window coordinates is said to have clockwise winding if -%% an imaginary object following the path from its first vertex, its second vertex, and so -%% on, to its last vertex, and finally back to its first vertex, moves in a clockwise direction -%% about the interior of the polygon. The polygon's winding is said to be counterclockwise -%% if the imaginary object following the same path moves in a counterclockwise direction -%% about the interior of the polygon. ``gl:frontFace'' specifies whether polygons with -%% clockwise winding in window coordinates, or counterclockwise winding in window coordinates, -%% are taken to be front-facing. Passing `?GL_CCW' to `Mode' selects counterclockwise -%% polygons as front-facing; `?GL_CW' selects clockwise polygons as front-facing. By -%% default, counterclockwise polygons are taken to be front-facing. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFrontFace.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glFrontFace.xhtml">external</a> documentation. -spec frontFace(Mode) -> 'ok' when Mode :: enum(). frontFace(Mode) -> cast(5046, <<Mode:?GLenum>>). @@ -597,7 +446,7 @@ frontFace(Mode) -> %% will be used to rasterize points. Otherwise, the value written to the shading language %% built-in variable gl_PointSize will be used. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPointSize.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPointSize.xhtml">external</a> documentation. -spec pointSize(Size) -> 'ok' when Size :: float(). pointSize(Size) -> cast(5047, <<Size:?GLfloat>>). @@ -609,27 +458,7 @@ pointSize(Size) -> %% is enabled. To enable and disable line antialiasing, call {@link gl:enable/1} and {@link gl:enable/1} %% with argument `?GL_LINE_SMOOTH'. Line antialiasing is initially disabled. %% -%% If line antialiasing is disabled, the actual width is determined by rounding the supplied -%% width to the nearest integer. (If the rounding results in the value 0, it is as if the -%% line width were 1.) If |&Delta; x|>=|&Delta; y|, `i' pixels are filled in each column that is rasterized, -%% where `i' is the rounded value of `Width' . Otherwise, `i' pixels are filled -%% in each row that is rasterized. -%% -%% If antialiasing is enabled, line rasterization produces a fragment for each pixel square -%% that intersects the region lying within the rectangle having width equal to the current -%% line width, length equal to the actual length of the line, and centered on the mathematical -%% line segment. The coverage value for each fragment is the window coordinate area of the -%% intersection of the rectangular region with the corresponding pixel square. This value -%% is saved and used in the final rasterization step. -%% -%% Not all widths can be supported when line antialiasing is enabled. If an unsupported -%% width is requested, the nearest supported width is used. Only width 1 is guaranteed to -%% be supported; others depend on the implementation. Likewise, there is a range for aliased -%% line widths as well. To query the range of supported widths and the size difference between -%% supported widths within the range, call {@link gl:getBooleanv/1} with arguments `?GL_ALIASED_LINE_WIDTH_RANGE' -%% , `?GL_SMOOTH_LINE_WIDTH_RANGE', and `?GL_SMOOTH_LINE_WIDTH_GRANULARITY'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLineWidth.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glLineWidth.xhtml">external</a> documentation. -spec lineWidth(Width) -> 'ok' when Width :: float(). lineWidth(Width) -> cast(5048, <<Width:?GLfloat>>). @@ -641,27 +470,7 @@ lineWidth(Width) -> %% stipple pattern `Pattern' , the repeat count `Factor' , and an integer stipple %% counter s. %% -%% Counter s is reset to 0 whenever {@link gl:'begin'/1} is called and before each line segment -%% of a {@link gl:'begin'/1} (`?GL_LINES')/ {@link gl:'begin'/1} sequence is generated. It is -%% incremented after each fragment of a unit width aliased line segment is generated or after -%% each i fragments of an i width line segment are generated. The i fragments associated -%% with count s are masked out if -%% -%% `Pattern' bit (s/factor)% 16 -%% -%% is 0, otherwise these fragments are sent to the frame buffer. Bit zero of `Pattern' -%% is the least significant bit. -%% -%% Antialiased lines are treated as a sequence of 1×width rectangles for purposes of stippling. -%% Whether rectangle s is rasterized or not depends on the fragment rule described for -%% aliased lines, counting rectangles rather than groups of fragments. -%% -%% To enable and disable line stippling, call {@link gl:enable/1} and {@link gl:enable/1} -%% with argument `?GL_LINE_STIPPLE'. When enabled, the line stipple pattern is applied -%% as described above. When disabled, it is as if the pattern were all 1's. Initially, line -%% stippling is disabled. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLineStipple.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLineStipple.xml">external</a> documentation. -spec lineStipple(Factor, Pattern) -> 'ok' when Factor :: integer(),Pattern :: integer(). lineStipple(Factor,Pattern) -> cast(5049, <<Factor:?GLint,Pattern:?GLushort>>). @@ -674,22 +483,7 @@ lineStipple(Factor,Pattern) -> %% polygon's vertices are lit and the polygon is clipped and possibly culled before these %% modes are applied. %% -%% Three modes are defined and can be specified in `Mode' : -%% -%% `?GL_POINT': Polygon vertices that are marked as the start of a boundary edge are -%% drawn as points. Point attributes such as `?GL_POINT_SIZE' and `?GL_POINT_SMOOTH' -%% control the rasterization of the points. Polygon rasterization attributes other than `?GL_POLYGON_MODE' -%% have no effect. -%% -%% `?GL_LINE': Boundary edges of the polygon are drawn as line segments. Line attributes -%% such as `?GL_LINE_WIDTH' and `?GL_LINE_SMOOTH' control the rasterization of -%% the lines. Polygon rasterization attributes other than `?GL_POLYGON_MODE' have no -%% effect. -%% -%% `?GL_FILL': The interior of the polygon is filled. Polygon attributes such as `?GL_POLYGON_SMOOTH' -%% control the rasterization of the polygon. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPolygonMode.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPolygonMode.xhtml">external</a> documentation. -spec polygonMode(Face, Mode) -> 'ok' when Face :: enum(),Mode :: enum(). polygonMode(Face,Mode) -> cast(5050, <<Face:?GLenum,Mode:?GLenum>>). @@ -704,10 +498,7 @@ polygonMode(Face,Mode) -> %% a resolvable offset for a given implementation. The offset is added before the depth test %% is performed and before the value is written into the depth buffer. %% -%% ``gl:polygonOffset'' is useful for rendering hidden-line images, for applying decals -%% to surfaces, and for rendering solids with highlighted edges. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPolygonOffset.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPolygonOffset.xhtml">external</a> documentation. -spec polygonOffset(Factor, Units) -> 'ok' when Factor :: float(),Units :: float(). polygonOffset(Factor,Units) -> cast(5051, <<Factor:?GLfloat,Units:?GLfloat>>). @@ -718,27 +509,7 @@ polygonOffset(Factor,Units) -> %% fragments produced by rasterization, creating a pattern. Stippling is independent of polygon %% antialiasing. %% -%% `Pattern' is a pointer to a 32×32 stipple pattern that is stored in memory just -%% like the pixel data supplied to a {@link gl:drawPixels/5} call with height and `width' -%% both equal to 32, a pixel format of `?GL_COLOR_INDEX', and data type of `?GL_BITMAP' -%% . That is, the stipple pattern is represented as a 32×32 array of 1-bit color indices -%% packed in unsigned bytes. {@link gl:pixelStoref/2} parameters like `?GL_UNPACK_SWAP_BYTES' -%% and `?GL_UNPACK_LSB_FIRST' affect the assembling of the bits into a stipple pattern. -%% Pixel transfer operations (shift, offset, pixel map) are not applied to the stipple image, -%% however. -%% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a stipple pattern is specified, `Pattern' is -%% treated as a byte offset into the buffer object's data store. -%% -%% To enable and disable polygon stippling, call {@link gl:enable/1} and {@link gl:enable/1} -%% with argument `?GL_POLYGON_STIPPLE'. Polygon stippling is initially disabled. If -%% it's enabled, a rasterized polygon fragment with window coordinates x w and y w is -%% sent to the next stage of the GL if and only if the ( x w% 32)th bit in the ( y w% 32)th -%% row of the stipple pattern is 1 (one). When polygon stippling is disabled, it is as if -%% the stipple pattern consists of all 1's. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPolygonStipple.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPolygonStipple.xml">external</a> documentation. -spec polygonStipple(Mask) -> 'ok' when Mask :: binary(). polygonStipple(Mask) -> send_bin(Mask), @@ -753,11 +524,7 @@ polygonStipple(Mask) -> %% Unlike {@link gl:readPixels/7} , however, pixel transfer operations (shift, offset, pixel %% map) are not applied to the returned stipple image. %% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a polygon stipple pattern is requested, `Pattern' -%% is treated as a byte offset into the buffer object's data store. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetPolygonStipple.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetPolygonStipple.xml">external</a> documentation. -spec getPolygonStipple() -> binary(). getPolygonStipple() -> call(5053, <<>>). @@ -771,13 +538,7 @@ getPolygonStipple() -> %% of a nonboundary edge. ``gl:edgeFlag'' sets the edge flag bit to `?GL_TRUE' if `Flag' %% is `?GL_TRUE' and to `?GL_FALSE' otherwise. %% -%% The vertices of connected triangles and connected quadrilaterals are always marked as -%% boundary, regardless of the value of the edge flag. -%% -%% Boundary and nonboundary edge flags on vertices are significant only if `?GL_POLYGON_MODE' -%% is set to `?GL_POINT' or `?GL_LINE'. See {@link gl:polygonMode/2} . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEdgeFlag.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glEdgeFlag.xml">external</a> documentation. -spec edgeFlag(Flag) -> 'ok' when Flag :: 0|1. edgeFlag(Flag) -> cast(5054, <<Flag:?GLboolean>>). @@ -792,17 +553,7 @@ edgeFlagv({Flag}) -> edgeFlag(Flag). %% first two arguments, `X' and `Y' , specify the lower left corner of the box. `Width' %% and `Height' specify the width and height of the box. %% -%% To enable and disable the scissor test, call {@link gl:enable/1} and {@link gl:enable/1} -%% with argument `?GL_SCISSOR_TEST'. The test is initially disabled. While the test -%% is enabled, only pixels that lie within the scissor box can be modified by drawing commands. -%% Window coordinates have integer values at the shared corners of frame buffer pixels. glScissor(0,0,1,1) -%% allows modification of only the lower left pixel in the window, and glScissor(0,0,0,0) -%% doesn't allow modification of any pixels in the window. -%% -%% When the scissor test is disabled, it is as though the scissor box includes the entire -%% window. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScissor.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glScissor.xhtml">external</a> documentation. -spec scissor(X, Y, Width, Height) -> 'ok' when X :: integer(),Y :: integer(),Width :: integer(),Height :: integer(). scissor(X,Y,Width,Height) -> cast(5055, <<X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>). @@ -817,20 +568,7 @@ scissor(X,Y,Width,Height) -> %% clipping planes. Because the resulting clipping region is the intersection of the defined %% half-spaces, it is always convex. %% -%% ``gl:clipPlane'' specifies a half-space using a four-component plane equation. When ``gl:clipPlane'' -%% is called, `Equation' is transformed by the inverse of the modelview matrix and -%% stored in the resulting eye coordinates. Subsequent changes to the modelview matrix have -%% no effect on the stored plane-equation components. If the dot product of the eye coordinates -%% of a vertex with the stored plane equation components is positive or zero, the vertex is `in' -%% with respect to that clipping plane. Otherwise, it is `out'. -%% -%% To enable and disable clipping planes, call {@link gl:enable/1} and {@link gl:enable/1} -%% with the argument `?GL_CLIP_PLANE'`i', where `i' is the plane number. -%% -%% All clipping planes are initially defined as (0, 0, 0, 0) in eye coordinates and are -%% disabled. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClipPlane.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glClipPlane.xml">external</a> documentation. -spec clipPlane(Plane, Equation) -> 'ok' when Plane :: enum(),Equation :: {float(),float(),float(),float()}. clipPlane(Plane,{E1,E2,E3,E4}) -> cast(5056, <<Plane:?GLenum,0:32,E1:?GLdouble,E2:?GLdouble,E3:?GLdouble,E4:?GLdouble>>). @@ -840,7 +578,7 @@ clipPlane(Plane,{E1,E2,E3,E4}) -> %% ``gl:getClipPlane'' returns in `Equation' the four coefficients of the plane equation %% for `Plane' . %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetClipPlane.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetClipPlane.xml">external</a> documentation. -spec getClipPlane(Plane) -> {float(),float(),float(),float()} when Plane :: enum(). getClipPlane(Plane) -> call(5057, <<Plane:?GLenum>>). @@ -850,44 +588,7 @@ getClipPlane(Plane) -> %% When colors are written to the frame buffer, they are written into the color buffers %% specified by ``gl:drawBuffer''. The specifications are as follows: %% -%% `?GL_NONE': No color buffers are written. -%% -%% `?GL_FRONT_LEFT': Only the front left color buffer is written. -%% -%% `?GL_FRONT_RIGHT': Only the front right color buffer is written. -%% -%% `?GL_BACK_LEFT': Only the back left color buffer is written. -%% -%% `?GL_BACK_RIGHT': Only the back right color buffer is written. -%% -%% `?GL_FRONT': Only the front left and front right color buffers are written. If there -%% is no front right color buffer, only the front left color buffer is written. -%% -%% `?GL_BACK': Only the back left and back right color buffers are written. If there -%% is no back right color buffer, only the back left color buffer is written. -%% -%% `?GL_LEFT': Only the front left and back left color buffers are written. If there -%% is no back left color buffer, only the front left color buffer is written. -%% -%% `?GL_RIGHT': Only the front right and back right color buffers are written. If there -%% is no back right color buffer, only the front right color buffer is written. -%% -%% `?GL_FRONT_AND_BACK': All the front and back color buffers (front left, front right, -%% back left, back right) are written. If there are no back color buffers, only the front -%% left and front right color buffers are written. If there are no right color buffers, only -%% the front left and back left color buffers are written. If there are no right or back -%% color buffers, only the front left color buffer is written. -%% -%% If more than one color buffer is selected for drawing, then blending or logical operations -%% are computed and applied independently for each color buffer and can produce different -%% results in each buffer. -%% -%% Monoscopic contexts include only `left' buffers, and stereoscopic contexts include -%% both `left' and `right' buffers. Likewise, single-buffered contexts include -%% only `front' buffers, and double-buffered contexts include both `front' and `back' -%% buffers. The context is selected at GL initialization. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawBuffer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawBuffer.xhtml">external</a> documentation. -spec drawBuffer(Mode) -> 'ok' when Mode :: enum(). drawBuffer(Mode) -> cast(5058, <<Mode:?GLenum>>). @@ -904,15 +605,7 @@ drawBuffer(Mode) -> %% the `i'th color attachment where `i' ranges from zero to the value of `?GL_MAX_COLOR_ATTACHMENTS' %% minus one. %% -%% Nonstereo double-buffered configurations have only a front left and a back left buffer. -%% Single-buffered configurations have a front left and a front right buffer if stereo, and -%% only a front left buffer if nonstereo. It is an error to specify a nonexistent buffer to ``gl:readBuffer'' -%% . -%% -%% `Mode' is initially `?GL_FRONT' in single-buffered configurations and `?GL_BACK' -%% in double-buffered configurations. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glReadBuffer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glReadBuffer.xhtml">external</a> documentation. -spec readBuffer(Mode) -> 'ok' when Mode :: enum(). readBuffer(Mode) -> cast(5059, <<Mode:?GLenum>>). @@ -925,104 +618,7 @@ readBuffer(Mode) -> %% is `?GL_FALSE'. The initial value for `?GL_DITHER' and `?GL_MULTISAMPLE' %% is `?GL_TRUE'. %% -%% Both ``gl:enable'' and {@link gl:enable/1} take a single argument, `Cap' , which -%% can assume one of the following values: -%% -%% Some of the GL's capabilities are indexed. ``gl:enablei'' and ``gl:disablei'' enable -%% and disable indexed capabilities. -%% -%% `?GL_BLEND': If enabled, blend the computed fragment color values with the values -%% in the color buffers. See {@link gl:blendFunc/2} . -%% -%% `?GL_CLIP_DISTANCE'`i': If enabled, clip geometry against user-defined half -%% space `i'. -%% -%% `?GL_COLOR_LOGIC_OP': If enabled, apply the currently selected logical operation -%% to the computed fragment color and color buffer values. See {@link gl:logicOp/1} . -%% -%% `?GL_CULL_FACE': If enabled, cull polygons based on their winding in window coordinates. -%% See {@link gl:cullFace/1} . -%% -%% `?GL_DEPTH_CLAMP': If enabled, the -w c&le; z c&le; w c plane equation is -%% ignored by view volume clipping (effectively, there is no near or far plane clipping). -%% See {@link gl:depthRange/2} . -%% -%% `?GL_DEPTH_TEST': If enabled, do depth comparisons and update the depth buffer. -%% Note that even if the depth buffer exists and the depth mask is non-zero, the depth buffer -%% is not updated if the depth test is disabled. See {@link gl:depthFunc/1} and {@link gl:depthRange/2} -%% . -%% -%% `?GL_DITHER': If enabled, dither color components or indices before they are written -%% to the color buffer. -%% -%% `?GL_FRAMEBUFFER_SRGB': If enabled and the value of `?GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING' -%% for the framebuffer attachment corresponding to the destination buffer is `?GL_SRGB', -%% the R, G, and B destination color values (after conversion from fixed-point to floating-point) -%% are considered to be encoded for the sRGB color space and hence are linearized prior to -%% their use in blending. -%% -%% `?GL_LINE_SMOOTH': If enabled, draw lines with correct filtering. Otherwise, draw -%% aliased lines. See {@link gl:lineWidth/1} . -%% -%% `?GL_MULTISAMPLE': If enabled, use multiple fragment samples in computing the final -%% color of a pixel. See {@link gl:sampleCoverage/2} . -%% -%% `?GL_POLYGON_OFFSET_FILL': If enabled, and if the polygon is rendered in `?GL_FILL' -%% mode, an offset is added to depth values of a polygon's fragments before the depth comparison -%% is performed. See {@link gl:polygonOffset/2} . -%% -%% `?GL_POLYGON_OFFSET_LINE': If enabled, and if the polygon is rendered in `?GL_LINE' -%% mode, an offset is added to depth values of a polygon's fragments before the depth comparison -%% is performed. See {@link gl:polygonOffset/2} . -%% -%% `?GL_POLYGON_OFFSET_POINT': If enabled, an offset is added to depth values of a -%% polygon's fragments before the depth comparison is performed, if the polygon is rendered -%% in `?GL_POINT' mode. See {@link gl:polygonOffset/2} . -%% -%% `?GL_POLYGON_SMOOTH': If enabled, draw polygons with proper filtering. Otherwise, -%% draw aliased polygons. For correct antialiased polygons, an alpha buffer is needed and -%% the polygons must be sorted front to back. -%% -%% `?GL_PRIMITIVE_RESTART': Enables primitive restarting. If enabled, any one of the -%% draw commands which transfers a set of generic attribute array elements to the GL will -%% restart the primitive when the index of the vertex is equal to the primitive restart -%% index. See {@link gl:primitiveRestartIndex/1} . -%% -%% `?GL_SAMPLE_ALPHA_TO_COVERAGE': If enabled, compute a temporary coverage value where -%% each bit is determined by the alpha value at the corresponding sample location. The temporary -%% coverage value is then ANDed with the fragment coverage value. -%% -%% `?GL_SAMPLE_ALPHA_TO_ONE': If enabled, each sample alpha value is replaced by the -%% maximum representable alpha value. -%% -%% `?GL_SAMPLE_COVERAGE': If enabled, the fragment's coverage is ANDed with the temporary -%% coverage value. If `?GL_SAMPLE_COVERAGE_INVERT' is set to `?GL_TRUE', invert -%% the coverage value. See {@link gl:sampleCoverage/2} . -%% -%% `?GL_SAMPLE_SHADING': If enabled, the active fragment shader is run once for each -%% covered sample, or at fraction of this rate as determined by the current value of `?GL_MIN_SAMPLE_SHADING_VALUE' -%% . See {@link gl:minSampleShading/1} . -%% -%% `?GL_SAMPLE_MASK': If enabled, the sample coverage mask generated for a fragment -%% during rasterization will be ANDed with the value of `?GL_SAMPLE_MASK_VALUE' before -%% shading occurs. See {@link gl:sampleMaski/2} . -%% -%% `?GL_SCISSOR_TEST': If enabled, discard fragments that are outside the scissor rectangle. -%% See {@link gl:scissor/4} . -%% -%% `?GL_STENCIL_TEST': If enabled, do stencil testing and update the stencil buffer. -%% See {@link gl:stencilFunc/3} and {@link gl:stencilOp/3} . -%% -%% `?GL_TEXTURE_CUBE_MAP_SEAMLESS': If enabled, cubemap textures are sampled such that -%% when linearly sampling from the border between two adjacent faces, texels from both faces -%% are used to generate the final sample value. When disabled, texels from only a single -%% face are used to construct the final sample value. -%% -%% `?GL_PROGRAM_POINT_SIZE': If enabled and a vertex or geometry shader is active, -%% then the derived point size is taken from the (potentially clipped) shader builtin `?gl_PointSize' -%% and clamped to the implementation-dependent point size range. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEnable.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glEnable.xhtml">external</a> documentation. -spec enable(Cap) -> 'ok' when Cap :: enum(). enable(Cap) -> cast(5060, <<Cap:?GLenum>>). @@ -1042,31 +638,7 @@ disable(Cap) -> %% all capabilities except `?GL_DITHER' are disabled; `?GL_DITHER' is initially %% enabled. %% -%% The following capabilities are accepted for `Cap' : <table><tbody><tr><td>` Constant ' -%% </td><td>` See '</td></tr></tbody><tbody><tr><td>`?GL_BLEND'</td><td> {@link gl:blendFunc/2} -%% , {@link gl:logicOp/1} </td></tr><tr><td>`?GL_CLIP_DISTANCE'`i'</td><td> {@link gl:enable/1} -%% </td></tr><tr><td>`?GL_COLOR_LOGIC_OP'</td><td> {@link gl:logicOp/1} </td></tr><tr><td>`?GL_CULL_FACE' -%% </td><td> {@link gl:cullFace/1} </td></tr><tr><td>`?GL_DEPTH_CLAMP'</td><td> {@link gl:enable/1} -%% </td></tr><tr><td>`?GL_DEPTH_TEST'</td><td> {@link gl:depthFunc/1} , {@link gl:depthRange/2} -%% </td></tr><tr><td>`?GL_DITHER'</td><td> {@link gl:enable/1} </td></tr><tr><td>`?GL_FRAMEBUFFER_SRGB' -%% </td><td> {@link gl:enable/1} </td></tr><tr><td>`?GL_LINE_SMOOTH'</td><td> {@link gl:lineWidth/1} -%% </td></tr><tr><td>`?GL_MULTISAMPLE'</td><td> {@link gl:sampleCoverage/2} </td></tr><tr><td> -%% `?GL_POLYGON_SMOOTH'</td><td> {@link gl:polygonMode/2} </td></tr><tr><td>`?GL_POLYGON_OFFSET_FILL' -%% </td><td> {@link gl:polygonOffset/2} </td></tr><tr><td>`?GL_POLYGON_OFFSET_LINE'</td><td> -%% {@link gl:polygonOffset/2} </td></tr><tr><td>`?GL_POLYGON_OFFSET_POINT'</td><td> {@link gl:polygonOffset/2} -%% </td></tr><tr><td>`?GL_PROGRAM_POINT_SIZE'</td><td> {@link gl:enable/1} </td></tr><tr><td> -%% `?GL_PRIMITIVE_RESTART'</td><td> {@link gl:enable/1} , {@link gl:primitiveRestartIndex/1} </td> -%% </tr><tr><td>`?GL_SAMPLE_ALPHA_TO_COVERAGE'</td><td> {@link gl:sampleCoverage/2} </td></tr> -%% <tr><td>`?GL_SAMPLE_ALPHA_TO_ONE'</td><td> {@link gl:sampleCoverage/2} </td></tr><tr><td> -%% `?GL_SAMPLE_COVERAGE'</td><td> {@link gl:sampleCoverage/2} </td></tr><tr><td>`?GL_SAMPLE_MASK' -%% </td><td> {@link gl:enable/1} </td></tr><tr><td>`?GL_SCISSOR_TEST'</td><td> {@link gl:scissor/4} -%% </td></tr><tr><td>`?GL_STENCIL_TEST'</td><td> {@link gl:stencilFunc/3} , {@link gl:stencilOp/3} -%% </td></tr><tr><td>`?GL_TEXTURE_CUBEMAP_SEAMLESS'</td><td> {@link gl:enable/1} </td></tr> -%% </tbody></table> -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsEnabled.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsEnabled.xhtml">external</a> documentation. -spec isEnabled(Cap) -> 0|1 when Cap :: enum(). isEnabled(Cap) -> call(5062, <<Cap:?GLenum>>). @@ -1078,47 +650,7 @@ isEnabled(Cap) -> %% and {@link gl:enableClientState/1} take a single argument, `Cap' , which can assume %% one of the following values: %% -%% `?GL_COLOR_ARRAY': If enabled, the color array is enabled for writing and used during -%% rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4} , -%% {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements' -%% is called. See {@link gl:colorPointer/4} . -%% -%% `?GL_EDGE_FLAG_ARRAY': If enabled, the edge flag array is enabled for writing and -%% used during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4} -%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements' -%% is called. See {@link gl:edgeFlagPointer/2} . -%% -%% `?GL_FOG_COORD_ARRAY': If enabled, the fog coordinate array is enabled for writing -%% and used during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4} -%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements' -%% is called. See {@link gl:fogCoordPointer/3} . -%% -%% `?GL_INDEX_ARRAY': If enabled, the index array is enabled for writing and used during -%% rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4} , -%% {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements' -%% is called. See {@link gl:indexPointer/3} . -%% -%% `?GL_NORMAL_ARRAY': If enabled, the normal array is enabled for writing and used -%% during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4} -%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements' -%% is called. See {@link gl:normalPointer/3} . -%% -%% `?GL_SECONDARY_COLOR_ARRAY': If enabled, the secondary color array is enabled for -%% writing and used during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4} -%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements' -%% is called. See {@link gl:colorPointer/4} . -%% -%% `?GL_TEXTURE_COORD_ARRAY': If enabled, the texture coordinate array is enabled for -%% writing and used during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4} -%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements' -%% is called. See {@link gl:texCoordPointer/4} . -%% -%% `?GL_VERTEX_ARRAY': If enabled, the vertex array is enabled for writing and used -%% during rendering when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:drawElements/4} -%% , {@link gl:drawRangeElements/6} {@link gl:multiDrawArrays/3} , or see `glMultiDrawElements' -%% is called. See {@link gl:vertexPointer/4} . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEnableClientState.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glEnableClientState.xml">external</a> documentation. -spec enableClientState(Cap) -> 'ok' when Cap :: enum(). enableClientState(Cap) -> cast(5063, <<Cap:?GLenum>>). @@ -1135,809 +667,7 @@ disableClientState(Cap) -> %% symbolic constant indicating the state variable to be returned, and `Params' is a %% pointer to an array of the indicated type in which to place the returned data. %% -%% Type conversion is performed if `Params' has a different type than the state variable -%% value being requested. If ``gl:getBooleanv'' is called, a floating-point (or integer) -%% value is converted to `?GL_FALSE' if and only if it is 0.0 (or 0). Otherwise, it -%% is converted to `?GL_TRUE'. If ``gl:getIntegerv'' is called, boolean values are -%% returned as `?GL_TRUE' or `?GL_FALSE', and most floating-point values are rounded -%% to the nearest integer value. Floating-point colors and normals, however, are returned -%% with a linear mapping that maps 1.0 to the most positive representable integer value and -%% -1.0 to the most negative representable integer value. If ``gl:getFloatv'' or ``gl:getDoublev'' -%% is called, boolean values are returned as `?GL_TRUE' or `?GL_FALSE', and integer -%% values are converted to floating-point values. -%% -%% The following symbolic constants are accepted by `Pname' : -%% -%% `?GL_ACTIVE_TEXTURE': `Params' returns a single value indicating the active -%% multitexture unit. The initial value is `?GL_TEXTURE0'. See {@link gl:activeTexture/1} . -%% -%% -%% `?GL_ALIASED_LINE_WIDTH_RANGE': `Params' returns a pair of values indicating -%% the range of widths supported for aliased lines. See {@link gl:lineWidth/1} . -%% -%% `?GL_ARRAY_BUFFER_BINDING': `Params' returns a single value, the name of the -%% buffer object currently bound to the target `?GL_ARRAY_BUFFER'. If no buffer object -%% is bound to this target, 0 is returned. The initial value is 0. See {@link gl:bindBuffer/2} . -%% -%% -%% `?GL_BLEND': `Params' returns a single boolean value indicating whether blending -%% is enabled. The initial value is `?GL_FALSE'. See {@link gl:blendFunc/2} . -%% -%% `?GL_BLEND_COLOR': `Params' returns four values, the red, green, blue, and alpha -%% values which are the components of the blend color. See {@link gl:blendColor/4} . -%% -%% `?GL_BLEND_DST_ALPHA': `Params' returns one value, the symbolic constant identifying -%% the alpha destination blend function. The initial value is `?GL_ZERO'. See {@link gl:blendFunc/2} -%% and {@link gl:blendFuncSeparate/4} . -%% -%% `?GL_BLEND_DST_RGB': `Params' returns one value, the symbolic constant identifying -%% the RGB destination blend function. The initial value is `?GL_ZERO'. See {@link gl:blendFunc/2} -%% and {@link gl:blendFuncSeparate/4} . -%% -%% `?GL_BLEND_EQUATION_RGB': `Params' returns one value, a symbolic constant indicating -%% whether the RGB blend equation is `?GL_FUNC_ADD', `?GL_FUNC_SUBTRACT', `?GL_FUNC_REVERSE_SUBTRACT' -%% , `?GL_MIN' or `?GL_MAX'. See {@link gl:blendEquationSeparate/2} . -%% -%% `?GL_BLEND_EQUATION_ALPHA': `Params' returns one value, a symbolic constant -%% indicating whether the Alpha blend equation is `?GL_FUNC_ADD', `?GL_FUNC_SUBTRACT' -%% , `?GL_FUNC_REVERSE_SUBTRACT', `?GL_MIN' or `?GL_MAX'. See {@link gl:blendEquationSeparate/2} -%% . -%% -%% `?GL_BLEND_SRC_ALPHA': `Params' returns one value, the symbolic constant identifying -%% the alpha source blend function. The initial value is `?GL_ONE'. See {@link gl:blendFunc/2} -%% and {@link gl:blendFuncSeparate/4} . -%% -%% `?GL_BLEND_SRC_RGB': `Params' returns one value, the symbolic constant identifying -%% the RGB source blend function. The initial value is `?GL_ONE'. See {@link gl:blendFunc/2} -%% and {@link gl:blendFuncSeparate/4} . -%% -%% `?GL_COLOR_CLEAR_VALUE': `Params' returns four values: the red, green, blue, -%% and alpha values used to clear the color buffers. Integer values, if requested, are linearly -%% mapped from the internal floating-point representation such that 1.0 returns the most -%% positive representable integer value, and -1.0 returns the most negative representable -%% integer value. The initial value is (0, 0, 0, 0). See {@link gl:clearColor/4} . -%% -%% `?GL_COLOR_LOGIC_OP': `Params' returns a single boolean value indicating whether -%% a fragment's RGBA color values are merged into the framebuffer using a logical operation. -%% The initial value is `?GL_FALSE'. See {@link gl:logicOp/1} . -%% -%% `?GL_COLOR_WRITEMASK': `Params' returns four boolean values: the red, green, -%% blue, and alpha write enables for the color buffers. The initial value is (`?GL_TRUE', -%% `?GL_TRUE', `?GL_TRUE', `?GL_TRUE'). See {@link gl:colorMask/4} . -%% -%% `?GL_COMPRESSED_TEXTURE_FORMATS': `Params' returns a list of symbolic constants -%% of length `?GL_NUM_COMPRESSED_TEXTURE_FORMATS' indicating which compressed texture -%% formats are available. See {@link gl:compressedTexImage2D/8} . -%% -%% `?GL_CONTEXT_FLAGS': `Params' returns one value, the flags with which the context -%% was created (such as debugging functionality). -%% -%% `?GL_CULL_FACE': `Params' returns a single boolean value indicating whether -%% polygon culling is enabled. The initial value is `?GL_FALSE'. See {@link gl:cullFace/1} -%% . -%% -%% `?GL_CURRENT_PROGRAM': `Params' returns one value, the name of the program object -%% that is currently active, or 0 if no program object is active. See {@link gl:useProgram/1} . -%% -%% -%% `?GL_DEPTH_CLEAR_VALUE': `Params' returns one value, the value that is used -%% to clear the depth buffer. Integer values, if requested, are linearly mapped from the -%% internal floating-point representation such that 1.0 returns the most positive representable -%% integer value, and -1.0 returns the most negative representable integer value. The initial -%% value is 1. See {@link gl:clearDepth/1} . -%% -%% `?GL_DEPTH_FUNC': `Params' returns one value, the symbolic constant that indicates -%% the depth comparison function. The initial value is `?GL_LESS'. See {@link gl:depthFunc/1} -%% . -%% -%% `?GL_DEPTH_RANGE': `Params' returns two values: the near and far mapping limits -%% for the depth buffer. Integer values, if requested, are linearly mapped from the internal -%% floating-point representation such that 1.0 returns the most positive representable integer -%% value, and -1.0 returns the most negative representable integer value. The initial value -%% is (0, 1). See {@link gl:depthRange/2} . -%% -%% `?GL_DEPTH_TEST': `Params' returns a single boolean value indicating whether -%% depth testing of fragments is enabled. The initial value is `?GL_FALSE'. See {@link gl:depthFunc/1} -%% and {@link gl:depthRange/2} . -%% -%% `?GL_DEPTH_WRITEMASK': `Params' returns a single boolean value indicating if -%% the depth buffer is enabled for writing. The initial value is `?GL_TRUE'. See {@link gl:depthMask/1} -%% . -%% -%% `?GL_DITHER': `Params' returns a single boolean value indicating whether dithering -%% of fragment colors and indices is enabled. The initial value is `?GL_TRUE'. -%% -%% `?GL_DOUBLEBUFFER': `Params' returns a single boolean value indicating whether -%% double buffering is supported. -%% -%% `?GL_DRAW_BUFFER': `Params' returns one value, a symbolic constant indicating -%% which buffers are being drawn to. See {@link gl:drawBuffer/1} . The initial value is `?GL_BACK' -%% if there are back buffers, otherwise it is `?GL_FRONT'. -%% -%% `?GL_DRAW_BUFFER'`i': `Params' returns one value, a symbolic constant indicating -%% which buffers are being drawn to by the corresponding output color. See {@link gl:drawBuffers/1} -%% . The initial value of `?GL_DRAW_BUFFER0' is `?GL_BACK' if there are back buffers, -%% otherwise it is `?GL_FRONT'. The initial values of draw buffers for all other output -%% colors is `?GL_NONE'. -%% -%% `?GL_DRAW_FRAMEBUFFER_BINDING': `Params' returns one value, the name of the -%% framebuffer object currently bound to the `?GL_DRAW_FRAMEBUFFER' target. If the default -%% framebuffer is bound, this value will be zero. The initial value is zero. See {@link gl:bindFramebuffer/2} -%% . -%% -%% `?GL_READ_FRAMEBUFFER_BINDING': `Params' returns one value, the name of the -%% framebuffer object currently bound to the `?GL_READ_FRAMEBUFFER' target. If the default -%% framebuffer is bound, this value will be zero. The initial value is zero. See {@link gl:bindFramebuffer/2} -%% . -%% -%% `?GL_ELEMENT_ARRAY_BUFFER_BINDING': `Params' returns a single value, the name -%% of the buffer object currently bound to the target `?GL_ELEMENT_ARRAY_BUFFER'. If -%% no buffer object is bound to this target, 0 is returned. The initial value is 0. See {@link gl:bindBuffer/2} -%% . -%% -%% `?GL_FRAGMENT_SHADER_DERIVATIVE_HINT': `Params' returns one value, a symbolic -%% constant indicating the mode of the derivative accuracy hint for fragment shaders. The -%% initial value is `?GL_DONT_CARE'. See {@link gl:hint/2} . -%% -%% `?GL_IMPLEMENTATION_COLOR_READ_FORMAT': `Params' returns a single GLenum value -%% indicating the implementation's preferred pixel data format. See {@link gl:readPixels/7} . -%% -%% `?GL_IMPLEMENTATION_COLOR_READ_TYPE': `Params' returns a single GLenum value -%% indicating the implementation's preferred pixel data type. See {@link gl:readPixels/7} . -%% -%% `?GL_LINE_SMOOTH': `Params' returns a single boolean value indicating whether -%% antialiasing of lines is enabled. The initial value is `?GL_FALSE'. See {@link gl:lineWidth/1} -%% . -%% -%% `?GL_LINE_SMOOTH_HINT': `Params' returns one value, a symbolic constant indicating -%% the mode of the line antialiasing hint. The initial value is `?GL_DONT_CARE'. See {@link gl:hint/2} -%% . -%% -%% `?GL_LINE_WIDTH': `Params' returns one value, the line width as specified with {@link gl:lineWidth/1} -%% . The initial value is 1. -%% -%% `?GL_LAYER_PROVOKING_VERTEX': `Params' returns one value, the implementation -%% dependent specifc vertex of a primitive that is used to select the rendering layer. If -%% the value returned is equivalent to `?GL_PROVOKING_VERTEX', then the vertex selection -%% follows the convention specified by {@link gl:provokingVertex/1} . If the value returned -%% is equivalent to `?GL_FIRST_VERTEX_CONVENTION', then the selection is always taken -%% from the first vertex in the primitive. If the value returned is equivalent to `?GL_LAST_VERTEX_CONVENTION' -%% , then the selection is always taken from the last vertex in the primitive. If the value -%% returned is equivalent to `?GL_UNDEFINED_VERTEX', then the selection is not guaranteed -%% to be taken from any specific vertex in the primitive. -%% -%% `?GL_LINE_WIDTH_GRANULARITY': `Params' returns one value, the width difference -%% between adjacent supported widths for antialiased lines. See {@link gl:lineWidth/1} . -%% -%% `?GL_LINE_WIDTH_RANGE': `Params' returns two values: the smallest and largest -%% supported widths for antialiased lines. See {@link gl:lineWidth/1} . -%% -%% `?GL_LOGIC_OP_MODE': `Params' returns one value, a symbolic constant indicating -%% the selected logic operation mode. The initial value is `?GL_COPY'. See {@link gl:logicOp/1} -%% . -%% -%% `?GL_MAJOR_VERSION': `Params' returns one value, the major version number of -%% the OpenGL API supported by the current context. -%% -%% `?GL_MAX_3D_TEXTURE_SIZE': `Params' returns one value, a rough estimate of the -%% largest 3D texture that the GL can handle. The value must be at least 64. Use `?GL_PROXY_TEXTURE_3D' -%% to determine if a texture is too large. See {@link gl:texImage3D/10} . -%% -%% `?GL_MAX_ARRAY_TEXTURE_LAYERS': `Params' returns one value. The value indicates -%% the maximum number of layers allowed in an array texture, and must be at least 256. See {@link gl:texImage2D/9} -%% . -%% -%% `?GL_MAX_CLIP_DISTANCES': `Params' returns one value, the maximum number of -%% application-defined clipping distances. The value must be at least 8. -%% -%% `?GL_MAX_COLOR_TEXTURE_SAMPLES': `Params' returns one value, the maximum number -%% of samples in a color multisample texture. -%% -%% `?GL_MAX_COMBINED_ATOMIC_COUNTERS': `Params' returns a single value, the maximum -%% number of atomic counters available to all active shaders. -%% -%% `?GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS': `Params' returns one value, -%% the number of words for fragment shader uniform variables in all uniform blocks (including -%% default). The value must be at least 1. See {@link gl:uniform1f/2} . -%% -%% `?GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS': `Params' returns one value, -%% the number of words for geometry shader uniform variables in all uniform blocks (including -%% default). The value must be at least 1. See {@link gl:uniform1f/2} . -%% -%% `?GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS': `Params' returns one value, the maximum -%% supported texture image units that can be used to access texture maps from the vertex -%% shader and the fragment processor combined. If both the vertex shader and the fragment -%% processing stage access the same texture image unit, then that counts as using two texture -%% image units against this limit. The value must be at least 48. See {@link gl:activeTexture/1} -%% . -%% -%% `?GL_MAX_COMBINED_UNIFORM_BLOCKS': `Params' returns one value, the maximum number -%% of uniform blocks per program. The value must be at least 36. See {@link gl:uniformBlockBinding/3} -%% . -%% -%% `?GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS': `Params' returns one value, the -%% number of words for vertex shader uniform variables in all uniform blocks (including default). -%% The value must be at least 1. See {@link gl:uniform1f/2} . -%% -%% `?GL_MAX_CUBE_MAP_TEXTURE_SIZE': `Params' returns one value. The value gives -%% a rough estimate of the largest cube-map texture that the GL can handle. The value must -%% be at least 1024. Use `?GL_PROXY_TEXTURE_CUBE_MAP' to determine if a texture is too -%% large. See {@link gl:texImage2D/9} . -%% -%% `?GL_MAX_DEPTH_TEXTURE_SAMPLES': `Params' returns one value, the maximum number -%% of samples in a multisample depth or depth-stencil texture. -%% -%% `?GL_MAX_DRAW_BUFFERS': `Params' returns one value, the maximum number of simultaneous -%% outputs that may be written in a fragment shader. The value must be at least 8. See {@link gl:drawBuffers/1} -%% . -%% -%% `?GL_MAX_DUALSOURCE_DRAW_BUFFERS': `Params' returns one value, the maximum number -%% of active draw buffers when using dual-source blending. The value must be at least 1. -%% See {@link gl:blendFunc/2} and {@link gl:blendFuncSeparate/4} . -%% -%% `?GL_MAX_ELEMENTS_INDICES': `Params' returns one value, the recommended maximum -%% number of vertex array indices. See {@link gl:drawRangeElements/6} . -%% -%% `?GL_MAX_ELEMENTS_VERTICES': `Params' returns one value, the recommended maximum -%% number of vertex array vertices. See {@link gl:drawRangeElements/6} . -%% -%% `?GL_MAX_FRAGMENT_ATOMIC_COUNTERS': `Params' returns a single value, the maximum -%% number of atomic counters available to fragment shaders. -%% -%% `?GL_MAX_FRAGMENT_INPUT_COMPONENTS': `Params' returns one value, the maximum -%% number of components of the inputs read by the fragment shader, which must be at least -%% 128. -%% -%% `?GL_MAX_FRAGMENT_UNIFORM_COMPONENTS': `Params' returns one value, the maximum -%% number of individual floating-point, integer, or boolean values that can be held in uniform -%% variable storage for a fragment shader. The value must be at least 1024. See {@link gl:uniform1f/2} -%% . -%% -%% `?GL_MAX_FRAGMENT_UNIFORM_VECTORS': `Params' returns one value, the maximum -%% number of individual 4-vectors of floating-point, integer, or boolean values that can -%% be held in uniform variable storage for a fragment shader. The value is equal to the value -%% of `?GL_MAX_FRAGMENT_UNIFORM_COMPONENTS' divided by 4 and must be at least 256. See {@link gl:uniform1f/2} -%% . -%% -%% `?GL_MAX_FRAGMENT_UNIFORM_BLOCKS': `Params' returns one value, the maximum number -%% of uniform blocks per fragment shader. The value must be at least 12. See {@link gl:uniformBlockBinding/3} -%% . -%% -%% `?GL_MAX_GEOMETRY_ATOMIC_COUNTERS': `Params' returns a single value, the maximum -%% number of atomic counters available to geometry shaders. -%% -%% `?GL_MAX_GEOMETRY_INPUT_COMPONENTS': `Params' returns one value, the maximum -%% number of components of inputs read by a geometry shader, which must be at least 64. -%% -%% `?GL_MAX_GEOMETRY_OUTPUT_COMPONENTS': `Params' returns one value, the maximum -%% number of components of outputs written by a geometry shader, which must be at least 128. -%% -%% -%% `?GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS': `Params' returns one value, the maximum -%% supported texture image units that can be used to access texture maps from the geometry -%% shader. The value must be at least 16. See {@link gl:activeTexture/1} . -%% -%% `?GL_MAX_GEOMETRY_UNIFORM_BLOCKS': `Params' returns one value, the maximum number -%% of uniform blocks per geometry shader. The value must be at least 12. See {@link gl:uniformBlockBinding/3} -%% . -%% -%% `?GL_MAX_GEOMETRY_UNIFORM_COMPONENTS': `Params' returns one value, the maximum -%% number of individual floating-point, integer, or boolean values that can be held in uniform -%% variable storage for a geometry shader. The value must be at least 1024. See {@link gl:uniform1f/2} -%% . -%% -%% `?GL_MAX_INTEGER_SAMPLES': `Params' returns one value, the maximum number of -%% samples supported in integer format multisample buffers. -%% -%% `?GL_MIN_MAP_BUFFER_ALIGNMENT': `Params' returns one value, the minimum alignment -%% in basic machine units of pointers returned fromsee `glMapBuffer' and see `glMapBufferRange' -%% . This value must be a power of two and must be at least 64. -%% -%% `?GL_MAX_PROGRAM_TEXEL_OFFSET': `Params' returns one value, the maximum texel -%% offset allowed in a texture lookup, which must be at least 7. -%% -%% `?GL_MIN_PROGRAM_TEXEL_OFFSET': `Params' returns one value, the minimum texel -%% offset allowed in a texture lookup, which must be at most -8. -%% -%% `?GL_MAX_RECTANGLE_TEXTURE_SIZE': `Params' returns one value. The value gives -%% a rough estimate of the largest rectangular texture that the GL can handle. The value -%% must be at least 1024. Use `?GL_PROXY_RECTANGLE_TEXTURE' to determine if a texture -%% is too large. See {@link gl:texImage2D/9} . -%% -%% `?GL_MAX_RENDERBUFFER_SIZE': `Params' returns one value. The value indicates -%% the maximum supported size for renderbuffers. See {@link gl:framebufferRenderbuffer/4} . -%% -%% `?GL_MAX_SAMPLE_MASK_WORDS': `Params' returns one value, the maximum number -%% of sample mask words. -%% -%% `?GL_MAX_SERVER_WAIT_TIMEOUT': `Params' returns one value, the maximum {@link gl:waitSync/3} -%% timeout interval. -%% -%% `?GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS': `Params' returns a single value, the -%% maximum number of atomic counters available to tessellation control shaders. -%% -%% `?GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS': `Params' returns a single value, -%% the maximum number of atomic counters available to tessellation evaluation shaders. -%% -%% `?GL_MAX_TEXTURE_BUFFER_SIZE': `Params' returns one value. The value gives the -%% maximum number of texels allowed in the texel array of a texture buffer object. Value -%% must be at least 65536. -%% -%% `?GL_MAX_TEXTURE_IMAGE_UNITS': `Params' returns one value, the maximum supported -%% texture image units that can be used to access texture maps from the fragment shader. -%% The value must be at least 16. See {@link gl:activeTexture/1} . -%% -%% `?GL_MAX_TEXTURE_LOD_BIAS': `Params' returns one value, the maximum, absolute -%% value of the texture level-of-detail bias. The value must be at least 2.0. -%% -%% `?GL_MAX_TEXTURE_SIZE': `Params' returns one value. The value gives a rough -%% estimate of the largest texture that the GL can handle. The value must be at least 1024. -%% Use a proxy texture target such as `?GL_PROXY_TEXTURE_1D' or `?GL_PROXY_TEXTURE_2D' -%% to determine if a texture is too large. See {@link gl:texImage1D/8} and {@link gl:texImage2D/9} -%% . -%% -%% `?GL_MAX_UNIFORM_BUFFER_BINDINGS': `Params' returns one value, the maximum number -%% of uniform buffer binding points on the context, which must be at least 36. -%% -%% `?GL_MAX_UNIFORM_BLOCK_SIZE': `Params' returns one value, the maximum size in -%% basic machine units of a uniform block, which must be at least 16384. -%% -%% `?GL_MAX_VARYING_COMPONENTS': `Params' returns one value, the number components -%% for varying variables, which must be at least 60. -%% -%% `?GL_MAX_VARYING_VECTORS': `Params' returns one value, the number 4-vectors -%% for varying variables, which is equal to the value of `?GL_MAX_VARYING_COMPONENTS' -%% and must be at least 15. -%% -%% `?GL_MAX_VARYING_FLOATS': `Params' returns one value, the maximum number of -%% interpolators available for processing varying variables used by vertex and fragment shaders. -%% This value represents the number of individual floating-point values that can be interpolated; -%% varying variables declared as vectors, matrices, and arrays will all consume multiple -%% interpolators. The value must be at least 32. -%% -%% `?GL_MAX_VERTEX_ATOMIC_COUNTERS': `Params' returns a single value, the maximum -%% number of atomic counters available to vertex shaders. -%% -%% `?GL_MAX_VERTEX_ATTRIBS': `Params' returns one value, the maximum number of -%% 4-component generic vertex attributes accessible to a vertex shader. The value must be -%% at least 16. See {@link gl:vertexAttrib1d/2} . -%% -%% `?GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS': `Params' returns one value, the maximum -%% supported texture image units that can be used to access texture maps from the vertex -%% shader. The value may be at least 16. See {@link gl:activeTexture/1} . -%% -%% `?GL_MAX_VERTEX_UNIFORM_COMPONENTS': `Params' returns one value, the maximum -%% number of individual floating-point, integer, or boolean values that can be held in uniform -%% variable storage for a vertex shader. The value must be at least 1024. See {@link gl:uniform1f/2} -%% . -%% -%% `?GL_MAX_VERTEX_UNIFORM_VECTORS': `Params' returns one value, the maximum number -%% of 4-vectors that may be held in uniform variable storage for the vertex shader. The value -%% of `?GL_MAX_VERTEX_UNIFORM_VECTORS' is equal to the value of `?GL_MAX_VERTEX_UNIFORM_COMPONENTS' -%% and must be at least 256. -%% -%% `?GL_MAX_VERTEX_OUTPUT_COMPONENTS': `Params' returns one value, the maximum -%% number of components of output written by a vertex shader, which must be at least 64. -%% -%% `?GL_MAX_VERTEX_UNIFORM_BLOCKS': `Params' returns one value, the maximum number -%% of uniform blocks per vertex shader. The value must be at least 12. See {@link gl:uniformBlockBinding/3} -%% . -%% -%% `?GL_MAX_VIEWPORT_DIMS': `Params' returns two values: the maximum supported -%% width and height of the viewport. These must be at least as large as the visible dimensions -%% of the display being rendered to. See {@link gl:viewport/4} . -%% -%% `?GL_MAX_VIEWPORTS': `Params' returns one value, the maximum number of simultaneous -%% viewports that are supported. The value must be at least 16. See {@link gl:viewportIndexedf/5} -%% . -%% -%% `?GL_MINOR_VERSION': `Params' returns one value, the minor version number of -%% the OpenGL API supported by the current context. -%% -%% `?GL_NUM_COMPRESSED_TEXTURE_FORMATS': `Params' returns a single integer value -%% indicating the number of available compressed texture formats. The minimum value is 4. -%% See {@link gl:compressedTexImage2D/8} . -%% -%% `?GL_NUM_EXTENSIONS': `Params' returns one value, the number of extensions supported -%% by the GL implementation for the current context. See {@link gl:getString/1} . -%% -%% `?GL_NUM_PROGRAM_BINARY_FORMATS': `Params' returns one value, the number of -%% program binary formats supported by the implementation. -%% -%% `?GL_NUM_SHADER_BINARY_FORMATS': `Params' returns one value, the number of binary -%% shader formats supported by the implementation. If this value is greater than zero, then -%% the implementation supports loading binary shaders. If it is zero, then the loading of -%% binary shaders by the implementation is not supported. -%% -%% `?GL_PACK_ALIGNMENT': `Params' returns one value, the byte alignment used for -%% writing pixel data to memory. The initial value is 4. See {@link gl:pixelStoref/2} . -%% -%% `?GL_PACK_IMAGE_HEIGHT': `Params' returns one value, the image height used for -%% writing pixel data to memory. The initial value is 0. See {@link gl:pixelStoref/2} . -%% -%% `?GL_PACK_LSB_FIRST': `Params' returns a single boolean value indicating whether -%% single-bit pixels being written to memory are written first to the least significant bit -%% of each unsigned byte. The initial value is `?GL_FALSE'. See {@link gl:pixelStoref/2} . -%% -%% -%% `?GL_PACK_ROW_LENGTH': `Params' returns one value, the row length used for writing -%% pixel data to memory. The initial value is 0. See {@link gl:pixelStoref/2} . -%% -%% `?GL_PACK_SKIP_IMAGES': `Params' returns one value, the number of pixel images -%% skipped before the first pixel is written into memory. The initial value is 0. See {@link gl:pixelStoref/2} -%% . -%% -%% `?GL_PACK_SKIP_PIXELS': `Params' returns one value, the number of pixel locations -%% skipped before the first pixel is written into memory. The initial value is 0. See {@link gl:pixelStoref/2} -%% . -%% -%% `?GL_PACK_SKIP_ROWS': `Params' returns one value, the number of rows of pixel -%% locations skipped before the first pixel is written into memory. The initial value is -%% 0. See {@link gl:pixelStoref/2} . -%% -%% `?GL_PACK_SWAP_BYTES': `Params' returns a single boolean value indicating whether -%% the bytes of two-byte and four-byte pixel indices and components are swapped before being -%% written to memory. The initial value is `?GL_FALSE'. See {@link gl:pixelStoref/2} . -%% -%% `?GL_PIXEL_PACK_BUFFER_BINDING': `Params' returns a single value, the name of -%% the buffer object currently bound to the target `?GL_PIXEL_PACK_BUFFER'. If no buffer -%% object is bound to this target, 0 is returned. The initial value is 0. See {@link gl:bindBuffer/2} -%% . -%% -%% `?GL_PIXEL_UNPACK_BUFFER_BINDING': `Params' returns a single value, the name -%% of the buffer object currently bound to the target `?GL_PIXEL_UNPACK_BUFFER'. If -%% no buffer object is bound to this target, 0 is returned. The initial value is 0. See {@link gl:bindBuffer/2} -%% . -%% -%% `?GL_POINT_FADE_THRESHOLD_SIZE': `Params' returns one value, the point size -%% threshold for determining the point size. See {@link gl:pointParameterf/2} . -%% -%% `?GL_PRIMITIVE_RESTART_INDEX': `Params' returns one value, the current primitive -%% restart index. The initial value is 0. See {@link gl:primitiveRestartIndex/1} . -%% -%% `?GL_PROGRAM_BINARY_FORMATS': `Params' an array of `?GL_NUM_PROGRAM_BINARY_FORMATS' -%% values, indicating the proram binary formats supported by the implementation. -%% -%% `?GL_PROGRAM_PIPELINE_BINDING': `Params' a single value, the name of the currently -%% bound program pipeline object, or zero if no program pipeline object is bound. See {@link gl:bindProgramPipeline/1} -%% . -%% -%% `?GL_PROVOKING_VERTEX': `Params' returns one value, the currently selected provoking -%% vertex convention. The initial value is `?GL_LAST_VERTEX_CONVENTION'. See {@link gl:provokingVertex/1} -%% . -%% -%% `?GL_POINT_SIZE': `Params' returns one value, the point size as specified by {@link gl:pointSize/1} -%% . The initial value is 1. -%% -%% `?GL_POINT_SIZE_GRANULARITY': `Params' returns one value, the size difference -%% between adjacent supported sizes for antialiased points. See {@link gl:pointSize/1} . -%% -%% `?GL_POINT_SIZE_RANGE': `Params' returns two values: the smallest and largest -%% supported sizes for antialiased points. The smallest size must be at most 1, and the largest -%% size must be at least 1. See {@link gl:pointSize/1} . -%% -%% `?GL_POLYGON_OFFSET_FACTOR': `Params' returns one value, the scaling factor -%% used to determine the variable offset that is added to the depth value of each fragment -%% generated when a polygon is rasterized. The initial value is 0. See {@link gl:polygonOffset/2} -%% . -%% -%% `?GL_POLYGON_OFFSET_UNITS': `Params' returns one value. This value is multiplied -%% by an implementation-specific value and then added to the depth value of each fragment -%% generated when a polygon is rasterized. The initial value is 0. See {@link gl:polygonOffset/2} -%% . -%% -%% `?GL_POLYGON_OFFSET_FILL': `Params' returns a single boolean value indicating -%% whether polygon offset is enabled for polygons in fill mode. The initial value is `?GL_FALSE' -%% . See {@link gl:polygonOffset/2} . -%% -%% `?GL_POLYGON_OFFSET_LINE': `Params' returns a single boolean value indicating -%% whether polygon offset is enabled for polygons in line mode. The initial value is `?GL_FALSE' -%% . See {@link gl:polygonOffset/2} . -%% -%% `?GL_POLYGON_OFFSET_POINT': `Params' returns a single boolean value indicating -%% whether polygon offset is enabled for polygons in point mode. The initial value is `?GL_FALSE' -%% . See {@link gl:polygonOffset/2} . -%% -%% `?GL_POLYGON_SMOOTH': `Params' returns a single boolean value indicating whether -%% antialiasing of polygons is enabled. The initial value is `?GL_FALSE'. See {@link gl:polygonMode/2} -%% . -%% -%% `?GL_POLYGON_SMOOTH_HINT': `Params' returns one value, a symbolic constant indicating -%% the mode of the polygon antialiasing hint. The initial value is `?GL_DONT_CARE'. -%% See {@link gl:hint/2} . -%% -%% `?GL_READ_BUFFER': `Params' returns one value, a symbolic constant indicating -%% which color buffer is selected for reading. The initial value is `?GL_BACK' if there -%% is a back buffer, otherwise it is `?GL_FRONT'. See {@link gl:readPixels/7} . -%% -%% `?GL_RENDERBUFFER_BINDING': `Params' returns a single value, the name of the -%% renderbuffer object currently bound to the target `?GL_RENDERBUFFER'. If no renderbuffer -%% object is bound to this target, 0 is returned. The initial value is 0. See {@link gl:bindRenderbuffer/2} -%% . -%% -%% `?GL_SAMPLE_BUFFERS': `Params' returns a single integer value indicating the -%% number of sample buffers associated with the framebuffer. See {@link gl:sampleCoverage/2} . -%% -%% -%% `?GL_SAMPLE_COVERAGE_VALUE': `Params' returns a single positive floating-point -%% value indicating the current sample coverage value. See {@link gl:sampleCoverage/2} . -%% -%% `?GL_SAMPLE_COVERAGE_INVERT': `Params' returns a single boolean value indicating -%% if the temporary coverage value should be inverted. See {@link gl:sampleCoverage/2} . -%% -%% `?GL_SAMPLER_BINDING': `Params' returns a single value, the name of the sampler -%% object currently bound to the active texture unit. The initial value is 0. See {@link gl:bindSampler/2} -%% . -%% -%% `?GL_SAMPLES': `Params' returns a single integer value indicating the coverage -%% mask size. See {@link gl:sampleCoverage/2} . -%% -%% `?GL_SCISSOR_BOX': `Params' returns four values: the x and y window coordinates -%% of the scissor box, followed by its width and height. Initially the x and y window -%% coordinates are both 0 and the width and height are set to the size of the window. See {@link gl:scissor/4} -%% . -%% -%% `?GL_SCISSOR_TEST': `Params' returns a single boolean value indicating whether -%% scissoring is enabled. The initial value is `?GL_FALSE'. See {@link gl:scissor/4} . -%% -%% `?GL_SHADER_COMPILER': `Params' returns a single boolean value indicating whether -%% an online shader compiler is present in the implementation. All desktop OpenGL implementations -%% must support online shader compilations, and therefore the value of `?GL_SHADER_COMPILER' -%% will always be `?GL_TRUE'. -%% -%% `?GL_SMOOTH_LINE_WIDTH_RANGE': `Params' returns a pair of values indicating -%% the range of widths supported for smooth (antialiased) lines. See {@link gl:lineWidth/1} . -%% -%% `?GL_SMOOTH_LINE_WIDTH_GRANULARITY': `Params' returns a single value indicating -%% the level of quantization applied to smooth line width parameters. -%% -%% `?GL_STENCIL_BACK_FAIL': `Params' returns one value, a symbolic constant indicating -%% what action is taken for back-facing polygons when the stencil test fails. The initial -%% value is `?GL_KEEP'. See {@link gl:stencilOpSeparate/4} . -%% -%% `?GL_STENCIL_BACK_FUNC': `Params' returns one value, a symbolic constant indicating -%% what function is used for back-facing polygons to compare the stencil reference value -%% with the stencil buffer value. The initial value is `?GL_ALWAYS'. See {@link gl:stencilFuncSeparate/4} -%% . -%% -%% `?GL_STENCIL_BACK_PASS_DEPTH_FAIL': `Params' returns one value, a symbolic constant -%% indicating what action is taken for back-facing polygons when the stencil test passes, -%% but the depth test fails. The initial value is `?GL_KEEP'. See {@link gl:stencilOpSeparate/4} -%% . -%% -%% `?GL_STENCIL_BACK_PASS_DEPTH_PASS': `Params' returns one value, a symbolic constant -%% indicating what action is taken for back-facing polygons when the stencil test passes -%% and the depth test passes. The initial value is `?GL_KEEP'. See {@link gl:stencilOpSeparate/4} -%% . -%% -%% `?GL_STENCIL_BACK_REF': `Params' returns one value, the reference value that -%% is compared with the contents of the stencil buffer for back-facing polygons. The initial -%% value is 0. See {@link gl:stencilFuncSeparate/4} . -%% -%% `?GL_STENCIL_BACK_VALUE_MASK': `Params' returns one value, the mask that is -%% used for back-facing polygons to mask both the stencil reference value and the stencil -%% buffer value before they are compared. The initial value is all 1's. See {@link gl:stencilFuncSeparate/4} -%% . -%% -%% `?GL_STENCIL_BACK_WRITEMASK': `Params' returns one value, the mask that controls -%% writing of the stencil bitplanes for back-facing polygons. The initial value is all 1's. -%% See {@link gl:stencilMaskSeparate/2} . -%% -%% `?GL_STENCIL_CLEAR_VALUE': `Params' returns one value, the index to which the -%% stencil bitplanes are cleared. The initial value is 0. See {@link gl:clearStencil/1} . -%% -%% `?GL_STENCIL_FAIL': `Params' returns one value, a symbolic constant indicating -%% what action is taken when the stencil test fails. The initial value is `?GL_KEEP'. -%% See {@link gl:stencilOp/3} . This stencil state only affects non-polygons and front-facing -%% polygons. Back-facing polygons use separate stencil state. See {@link gl:stencilOpSeparate/4} -%% . -%% -%% `?GL_STENCIL_FUNC': `Params' returns one value, a symbolic constant indicating -%% what function is used to compare the stencil reference value with the stencil buffer value. -%% The initial value is `?GL_ALWAYS'. See {@link gl:stencilFunc/3} . This stencil state -%% only affects non-polygons and front-facing polygons. Back-facing polygons use separate -%% stencil state. See {@link gl:stencilFuncSeparate/4} . -%% -%% `?GL_STENCIL_PASS_DEPTH_FAIL': `Params' returns one value, a symbolic constant -%% indicating what action is taken when the stencil test passes, but the depth test fails. -%% The initial value is `?GL_KEEP'. See {@link gl:stencilOp/3} . This stencil state only -%% affects non-polygons and front-facing polygons. Back-facing polygons use separate stencil -%% state. See {@link gl:stencilOpSeparate/4} . -%% -%% `?GL_STENCIL_PASS_DEPTH_PASS': `Params' returns one value, a symbolic constant -%% indicating what action is taken when the stencil test passes and the depth test passes. -%% The initial value is `?GL_KEEP'. See {@link gl:stencilOp/3} . This stencil state only -%% affects non-polygons and front-facing polygons. Back-facing polygons use separate stencil -%% state. See {@link gl:stencilOpSeparate/4} . -%% -%% `?GL_STENCIL_REF': `Params' returns one value, the reference value that is compared -%% with the contents of the stencil buffer. The initial value is 0. See {@link gl:stencilFunc/3} -%% . This stencil state only affects non-polygons and front-facing polygons. Back-facing -%% polygons use separate stencil state. See {@link gl:stencilFuncSeparate/4} . -%% -%% `?GL_STENCIL_TEST': `Params' returns a single boolean value indicating whether -%% stencil testing of fragments is enabled. The initial value is `?GL_FALSE'. See {@link gl:stencilFunc/3} -%% and {@link gl:stencilOp/3} . -%% -%% `?GL_STENCIL_VALUE_MASK': `Params' returns one value, the mask that is used -%% to mask both the stencil reference value and the stencil buffer value before they are -%% compared. The initial value is all 1's. See {@link gl:stencilFunc/3} . This stencil state -%% only affects non-polygons and front-facing polygons. Back-facing polygons use separate -%% stencil state. See {@link gl:stencilFuncSeparate/4} . -%% -%% `?GL_STENCIL_WRITEMASK': `Params' returns one value, the mask that controls -%% writing of the stencil bitplanes. The initial value is all 1's. See {@link gl:stencilMask/1} -%% . This stencil state only affects non-polygons and front-facing polygons. Back-facing -%% polygons use separate stencil state. See {@link gl:stencilMaskSeparate/2} . -%% -%% `?GL_STEREO': `Params' returns a single boolean value indicating whether stereo -%% buffers (left and right) are supported. -%% -%% `?GL_SUBPIXEL_BITS': `Params' returns one value, an estimate of the number of -%% bits of subpixel resolution that are used to position rasterized geometry in window coordinates. -%% The value must be at least 4. -%% -%% `?GL_TEXTURE_BINDING_1D': `Params' returns a single value, the name of the texture -%% currently bound to the target `?GL_TEXTURE_1D'. The initial value is 0. See {@link gl:bindTexture/2} -%% . -%% -%% `?GL_TEXTURE_BINDING_1D_ARRAY': `Params' returns a single value, the name of -%% the texture currently bound to the target `?GL_TEXTURE_1D_ARRAY'. The initial value -%% is 0. See {@link gl:bindTexture/2} . -%% -%% `?GL_TEXTURE_BINDING_2D': `Params' returns a single value, the name of the texture -%% currently bound to the target `?GL_TEXTURE_2D'. The initial value is 0. See {@link gl:bindTexture/2} -%% . -%% -%% `?GL_TEXTURE_BINDING_2D_ARRAY': `Params' returns a single value, the name of -%% the texture currently bound to the target `?GL_TEXTURE_2D_ARRAY'. The initial value -%% is 0. See {@link gl:bindTexture/2} . -%% -%% `?GL_TEXTURE_BINDING_2D_MULTISAMPLE': `Params' returns a single value, the name -%% of the texture currently bound to the target `?GL_TEXTURE_2D_MULTISAMPLE'. The initial -%% value is 0. See {@link gl:bindTexture/2} . -%% -%% `?GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY': `Params' returns a single value, -%% the name of the texture currently bound to the target `?GL_TEXTURE_2D_MULTISAMPLE_ARRAY' -%% . The initial value is 0. See {@link gl:bindTexture/2} . -%% -%% `?GL_TEXTURE_BINDING_3D': `Params' returns a single value, the name of the texture -%% currently bound to the target `?GL_TEXTURE_3D'. The initial value is 0. See {@link gl:bindTexture/2} -%% . -%% -%% `?GL_TEXTURE_BINDING_BUFFER': `Params' returns a single value, the name of the -%% texture currently bound to the target `?GL_TEXTURE_BUFFER'. The initial value is -%% 0. See {@link gl:bindTexture/2} . -%% -%% `?GL_TEXTURE_BINDING_CUBE_MAP': `Params' returns a single value, the name of -%% the texture currently bound to the target `?GL_TEXTURE_CUBE_MAP'. The initial value -%% is 0. See {@link gl:bindTexture/2} . -%% -%% `?GL_TEXTURE_BINDING_RECTANGLE': `Params' returns a single value, the name of -%% the texture currently bound to the target `?GL_TEXTURE_RECTANGLE'. The initial value -%% is 0. See {@link gl:bindTexture/2} . -%% -%% `?GL_TEXTURE_COMPRESSION_HINT': `Params' returns a single value indicating the -%% mode of the texture compression hint. The initial value is `?GL_DONT_CARE'. -%% -%% `?GL_TEXTURE_BUFFER_BINDING': `Params' returns a single value, the name of the -%% texture buffer object currently bound. The initial value is 0. See {@link gl:bindBuffer/2} . -%% -%% -%% `?GL_TIMESTAMP': `Params' returns a single value, the 64-bit value of the current -%% GL time. See {@link gl:queryCounter/2} . -%% -%% `?GL_TRANSFORM_FEEDBACK_BUFFER_BINDING': When used with non-indexed variants of ``gl:get'' -%% (such as ``gl:getIntegerv''), `Params' returns a single value, the name of the -%% buffer object currently bound to the target `?GL_TRANSFORM_FEEDBACK_BUFFER'. If no -%% buffer object is bound to this target, 0 is returned. When used with indexed variants of ``gl:get'' -%% (such as ``gl:getIntegeri_v''), `Params' returns a single value, the name of the -%% buffer object bound to the indexed transform feedback attribute stream. The initial value -%% is 0 for all targets. See {@link gl:bindBuffer/2} , {@link gl:bindBufferBase/3} , and {@link gl:bindBufferRange/5} -%% . -%% -%% `?GL_TRANSFORM_FEEDBACK_BUFFER_START': When used with indexed variants of ``gl:get'' -%% (such as ``gl:getInteger64i_v''), `Params' returns a single value, the start offset -%% of the binding range for each transform feedback attribute stream. The initial value is -%% 0 for all streams. See {@link gl:bindBufferRange/5} . -%% -%% `?GL_TRANSFORM_FEEDBACK_BUFFER_SIZE': When used with indexed variants of ``gl:get'' -%% (such as ``gl:getInteger64i_v''), `Params' returns a single value, the size of -%% the binding range for each transform feedback attribute stream. The initial value is 0 -%% for all streams. See {@link gl:bindBufferRange/5} . -%% -%% `?GL_UNIFORM_BUFFER_BINDING': When used with non-indexed variants of ``gl:get'' -%% (such as ``gl:getIntegerv''), `Params' returns a single value, the name of the -%% buffer object currently bound to the target `?GL_UNIFORM_BUFFER'. If no buffer object -%% is bound to this target, 0 is returned. When used with indexed variants of ``gl:get'' -%% (such as ``gl:getIntegeri_v''), `Params' returns a single value, the name of the -%% buffer object bound to the indexed uniform buffer binding point. The initial value is -%% 0 for all targets. See {@link gl:bindBuffer/2} , {@link gl:bindBufferBase/3} , and {@link gl:bindBufferRange/5} -%% . -%% -%% `?GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT': `Params' returns a single value, the -%% minimum required alignment for uniform buffer sizes and offset. The initial value is 1. -%% See {@link gl:uniformBlockBinding/3} . -%% -%% `?GL_UNIFORM_BUFFER_SIZE': When used with indexed variants of ``gl:get'' (such -%% as ``gl:getInteger64i_v''), `Params' returns a single value, the size of the binding -%% range for each indexed uniform buffer binding. The initial value is 0 for all bindings. -%% See {@link gl:bindBufferRange/5} . -%% -%% `?GL_UNIFORM_BUFFER_START': When used with indexed variants of ``gl:get'' (such -%% as ``gl:getInteger64i_v''), `Params' returns a single value, the start offset of -%% the binding range for each indexed uniform buffer binding. The initial value is 0 for -%% all bindings. See {@link gl:bindBufferRange/5} . -%% -%% `?GL_UNPACK_ALIGNMENT': `Params' returns one value, the byte alignment used -%% for reading pixel data from memory. The initial value is 4. See {@link gl:pixelStoref/2} . -%% -%% `?GL_UNPACK_IMAGE_HEIGHT': `Params' returns one value, the image height used -%% for reading pixel data from memory. The initial is 0. See {@link gl:pixelStoref/2} . -%% -%% `?GL_UNPACK_LSB_FIRST': `Params' returns a single boolean value indicating whether -%% single-bit pixels being read from memory are read first from the least significant bit -%% of each unsigned byte. The initial value is `?GL_FALSE'. See {@link gl:pixelStoref/2} . -%% -%% -%% `?GL_UNPACK_ROW_LENGTH': `Params' returns one value, the row length used for -%% reading pixel data from memory. The initial value is 0. See {@link gl:pixelStoref/2} . -%% -%% `?GL_UNPACK_SKIP_IMAGES': `Params' returns one value, the number of pixel images -%% skipped before the first pixel is read from memory. The initial value is 0. See {@link gl:pixelStoref/2} -%% . -%% -%% `?GL_UNPACK_SKIP_PIXELS': `Params' returns one value, the number of pixel locations -%% skipped before the first pixel is read from memory. The initial value is 0. See {@link gl:pixelStoref/2} -%% . -%% -%% `?GL_UNPACK_SKIP_ROWS': `Params' returns one value, the number of rows of pixel -%% locations skipped before the first pixel is read from memory. The initial value is 0. -%% See {@link gl:pixelStoref/2} . -%% -%% `?GL_UNPACK_SWAP_BYTES': `Params' returns a single boolean value indicating -%% whether the bytes of two-byte and four-byte pixel indices and components are swapped after -%% being read from memory. The initial value is `?GL_FALSE'. See {@link gl:pixelStoref/2} . -%% -%% -%% `?GL_VERTEX_PROGRAM_POINT_SIZE': `Params' returns a single boolean value indicating -%% whether vertex program point size mode is enabled. If enabled, and a vertex shader is -%% active, then the point size is taken from the shader built-in gl_PointSize. If disabled, -%% and a vertex shader is active, then the point size is taken from the point state as specified -%% by {@link gl:pointSize/1} . The initial value is `?GL_FALSE'. -%% -%% `?GL_VIEWPORT': When used with non-indexed variants of ``gl:get'' (such as ``gl:getIntegerv'' -%% ), `Params' returns four values: the x and y window coordinates of the viewport, -%% followed by its width and height. Initially the x and y window coordinates are both -%% set to 0, and the width and height are set to the width and height of the window into -%% which the GL will do its rendering. See {@link gl:viewport/4} . When used with indexed -%% variants of ``gl:get'' (such as ``gl:getIntegeri_v''), `Params' returns four -%% values: the x and y window coordinates of the indexed viewport, followed by its width -%% and height. Initially the x and y window coordinates are both set to 0, and the width -%% and height are set to the width and height of the window into which the GL will do its -%% rendering. See {@link gl:viewportIndexedf/5} . -%% -%% `?GL_VIEWPORT_BOUNDS_RANGE': `Params' returns two values, the minimum and maximum -%% viewport bounds range. The minimum range should be at least [-32768, 32767]. -%% -%% `?GL_VIEWPORT_INDEX_PROVOKING_VERTEX': `Params' returns one value, the implementation -%% dependent specifc vertex of a primitive that is used to select the viewport index. If -%% the value returned is equivalent to `?GL_PROVOKING_VERTEX', then the vertex selection -%% follows the convention specified by {@link gl:provokingVertex/1} . If the value returned -%% is equivalent to `?GL_FIRST_VERTEX_CONVENTION', then the selection is always taken -%% from the first vertex in the primitive. If the value returned is equivalent to `?GL_LAST_VERTEX_CONVENTION' -%% , then the selection is always taken from the last vertex in the primitive. If the value -%% returned is equivalent to `?GL_UNDEFINED_VERTEX', then the selection is not guaranteed -%% to be taken from any specific vertex in the primitive. -%% -%% `?GL_VIEWPORT_SUBPIXEL_BITS': `Params' returns a single value, the number of -%% bits of sub-pixel precision which the GL uses to interpret the floating point viewport -%% bounds. The minimum value is 0. -%% -%% Many of the boolean parameters can also be queried more easily using {@link gl:isEnabled/1} -%% . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGet.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGet.xhtml">external</a> documentation. -spec getBooleanv(Pname) -> [0|1] when Pname :: enum(). getBooleanv(Pname) -> call(5065, <<Pname:?GLenum>>). @@ -1968,131 +698,7 @@ getIntegerv(Pname) -> %% together. The special mask `?GL_ALL_ATTRIB_BITS' can be used to save all stackable %% states. %% -%% The symbolic mask constants and their associated GL state are as follows (the second -%% column lists which attributes are saved): -%% -%% <table><tbody><tr><td>`?GL_ACCUM_BUFFER_BIT'</td><td> Accumulation buffer clear value -%% </td></tr><tr><td>`?GL_COLOR_BUFFER_BIT'</td><td>`?GL_ALPHA_TEST' enable bit </td> -%% </tr><tr><td></td><td> Alpha test function and reference value </td></tr><tr><td></td><td> -%% `?GL_BLEND' enable bit </td></tr><tr><td></td><td> Blending source and destination -%% functions </td></tr><tr><td></td><td> Constant blend color </td></tr><tr><td></td><td> -%% Blending equation </td></tr><tr><td></td><td>`?GL_DITHER' enable bit </td></tr><tr><td> -%% </td><td>`?GL_DRAW_BUFFER' setting </td></tr><tr><td></td><td>`?GL_COLOR_LOGIC_OP' -%% enable bit </td></tr><tr><td></td><td>`?GL_INDEX_LOGIC_OP' enable bit </td></tr><tr> -%% <td></td><td> Logic op function </td></tr><tr><td></td><td> Color mode and index mode -%% clear values </td></tr><tr><td></td><td> Color mode and index mode writemasks </td></tr><tr> -%% <td>`?GL_CURRENT_BIT'</td><td> Current RGBA color </td></tr><tr><td></td><td> Current -%% color index </td></tr><tr><td></td><td> Current normal vector </td></tr><tr><td></td><td> -%% Current texture coordinates </td></tr><tr><td></td><td> Current raster position </td></tr> -%% <tr><td></td><td>`?GL_CURRENT_RASTER_POSITION_VALID' flag </td></tr><tr><td></td><td> -%% RGBA color associated with current raster position </td></tr><tr><td></td><td> Color -%% index associated with current raster position </td></tr><tr><td></td><td> Texture coordinates -%% associated with current raster position </td></tr><tr><td></td><td>`?GL_EDGE_FLAG' -%% flag </td></tr><tr><td>`?GL_DEPTH_BUFFER_BIT'</td><td>`?GL_DEPTH_TEST' enable -%% bit </td></tr><tr><td></td><td> Depth buffer test function </td></tr><tr><td></td><td> -%% Depth buffer clear value </td></tr><tr><td></td><td>`?GL_DEPTH_WRITEMASK' enable -%% bit </td></tr><tr><td>`?GL_ENABLE_BIT'</td><td>`?GL_ALPHA_TEST' flag </td></tr><tr> -%% <td></td><td>`?GL_AUTO_NORMAL' flag </td></tr><tr><td></td><td>`?GL_BLEND' flag -%% </td></tr><tr><td></td><td> Enable bits for the user-definable clipping planes </td></tr><tr> -%% <td></td><td>`?GL_COLOR_MATERIAL'</td></tr><tr><td></td><td>`?GL_CULL_FACE' -%% flag </td></tr><tr><td></td><td>`?GL_DEPTH_TEST' flag </td></tr><tr><td></td><td>`?GL_DITHER' -%% flag </td></tr><tr><td></td><td>`?GL_FOG' flag </td></tr><tr><td></td><td>`?GL_LIGHT' -%% `i' where `?0' <= `i' < `?GL_MAX_LIGHTS'</td></tr> -%% <tr><td></td><td>`?GL_LIGHTING' flag </td></tr><tr><td></td><td>`?GL_LINE_SMOOTH' -%% flag </td></tr><tr><td></td><td>`?GL_LINE_STIPPLE' flag </td></tr><tr><td></td><td>`?GL_COLOR_LOGIC_OP' -%% flag </td></tr><tr><td></td><td>`?GL_INDEX_LOGIC_OP' flag </td></tr><tr><td></td><td> -%% `?GL_MAP1_'`x' where `x' is a map type </td></tr><tr><td></td><td>`?GL_MAP2_' -%% `x' where `x' is a map type </td></tr><tr><td></td><td>`?GL_MULTISAMPLE' -%% flag </td></tr><tr><td></td><td>`?GL_NORMALIZE' flag </td></tr><tr><td></td><td>`?GL_POINT_SMOOTH' -%% flag </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_LINE' flag </td></tr><tr><td></td> -%% <td>`?GL_POLYGON_OFFSET_FILL' flag </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_POINT' -%% flag </td></tr><tr><td></td><td>`?GL_POLYGON_SMOOTH' flag </td></tr><tr><td></td><td> -%% `?GL_POLYGON_STIPPLE' flag </td></tr><tr><td></td><td>`?GL_SAMPLE_ALPHA_TO_COVERAGE' -%% flag </td></tr><tr><td></td><td>`?GL_SAMPLE_ALPHA_TO_ONE' flag </td></tr><tr><td></td> -%% <td>`?GL_SAMPLE_COVERAGE' flag </td></tr><tr><td></td><td>`?GL_SCISSOR_TEST' -%% flag </td></tr><tr><td></td><td>`?GL_STENCIL_TEST' flag </td></tr><tr><td></td><td>`?GL_TEXTURE_1D' -%% flag </td></tr><tr><td></td><td>`?GL_TEXTURE_2D' flag </td></tr><tr><td></td><td>`?GL_TEXTURE_3D' -%% flag </td></tr><tr><td></td><td> Flags `?GL_TEXTURE_GEN_'`x' where `x' -%% is S, T, R, or Q </td></tr><tr><td>`?GL_EVAL_BIT'</td><td>`?GL_MAP1_'`x' -%% enable bits, where `x' is a map type </td></tr><tr><td></td><td>`?GL_MAP2_'`x' -%% enable bits, where `x' is a map type </td></tr><tr><td></td><td> 1D grid endpoints -%% and divisions </td></tr><tr><td></td><td> 2D grid endpoints and divisions </td></tr><tr><td> -%% </td><td>`?GL_AUTO_NORMAL' enable bit </td></tr><tr><td>`?GL_FOG_BIT'</td><td>`?GL_FOG' -%% enable bit </td></tr><tr><td></td><td> Fog color </td></tr><tr><td></td><td> Fog density -%% </td></tr><tr><td></td><td> Linear fog start </td></tr><tr><td></td><td> Linear fog end </td> -%% </tr><tr><td></td><td> Fog index </td></tr><tr><td></td><td>`?GL_FOG_MODE' value </td> -%% </tr><tr><td>`?GL_HINT_BIT'</td><td>`?GL_PERSPECTIVE_CORRECTION_HINT' setting </td> -%% </tr><tr><td></td><td>`?GL_POINT_SMOOTH_HINT' setting </td></tr><tr><td></td><td>`?GL_LINE_SMOOTH_HINT' -%% setting </td></tr><tr><td></td><td>`?GL_POLYGON_SMOOTH_HINT' setting </td></tr><tr><td> -%% </td><td>`?GL_FOG_HINT' setting </td></tr><tr><td></td><td>`?GL_GENERATE_MIPMAP_HINT' -%% setting </td></tr><tr><td></td><td>`?GL_TEXTURE_COMPRESSION_HINT' setting </td></tr> -%% <tr><td>`?GL_LIGHTING_BIT'</td><td>`?GL_COLOR_MATERIAL' enable bit </td></tr><tr> -%% <td></td><td>`?GL_COLOR_MATERIAL_FACE' value </td></tr><tr><td></td><td> Color material -%% parameters that are tracking the current color </td></tr><tr><td></td><td> Ambient scene -%% color </td></tr><tr><td></td><td>`?GL_LIGHT_MODEL_LOCAL_VIEWER' value </td></tr><tr><td> -%% </td><td>`?GL_LIGHT_MODEL_TWO_SIDE' setting </td></tr><tr><td></td><td>`?GL_LIGHTING' -%% enable bit </td></tr><tr><td></td><td> Enable bit for each light </td></tr><tr><td></td><td> -%% Ambient, diffuse, and specular intensity for each light </td></tr><tr><td></td><td> Direction, -%% position, exponent, and cutoff angle for each light </td></tr><tr><td></td><td> Constant, -%% linear, and quadratic attenuation factors for each light </td></tr><tr><td></td><td> Ambient, -%% diffuse, specular, and emissive color for each material </td></tr><tr><td></td><td> Ambient, -%% diffuse, and specular color indices for each material </td></tr><tr><td></td><td> Specular -%% exponent for each material </td></tr><tr><td></td><td>`?GL_SHADE_MODEL' setting </td> -%% </tr><tr><td>`?GL_LINE_BIT'</td><td>`?GL_LINE_SMOOTH' flag </td></tr><tr><td></td> -%% <td>`?GL_LINE_STIPPLE' enable bit </td></tr><tr><td></td><td> Line stipple pattern -%% and repeat counter </td></tr><tr><td></td><td> Line width </td></tr><tr><td>`?GL_LIST_BIT' -%% </td><td>`?GL_LIST_BASE' setting </td></tr><tr><td>`?GL_MULTISAMPLE_BIT'</td><td> -%% `?GL_MULTISAMPLE' flag </td></tr><tr><td></td><td>`?GL_SAMPLE_ALPHA_TO_COVERAGE' -%% flag </td></tr><tr><td></td><td>`?GL_SAMPLE_ALPHA_TO_ONE' flag </td></tr><tr><td></td> -%% <td>`?GL_SAMPLE_COVERAGE' flag </td></tr><tr><td></td><td>`?GL_SAMPLE_COVERAGE_VALUE' -%% value </td></tr><tr><td></td><td>`?GL_SAMPLE_COVERAGE_INVERT' value </td></tr><tr><td> -%% `?GL_PIXEL_MODE_BIT'</td><td>`?GL_RED_BIAS' and `?GL_RED_SCALE' settings </td> -%% </tr><tr><td></td><td>`?GL_GREEN_BIAS' and `?GL_GREEN_SCALE' values </td></tr><tr> -%% <td></td><td>`?GL_BLUE_BIAS' and `?GL_BLUE_SCALE'</td></tr><tr><td></td><td>`?GL_ALPHA_BIAS' -%% and `?GL_ALPHA_SCALE'</td></tr><tr><td></td><td>`?GL_DEPTH_BIAS' and `?GL_DEPTH_SCALE' -%% </td></tr><tr><td></td><td>`?GL_INDEX_OFFSET' and `?GL_INDEX_SHIFT' values </td> -%% </tr><tr><td></td><td>`?GL_MAP_COLOR' and `?GL_MAP_STENCIL' flags </td></tr><tr> -%% <td></td><td>`?GL_ZOOM_X' and `?GL_ZOOM_Y' factors </td></tr><tr><td></td><td>`?GL_READ_BUFFER' -%% setting </td></tr><tr><td>`?GL_POINT_BIT'</td><td>`?GL_POINT_SMOOTH' flag </td> -%% </tr><tr><td></td><td> Point size </td></tr><tr><td>`?GL_POLYGON_BIT'</td><td>`?GL_CULL_FACE' -%% enable bit </td></tr><tr><td></td><td>`?GL_CULL_FACE_MODE' value </td></tr><tr><td></td> -%% <td>`?GL_FRONT_FACE' indicator </td></tr><tr><td></td><td>`?GL_POLYGON_MODE' -%% setting </td></tr><tr><td></td><td>`?GL_POLYGON_SMOOTH' flag </td></tr><tr><td></td><td> -%% `?GL_POLYGON_STIPPLE' enable bit </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_FILL' -%% flag </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_LINE' flag </td></tr><tr><td></td> -%% <td>`?GL_POLYGON_OFFSET_POINT' flag </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_FACTOR' -%% </td></tr><tr><td></td><td>`?GL_POLYGON_OFFSET_UNITS'</td></tr><tr><td>`?GL_POLYGON_STIPPLE_BIT' -%% </td><td> Polygon stipple image </td></tr><tr><td>`?GL_SCISSOR_BIT'</td><td>`?GL_SCISSOR_TEST' -%% flag </td></tr><tr><td></td><td> Scissor box </td></tr><tr><td>`?GL_STENCIL_BUFFER_BIT' -%% </td><td>`?GL_STENCIL_TEST' enable bit </td></tr><tr><td></td><td> Stencil function -%% and reference value </td></tr><tr><td></td><td> Stencil value mask </td></tr><tr><td></td> -%% <td> Stencil fail, pass, and depth buffer pass actions </td></tr><tr><td></td><td> Stencil -%% buffer clear value </td></tr><tr><td></td><td> Stencil buffer writemask </td></tr><tr><td> -%% `?GL_TEXTURE_BIT'</td><td> Enable bits for the four texture coordinates </td></tr><tr> -%% <td></td><td> Border color for each texture image </td></tr><tr><td></td><td> Minification -%% function for each texture image </td></tr><tr><td></td><td> Magnification function for -%% each texture image </td></tr><tr><td></td><td> Texture coordinates and wrap mode for each -%% texture image </td></tr><tr><td></td><td> Color and mode for each texture environment </td> -%% </tr><tr><td></td><td> Enable bits `?GL_TEXTURE_GEN_'`x', `x' is S, T, -%% R, and Q </td></tr><tr><td></td><td>`?GL_TEXTURE_GEN_MODE' setting for S, T, R, and -%% Q </td></tr><tr><td></td><td> {@link gl:texGend/3} plane equations for S, T, R, and Q </td></tr> -%% <tr><td></td><td> Current texture bindings (for example, `?GL_TEXTURE_BINDING_2D') </td> -%% </tr><tr><td>`?GL_TRANSFORM_BIT'</td><td> Coefficients of the six clipping planes </td> -%% </tr><tr><td></td><td> Enable bits for the user-definable clipping planes </td></tr><tr><td> -%% </td><td>`?GL_MATRIX_MODE' value </td></tr><tr><td></td><td>`?GL_NORMALIZE' -%% flag </td></tr><tr><td></td><td>`?GL_RESCALE_NORMAL' flag </td></tr><tr><td>`?GL_VIEWPORT_BIT' -%% </td><td> Depth range (near and far) </td></tr><tr><td></td><td> Viewport origin and extent -%% </td></tr></tbody></table> -%% -%% {@link gl:pushAttrib/1} restores the values of the state variables saved with the last ``gl:pushAttrib'' -%% command. Those not saved are left unchanged. -%% -%% It is an error to push attributes onto a full stack or to pop attributes off an empty -%% stack. In either case, the error flag is set and no other change is made to GL state. -%% -%% Initially, the attribute stack is empty. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPushAttrib.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPushAttrib.xml">external</a> documentation. -spec pushAttrib(Mask) -> 'ok' when Mask :: integer(). pushAttrib(Mask) -> cast(5069, <<Mask:?GLbitfield>>). @@ -2111,22 +717,7 @@ popAttrib() -> %% of these constants together. The special mask `?GL_CLIENT_ALL_ATTRIB_BITS' can %% be used to save all stackable client state. %% -%% The symbolic mask constants and their associated GL client state are as follows (the -%% second column lists which attributes are saved): -%% -%% `?GL_CLIENT_PIXEL_STORE_BIT' Pixel storage modes `?GL_CLIENT_VERTEX_ARRAY_BIT' -%% Vertex arrays (and enables) -%% -%% {@link gl:pushClientAttrib/1} restores the values of the client-state variables saved with -%% the last ``gl:pushClientAttrib''. Those not saved are left unchanged. -%% -%% It is an error to push attributes onto a full client attribute stack or to pop attributes -%% off an empty stack. In either case, the error flag is set, and no other change is made -%% to GL state. -%% -%% Initially, the client attribute stack is empty. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPushClientAttrib.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPushClientAttrib.xml">external</a> documentation. -spec pushClientAttrib(Mask) -> 'ok' when Mask :: integer(). pushClientAttrib(Mask) -> cast(5071, <<Mask:?GLbitfield>>). @@ -2142,37 +733,7 @@ popClientAttrib() -> %% ``gl:renderMode'' sets the rasterization mode. It takes one argument, `Mode' , which %% can assume one of three predefined values: %% -%% `?GL_RENDER': Render mode. Primitives are rasterized, producing pixel fragments, -%% which are written into the frame buffer. This is the normal mode and also the default -%% mode. -%% -%% `?GL_SELECT': Selection mode. No pixel fragments are produced, and no change to -%% the frame buffer contents is made. Instead, a record of the names of primitives that would -%% have been drawn if the render mode had been `?GL_RENDER' is returned in a select -%% buffer, which must be created (see {@link gl:selectBuffer/2} ) before selection mode is -%% entered. -%% -%% `?GL_FEEDBACK': Feedback mode. No pixel fragments are produced, and no change to -%% the frame buffer contents is made. Instead, the coordinates and attributes of vertices -%% that would have been drawn if the render mode had been `?GL_RENDER' is returned in -%% a feedback buffer, which must be created (see {@link gl:feedbackBuffer/3} ) before feedback -%% mode is entered. -%% -%% The return value of ``gl:renderMode'' is determined by the render mode at the time ``gl:renderMode'' -%% is called, rather than by `Mode' . The values returned for the three render modes -%% are as follows: -%% -%% `?GL_RENDER': 0. -%% -%% `?GL_SELECT': The number of hit records transferred to the select buffer. -%% -%% `?GL_FEEDBACK': The number of values (not vertices) transferred to the feedback -%% buffer. -%% -%% See the {@link gl:selectBuffer/2} and {@link gl:feedbackBuffer/3} reference pages for more -%% details concerning selection and feedback operation. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRenderMode.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glRenderMode.xml">external</a> documentation. -spec renderMode(Mode) -> integer() when Mode :: enum(). renderMode(Mode) -> call(5073, <<Mode:?GLenum>>). @@ -2186,44 +747,7 @@ renderMode(Mode) -> %% returns `?GL_NO_ERROR', there has been no detectable error since the last call to ``gl:getError'' %% , or since the GL was initialized. %% -%% To allow for distributed implementations, there may be several error flags. If any single -%% error flag has recorded an error, the value of that flag is returned and that flag is -%% reset to `?GL_NO_ERROR' when ``gl:getError'' is called. If more than one flag has -%% recorded an error, ``gl:getError'' returns and clears an arbitrary error flag value. -%% Thus, ``gl:getError'' should always be called in a loop, until it returns `?GL_NO_ERROR' -%% , if all error flags are to be reset. -%% -%% Initially, all error flags are set to `?GL_NO_ERROR'. -%% -%% The following errors are currently defined: -%% -%% `?GL_NO_ERROR': No error has been recorded. The value of this symbolic constant -%% is guaranteed to be 0. -%% -%% `?GL_INVALID_ENUM': An unacceptable value is specified for an enumerated argument. -%% The offending command is ignored and has no other side effect than to set the error flag. -%% -%% -%% `?GL_INVALID_VALUE': A numeric argument is out of range. The offending command is -%% ignored and has no other side effect than to set the error flag. -%% -%% `?GL_INVALID_OPERATION': The specified operation is not allowed in the current state. -%% The offending command is ignored and has no other side effect than to set the error flag. -%% -%% -%% `?GL_INVALID_FRAMEBUFFER_OPERATION': The framebuffer object is not complete. The -%% offending command is ignored and has no other side effect than to set the error flag. -%% -%% `?GL_OUT_OF_MEMORY': There is not enough memory left to execute the command. The -%% state of the GL is undefined, except for the state of the error flags, after this error -%% is recorded. -%% -%% When an error flag is set, results of a GL operation are undefined only if `?GL_OUT_OF_MEMORY' -%% has occurred. In all other cases, the command generating the error is ignored and has -%% no effect on the GL state or frame buffer contents. If the generating command returns -%% a value, it returns 0. If ``gl:getError'' itself generates an error, it returns 0. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetError.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetError.xhtml">external</a> documentation. -spec getError() -> enum(). getError() -> call(5074, <<>>). @@ -2233,40 +757,7 @@ getError() -> %% ``gl:getString'' returns a pointer to a static string describing some aspect of the %% current GL connection. `Name' can be one of the following: %% -%% `?GL_VENDOR': Returns the company responsible for this GL implementation. This name -%% does not change from release to release. -%% -%% `?GL_RENDERER': Returns the name of the renderer. This name is typically specific -%% to a particular configuration of a hardware platform. It does not change from release -%% to release. -%% -%% `?GL_VERSION': Returns a version or release number. -%% -%% `?GL_SHADING_LANGUAGE_VERSION': Returns a version or release number for the shading -%% language. -%% -%% ``gl:getStringi'' returns a pointer to a static string indexed by `Index' . `Name' -%% can be one of the following: -%% -%% `?GL_EXTENSIONS': For ``gl:getStringi'' only, returns the extension string supported -%% by the implementation at `Index' . -%% -%% Strings `?GL_VENDOR' and `?GL_RENDERER' together uniquely specify a platform. -%% They do not change from release to release and should be used by platform-recognition -%% algorithms. -%% -%% The `?GL_VERSION' and `?GL_SHADING_LANGUAGE_VERSION' strings begin with a version -%% number. The version number uses one of these forms: -%% -%% `major_number.minor_number'`major_number.minor_number.release_number' -%% -%% Vendor-specific information may follow the version number. Its format depends on the -%% implementation, but a space always separates the version number and the vendor-specific -%% information. -%% -%% All strings are null-terminated. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetString.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetString.xhtml">external</a> documentation. -spec getString(Name) -> string() when Name :: enum(). getString(Name) -> call(5075, <<Name:?GLenum>>). @@ -2277,7 +768,7 @@ getString(Name) -> %% are complete. Such effects include all changes to GL state, all changes to connection %% state, and all changes to the frame buffer contents. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFinish.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glFinish.xhtml">external</a> documentation. -spec finish() -> 'ok'. finish() -> cast(5076, <<>>). @@ -2290,12 +781,7 @@ finish() -> %% the actual rendering engine. Though this execution may not be completed in any particular %% time period, it does complete in finite time. %% -%% Because any GL program might be executed over a network, or on an accelerator that buffers -%% commands, all programs should call ``gl:flush'' whenever they count on having all of -%% their previously issued commands completed. For example, call ``gl:flush'' before waiting -%% for user input that depends on the generated image. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFlush.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glFlush.xhtml">external</a> documentation. -spec flush() -> 'ok'. flush() -> cast(5077, <<>>). @@ -2308,36 +794,7 @@ flush() -> %% indicating the desired behavior. The initial value for each `Target' is `?GL_DONT_CARE' %% . `Mode' can be one of the following: %% -%% `?GL_FASTEST': The most efficient option should be chosen. -%% -%% `?GL_NICEST': The most correct, or highest quality, option should be chosen. -%% -%% `?GL_DONT_CARE': No preference. -%% -%% Though the implementation aspects that can be hinted are well defined, the interpretation -%% of the hints depends on the implementation. The hint aspects that can be specified with `Target' -%% , along with suggested semantics, are as follows: -%% -%% `?GL_FRAGMENT_SHADER_DERIVATIVE_HINT': Indicates the accuracy of the derivative -%% calculation for the GL shading language fragment processing built-in functions: `?dFdx' -%% , `?dFdy', and `?fwidth'. -%% -%% `?GL_LINE_SMOOTH_HINT': Indicates the sampling quality of antialiased lines. If -%% a larger filter function is applied, hinting `?GL_NICEST' can result in more pixel -%% fragments being generated during rasterization. -%% -%% `?GL_POLYGON_SMOOTH_HINT': Indicates the sampling quality of antialiased polygons. -%% Hinting `?GL_NICEST' can result in more pixel fragments being generated during rasterization, -%% if a larger filter function is applied. -%% -%% `?GL_TEXTURE_COMPRESSION_HINT': Indicates the quality and performance of the compressing -%% texture images. Hinting `?GL_FASTEST' indicates that texture images should be compressed -%% as quickly as possible, while `?GL_NICEST' indicates that texture images should be -%% compressed with as little image quality loss as possible. `?GL_NICEST' should be -%% selected if the texture is to be retrieved by {@link gl:getCompressedTexImage/3} for reuse. -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glHint.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glHint.xhtml">external</a> documentation. -spec hint(Target, Mode) -> 'ok' when Target :: enum(),Mode :: enum(). hint(Target,Mode) -> cast(5078, <<Target:?GLenum,Mode:?GLenum>>). @@ -2347,7 +804,7 @@ hint(Target,Mode) -> %% ``gl:clearDepth'' specifies the depth value used by {@link gl:clear/1} to clear the depth %% buffer. Values specified by ``gl:clearDepth'' are clamped to the range [0 1]. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearDepth.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glClearDepth.xhtml">external</a> documentation. -spec clearDepth(Depth) -> 'ok' when Depth :: clamp(). clearDepth(Depth) -> cast(5079, <<Depth:?GLclampd>>). @@ -2359,36 +816,7 @@ clearDepth(Depth) -> %% depth testing is enabled. (See {@link gl:enable/1} and {@link gl:enable/1} of `?GL_DEPTH_TEST' %% .) %% -%% `Func' specifies the conditions under which the pixel will be drawn. The comparison -%% functions are as follows: -%% -%% `?GL_NEVER': Never passes. -%% -%% `?GL_LESS': Passes if the incoming depth value is less than the stored depth value. -%% -%% -%% `?GL_EQUAL': Passes if the incoming depth value is equal to the stored depth value. -%% -%% -%% `?GL_LEQUAL': Passes if the incoming depth value is less than or equal to the stored -%% depth value. -%% -%% `?GL_GREATER': Passes if the incoming depth value is greater than the stored depth -%% value. -%% -%% `?GL_NOTEQUAL': Passes if the incoming depth value is not equal to the stored depth -%% value. -%% -%% `?GL_GEQUAL': Passes if the incoming depth value is greater than or equal to the -%% stored depth value. -%% -%% `?GL_ALWAYS': Always passes. -%% -%% The initial value of `Func' is `?GL_LESS'. Initially, depth testing is disabled. -%% If depth testing is disabled or if no depth buffer exists, it is as if the depth test -%% always passes. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthFunc.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDepthFunc.xhtml">external</a> documentation. -spec depthFunc(Func) -> 'ok' when Func :: enum(). depthFunc(Func) -> cast(5080, <<Func:?GLenum>>). @@ -2399,7 +827,7 @@ depthFunc(Func) -> %% is `?GL_FALSE', depth buffer writing is disabled. Otherwise, it is enabled. Initially, %% depth buffer writing is enabled. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthMask.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDepthMask.xhtml">external</a> documentation. -spec depthMask(Flag) -> 'ok' when Flag :: 0|1. depthMask(Flag) -> cast(5081, <<Flag:?GLboolean>>). @@ -2413,10 +841,7 @@ depthMask(Flag) -> %% as though they range from 0 through 1 (like color components). Thus, the values accepted %% by ``gl:depthRange'' are both clamped to this range before they are accepted. %% -%% The setting of (0,1) maps the near plane to 0 and the far plane to 1. With this mapping, -%% the depth buffer range is fully utilized. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthRange.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDepthRange.xhtml">external</a> documentation. -spec depthRange(Near_val, Far_val) -> 'ok' when Near_val :: clamp(),Far_val :: clamp(). depthRange(Near_val,Far_val) -> cast(5082, <<Near_val:?GLclampd,Far_val:?GLclampd>>). @@ -2426,9 +851,7 @@ depthRange(Near_val,Far_val) -> %% ``gl:clearAccum'' specifies the red, green, blue, and alpha values used by {@link gl:clear/1} %% to clear the accumulation buffer. %% -%% Values specified by ``gl:clearAccum'' are clamped to the range [-1 1]. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearAccum.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glClearAccum.xml">external</a> documentation. -spec clearAccum(Red, Green, Blue, Alpha) -> 'ok' when Red :: float(),Green :: float(),Blue :: float(),Alpha :: float(). clearAccum(Red,Green,Blue,Alpha) -> cast(5083, <<Red:?GLfloat,Green:?GLfloat,Blue:?GLfloat,Alpha:?GLfloat>>). @@ -2441,53 +864,7 @@ clearAccum(Red,Green,Blue,Alpha) -> %% and polygons), motion blur, and depth of field can be created by accumulating images generated %% with different transformation matrices. %% -%% Each pixel in the accumulation buffer consists of red, green, blue, and alpha values. -%% The number of bits per component in the accumulation buffer depends on the implementation. -%% You can examine this number by calling {@link gl:getBooleanv/1} four times, with arguments -%% `?GL_ACCUM_RED_BITS', `?GL_ACCUM_GREEN_BITS', `?GL_ACCUM_BLUE_BITS', and `?GL_ACCUM_ALPHA_BITS' -%% . Regardless of the number of bits per component, the range of values stored by each component -%% is [-1 1]. The accumulation buffer pixels are mapped one-to-one with frame buffer pixels. -%% -%% ``gl:accum'' operates on the accumulation buffer. The first argument, `Op' , is -%% a symbolic constant that selects an accumulation buffer operation. The second argument, `Value' -%% , is a floating-point value to be used in that operation. Five operations are specified: `?GL_ACCUM' -%% , `?GL_LOAD', `?GL_ADD', `?GL_MULT', and `?GL_RETURN'. -%% -%% All accumulation buffer operations are limited to the area of the current scissor box -%% and applied identically to the red, green, blue, and alpha components of each pixel. If -%% a ``gl:accum'' operation results in a value outside the range [-1 1], the contents of an -%% accumulation buffer pixel component are undefined. -%% -%% The operations are as follows: -%% -%% `?GL_ACCUM': Obtains R, G, B, and A values from the buffer currently selected for -%% reading (see {@link gl:readBuffer/1} ). Each component value is divided by 2 n-1, where -%% n is the number of bits allocated to each color component in the currently selected buffer. -%% The result is a floating-point value in the range [0 1], which is multiplied by `Value' -%% and added to the corresponding pixel component in the accumulation buffer, thereby updating -%% the accumulation buffer. -%% -%% `?GL_LOAD': Similar to `?GL_ACCUM', except that the current value in the accumulation -%% buffer is not used in the calculation of the new value. That is, the R, G, B, and A values -%% from the currently selected buffer are divided by 2 n-1, multiplied by `Value' , -%% and then stored in the corresponding accumulation buffer cell, overwriting the current -%% value. -%% -%% `?GL_ADD': Adds `Value' to each R, G, B, and A in the accumulation buffer. -%% -%% `?GL_MULT': Multiplies each R, G, B, and A in the accumulation buffer by `Value' -%% and returns the scaled component to its corresponding accumulation buffer location. -%% -%% `?GL_RETURN': Transfers accumulation buffer values to the color buffer or buffers -%% currently selected for writing. Each R, G, B, and A component is multiplied by `Value' -%% , then multiplied by 2 n-1, clamped to the range [0 2 n-1], and stored in the corresponding -%% display buffer cell. The only fragment operations that are applied to this transfer are -%% pixel ownership, scissor, dithering, and color writemasks. -%% -%% To clear the accumulation buffer, call {@link gl:clearAccum/4} with R, G, B, and A values -%% to set it to, then call {@link gl:clear/1} with the accumulation buffer enabled. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAccum.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glAccum.xml">external</a> documentation. -spec accum(Op, Value) -> 'ok' when Op :: enum(),Value :: float(). accum(Op,Value) -> cast(5084, <<Op:?GLenum,Value:?GLfloat>>). @@ -2497,20 +874,7 @@ accum(Op,Value) -> %% ``gl:matrixMode'' sets the current matrix mode. `Mode' can assume one of four values: %% %% -%% `?GL_MODELVIEW': Applies subsequent matrix operations to the modelview matrix stack. -%% -%% -%% `?GL_PROJECTION': Applies subsequent matrix operations to the projection matrix -%% stack. -%% -%% `?GL_TEXTURE': Applies subsequent matrix operations to the texture matrix stack. -%% -%% `?GL_COLOR': Applies subsequent matrix operations to the color matrix stack. -%% -%% To find out which matrix stack is currently the target of all matrix operations, call {@link gl:getBooleanv/1} -%% with argument `?GL_MATRIX_MODE'. The initial value is `?GL_MODELVIEW'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMatrixMode.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glMatrixMode.xml">external</a> documentation. -spec matrixMode(Mode) -> 'ok' when Mode :: enum(). matrixMode(Mode) -> cast(5085, <<Mode:?GLenum>>). @@ -2522,20 +886,7 @@ matrixMode(Mode) -> %% the current matrix, as if {@link gl:multMatrixd/1} were called with the following matrix %% as its argument: %% -%% ((2/(right-left)) 0 0(t x) 0(2/(top-bottom)) 0(t y) 0 0(-2/(farVal-nearVal))(t z) 0 0 0 1) -%% -%% where t x=-((right+left)/(right-left)) t y=-((top+bottom)/(top-bottom)) t z=-((farVal+nearVal)/(farVal-nearVal)) -%% -%% Typically, the matrix mode is `?GL_PROJECTION', and (left bottom-nearVal) and (right top-nearVal) specify the points on -%% the near clipping plane that are mapped to the lower left and upper right corners of the -%% window, respectively, assuming that the eye is located at (0, 0, 0). -farVal specifies -%% the location of the far clipping plane. Both `NearVal' and `FarVal' can be either -%% positive or negative. -%% -%% Use {@link gl:pushMatrix/0} and {@link gl:pushMatrix/0} to save and restore the current -%% matrix stack. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml">external</a> documentation. -spec ortho(Left, Right, Bottom, Top, Near_val, Far_val) -> 'ok' when Left :: float(),Right :: float(),Bottom :: float(),Top :: float(),Near_val :: float(),Far_val :: float(). ortho(Left,Right,Bottom,Top,Near_val,Far_val) -> cast(5086, <<Left:?GLdouble,Right:?GLdouble,Bottom:?GLdouble,Top:?GLdouble,Near_val:?GLdouble,Far_val:?GLdouble>>). @@ -2547,25 +898,7 @@ ortho(Left,Right,Bottom,Top,Near_val,Far_val) -> %% replaces the current matrix, as if {@link gl:multMatrixd/1} were called with the following %% matrix as its argument: %% -%% [((2 nearVal)/(right-left)) 0 A 0 0((2 nearVal)/(top-bottom)) B 0 0 0 C D 0 0 -1 0] -%% -%% A=(right+left)/(right-left) -%% -%% B=(top+bottom)/(top-bottom) -%% -%% C=-((farVal+nearVal)/(farVal-nearVal)) -%% -%% D=-((2 farVal nearVal)/(farVal-nearVal)) -%% -%% Typically, the matrix mode is `?GL_PROJECTION', and (left bottom-nearVal) and (right top-nearVal) specify the points on -%% the near clipping plane that are mapped to the lower left and upper right corners of the -%% window, assuming that the eye is located at (0, 0, 0). -farVal specifies the location -%% of the far clipping plane. Both `NearVal' and `FarVal' must be positive. -%% -%% Use {@link gl:pushMatrix/0} and {@link gl:pushMatrix/0} to save and restore the current -%% matrix stack. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFrustum.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFrustum.xml">external</a> documentation. -spec frustum(Left, Right, Bottom, Top, Near_val, Far_val) -> 'ok' when Left :: float(),Right :: float(),Bottom :: float(),Top :: float(),Near_val :: float(),Far_val :: float(). frustum(Left,Right,Bottom,Top,Near_val,Far_val) -> cast(5087, <<Left:?GLdouble,Right:?GLdouble,Bottom:?GLdouble,Top:?GLdouble,Near_val:?GLdouble,Far_val:?GLdouble>>). @@ -2576,14 +909,7 @@ frustum(Left,Right,Bottom,Top,Near_val,Far_val) -> %% coordinates to window coordinates. Let (x nd y nd) be normalized device coordinates. Then the window %% coordinates (x w y w) are computed as follows: %% -%% x w=(x nd+1) (width/2)+x -%% -%% y w=(y nd+1) (height/2)+y -%% -%% Viewport width and height are silently clamped to a range that depends on the implementation. -%% To query this range, call {@link gl:getBooleanv/1} with argument `?GL_MAX_VIEWPORT_DIMS'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glViewport.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glViewport.xhtml">external</a> documentation. -spec viewport(X, Y, Width, Height) -> 'ok' when X :: integer(),Y :: integer(),Width :: integer(),Height :: integer(). viewport(X,Y,Width,Height) -> cast(5088, <<X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>). @@ -2595,20 +921,7 @@ viewport(X,Y,Width,Height) -> %% , and `?GL_TEXTURE', the depth is at least 2. The current matrix in any mode is the %% matrix on the top of the stack for that mode. %% -%% ``gl:pushMatrix'' pushes the current matrix stack down by one, duplicating the current -%% matrix. That is, after a ``gl:pushMatrix'' call, the matrix on top of the stack is identical -%% to the one below it. -%% -%% {@link gl:pushMatrix/0} pops the current matrix stack, replacing the current matrix with -%% the one below it on the stack. -%% -%% Initially, each of the stacks contains one matrix, an identity matrix. -%% -%% It is an error to push a full matrix stack or to pop a matrix stack that contains only -%% a single matrix. In either case, the error flag is set and no other change is made to -%% GL state. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPushMatrix.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPushMatrix.xml">external</a> documentation. -spec pushMatrix() -> 'ok'. pushMatrix() -> cast(5089, <<>>). @@ -2624,11 +937,7 @@ popMatrix() -> %% ``gl:loadIdentity'' replaces the current matrix with the identity matrix. It is semantically %% equivalent to calling {@link gl:loadMatrixd/1} with the identity matrix %% -%% ((1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1)) -%% -%% but in some cases it is more efficient. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadIdentity.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLoadIdentity.xml">external</a> documentation. -spec loadIdentity() -> 'ok'. loadIdentity() -> cast(5091, <<>>). @@ -2639,16 +948,7 @@ loadIdentity() -> %% by `M' . The current matrix is the projection matrix, modelview matrix, or texture %% matrix, depending on the current matrix mode (see {@link gl:matrixMode/1} ). %% -%% The current matrix, M, defines a transformation of coordinates. For instance, assume -%% M refers to the modelview matrix. If v=(v[0] v[1] v[2] v[3]) is the set of object coordinates of a vertex, -%% and `M' points to an array of 16 single- or double-precision floating-point values -%% m={m[0] m[1] ... m[15]}, then the modelview transformation M(v) does the following: -%% -%% M(v)=(m[0] m[4] m[8] m[12] m[1] m[5] m[9] m[13] m[2] m[6] m[10] m[14] m[3] m[7] m[11] m[15])×(v[0] v[1] v[2] v[3]) -%% -%% Projection and texture transformations are similarly defined. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadMatrix.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLoadMatrix.xml">external</a> documentation. -spec loadMatrixd(M) -> 'ok' when M :: matrix(). loadMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) -> cast(5092, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble>>); @@ -2668,10 +968,7 @@ loadMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) -> %% ``gl:multMatrix'' multiplies the current matrix with the one specified using `M' , %% and replaces the current matrix with the product. %% -%% The current matrix is determined by the current matrix mode (see {@link gl:matrixMode/1} ). -%% It is either the projection matrix, modelview matrix, or the texture matrix. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultMatrix.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glMultMatrix.xml">external</a> documentation. -spec multMatrixd(M) -> 'ok' when M :: matrix(). multMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) -> cast(5094, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble>>); @@ -2693,16 +990,7 @@ multMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) -> %% replacing the current matrix, as if {@link gl:multMatrixd/1} were called with the following %% matrix as its argument: %% -%% (x 2(1-c)+c x y(1-c)-z s x z(1-c)+y s 0 y x(1-c)+z s y 2(1-c)+c y z(1-c)-x s 0 x z(1-c)-y s y z(1-c)+x s z 2(1-c)+c 0 0 0 0 -%% 1) -%% -%% Where c=cos(angle), s=sin(angle), and ||(x y z)||=1 (if not, the GL will normalize this vector). -%% -%% If the matrix mode is either `?GL_MODELVIEW' or `?GL_PROJECTION', all objects -%% drawn after ``gl:rotate'' is called are rotated. Use {@link gl:pushMatrix/0} and {@link gl:pushMatrix/0} -%% to save and restore the unrotated coordinate system. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRotate.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glRotate.xml">external</a> documentation. -spec rotated(Angle, X, Y, Z) -> 'ok' when Angle :: float(),X :: float(),Y :: float(),Z :: float(). rotated(Angle,X,Y,Z) -> cast(5096, <<Angle:?GLdouble,X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>). @@ -2719,19 +1007,7 @@ rotatef(Angle,X,Y,Z) -> %% axes. The three parameters indicate the desired scale factor along each of the three axes. %% %% -%% The current matrix (see {@link gl:matrixMode/1} ) is multiplied by this scale matrix, and -%% the product replaces the current matrix as if {@link gl:multMatrixd/1} were called with -%% the following matrix as its argument: -%% -%% (x 0 0 0 0 y 0 0 0 0 z 0 0 0 0 1) -%% -%% If the matrix mode is either `?GL_MODELVIEW' or `?GL_PROJECTION', all objects -%% drawn after ``gl:scale'' is called are scaled. -%% -%% Use {@link gl:pushMatrix/0} and {@link gl:pushMatrix/0} to save and restore the unscaled -%% coordinate system. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScale.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glScale.xml">external</a> documentation. -spec scaled(X, Y, Z) -> 'ok' when X :: float(),Y :: float(),Z :: float(). scaled(X,Y,Z) -> cast(5098, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>). @@ -2748,15 +1024,7 @@ scalef(X,Y,Z) -> %% ) is multiplied by this translation matrix, with the product replacing the current matrix, %% as if {@link gl:multMatrixd/1} were called with the following matrix for its argument: %% -%% (1 0 0 x 0 1 0 y 0 0 1 z 0 0 0 1) -%% -%% If the matrix mode is either `?GL_MODELVIEW' or `?GL_PROJECTION', all objects -%% drawn after a call to ``gl:translate'' are translated. -%% -%% Use {@link gl:pushMatrix/0} and {@link gl:pushMatrix/0} to save and restore the untranslated -%% coordinate system. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTranslate.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTranslate.xml">external</a> documentation. -spec translated(X, Y, Z) -> 'ok' when X :: float(),Y :: float(),Z :: float(). translated(X,Y,Z) -> cast(5100, <<X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>). @@ -2772,10 +1040,7 @@ translatef(X,Y,Z) -> %% ``gl:isList'' returns `?GL_TRUE' if `List' is the name of a display list and %% returns `?GL_FALSE' if it is not, or if an error occurs. %% -%% A name returned by {@link gl:genLists/1} , but not yet associated with a display list by -%% calling {@link gl:newList/2} , is not the name of a display list. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsList.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glIsList.xml">external</a> documentation. -spec isList(List) -> 0|1 when List :: integer(). isList(List) -> call(5102, <<List:?GLuint>>). @@ -2787,11 +1052,7 @@ isList(List) -> %% display lists to delete. All display lists d with list<= d<= list+range-1 are %% deleted. %% -%% All storage locations allocated to the specified display lists are freed, and the names -%% are available for reuse at a later time. Names within the range that do not have an associated -%% display list are ignored. If `Range' is 0, nothing happens. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteLists.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glDeleteLists.xml">external</a> documentation. -spec deleteLists(List, Range) -> 'ok' when List :: integer(),Range :: integer(). deleteLists(List,Range) -> cast(5103, <<List:?GLuint,Range:?GLsizei>>). @@ -2804,7 +1065,7 @@ deleteLists(List,Range) -> %% available, or if any error is generated, no display lists are generated, and 0 is returned. %% %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenLists.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGenLists.xml">external</a> documentation. -spec genLists(Range) -> integer() when Range :: integer(). genLists(Range) -> call(5104, <<Range:?GLsizei>>). @@ -2815,53 +1076,14 @@ genLists(Range) -> %% Display lists are created with ``gl:newList''. All subsequent commands are placed in %% the display list, in the order issued, until {@link gl:endList/0} is called. %% -%% ``gl:newList'' has two arguments. The first argument, `List' , is a positive integer -%% that becomes the unique name for the display list. Names can be created and reserved with -%% {@link gl:genLists/1} and tested for uniqueness with {@link gl:isList/1} . The second argument, -%% `Mode' , is a symbolic constant that can assume one of two values: -%% -%% `?GL_COMPILE': Commands are merely compiled. -%% -%% `?GL_COMPILE_AND_EXECUTE': Commands are executed as they are compiled into the display -%% list. -%% -%% Certain commands are not compiled into the display list but are executed immediately, -%% regardless of the display-list mode. These commands are {@link gl:areTexturesResident/1} , {@link gl:colorPointer/4} -%% , {@link gl:deleteLists/2} , {@link gl:deleteTextures/1} , {@link gl:enableClientState/1} , {@link gl:edgeFlagPointer/2} -%% , {@link gl:enableClientState/1} , {@link gl:feedbackBuffer/3} , {@link gl:finish/0} , {@link gl:flush/0} -%% , {@link gl:genLists/1} , {@link gl:genTextures/1} , {@link gl:indexPointer/3} , {@link gl:interleavedArrays/3} -%% , {@link gl:isEnabled/1} , {@link gl:isList/1} , {@link gl:isTexture/1} , {@link gl:normalPointer/3} -%% , {@link gl:pushClientAttrib/1} , {@link gl:pixelStoref/2} , {@link gl:pushClientAttrib/1} , {@link gl:readPixels/7} -%% , {@link gl:renderMode/1} , {@link gl:selectBuffer/2} , {@link gl:texCoordPointer/4} , {@link gl:vertexPointer/4} -%% , and all of the {@link gl:getBooleanv/1} commands. -%% -%% Similarly, {@link gl:texImage1D/8} , {@link gl:texImage2D/9} , and {@link gl:texImage3D/10} -%% are executed immediately and not compiled into the display list when their first argument -%% is `?GL_PROXY_TEXTURE_1D', `?GL_PROXY_TEXTURE_1D', or `?GL_PROXY_TEXTURE_3D' -%% , respectively. -%% -%% When the ARB_imaging extension is supported, {@link gl:histogram/4} executes immediately -%% when its argument is `?GL_PROXY_HISTOGRAM'. Similarly, {@link gl:colorTable/6} executes -%% immediately when its first argument is `?GL_PROXY_COLOR_TABLE', `?GL_PROXY_POST_CONVOLUTION_COLOR_TABLE' -%% , or `?GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE'. -%% -%% For OpenGL versions 1.3 and greater, or when the ARB_multitexture extension is supported, -%% {@link gl:clientActiveTexture/1} is not compiled into display lists, but executed immediately. -%% -%% -%% When {@link gl:endList/0} is encountered, the display-list definition is completed by -%% associating the list with the unique name `List' (specified in the ``gl:newList'' -%% command). If a display list with name `List' already exists, it is replaced only -%% when {@link gl:endList/0} is called. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNewList.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glNewList.xml">external</a> documentation. -spec newList(List, Mode) -> 'ok' when List :: integer(),Mode :: enum(). newList(List,Mode) -> cast(5105, <<List:?GLuint,Mode:?GLenum>>). %% @doc glBeginList %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginList.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec endList() -> 'ok'. endList() -> cast(5106, <<>>). @@ -2873,17 +1095,7 @@ endList() -> %% list. If `List' has not been defined as a display list, ``gl:callList'' is ignored. %% %% -%% ``gl:callList'' can appear inside a display list. To avoid the possibility of infinite -%% recursion resulting from display lists calling one another, a limit is placed on the nesting -%% level of display lists during display-list execution. This limit is at least 64, and it -%% depends on the implementation. -%% -%% GL state is not saved and restored across a call to ``gl:callList''. Thus, changes -%% made to GL state during the execution of a display list remain after execution of the -%% display list is completed. Use {@link gl:pushAttrib/1} , {@link gl:pushAttrib/1} , {@link gl:pushMatrix/0} -%% , and {@link gl:pushMatrix/0} to preserve GL state across ``gl:callList'' calls. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCallList.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glCallList.xml">external</a> documentation. -spec callList(List) -> 'ok' when List :: integer(). callList(List) -> cast(5107, <<List:?GLuint>>). @@ -2895,62 +1107,7 @@ callList(List) -> %% just as if they were called without using a display list. Names of display lists that %% have not been defined are ignored. %% -%% ``gl:callLists'' provides an efficient means for executing more than one display list. `Type' -%% allows lists with various name formats to be accepted. The formats are as follows: -%% -%% `?GL_BYTE': `Lists' is treated as an array of signed bytes, each in the range -%% -128 through 127. -%% -%% `?GL_UNSIGNED_BYTE': `Lists' is treated as an array of unsigned bytes, each -%% in the range 0 through 255. -%% -%% `?GL_SHORT': `Lists' is treated as an array of signed two-byte integers, each -%% in the range -32768 through 32767. -%% -%% `?GL_UNSIGNED_SHORT': `Lists' is treated as an array of unsigned two-byte integers, -%% each in the range 0 through 65535. -%% -%% `?GL_INT': `Lists' is treated as an array of signed four-byte integers. -%% -%% `?GL_UNSIGNED_INT': `Lists' is treated as an array of unsigned four-byte integers. -%% -%% -%% `?GL_FLOAT': `Lists' is treated as an array of four-byte floating-point values. -%% -%% -%% `?GL_2_BYTES': `Lists' is treated as an array of unsigned bytes. Each pair of -%% bytes specifies a single display-list name. The value of the pair is computed as 256 times -%% the unsigned value of the first byte plus the unsigned value of the second byte. -%% -%% `?GL_3_BYTES': `Lists' is treated as an array of unsigned bytes. Each triplet -%% of bytes specifies a single display-list name. The value of the triplet is computed as -%% 65536 times the unsigned value of the first byte, plus 256 times the unsigned value of -%% the second byte, plus the unsigned value of the third byte. -%% -%% `?GL_4_BYTES': `Lists' is treated as an array of unsigned bytes. Each quadruplet -%% of bytes specifies a single display-list name. The value of the quadruplet is computed -%% as 16777216 times the unsigned value of the first byte, plus 65536 times the unsigned -%% value of the second byte, plus 256 times the unsigned value of the third byte, plus the -%% unsigned value of the fourth byte. -%% -%% The list of display-list names is not null-terminated. Rather, `N' specifies how -%% many names are to be taken from `Lists' . -%% -%% An additional level of indirection is made available with the {@link gl:listBase/1} command, -%% which specifies an unsigned offset that is added to each display-list name specified in `Lists' -%% before that display list is executed. -%% -%% ``gl:callLists'' can appear inside a display list. To avoid the possibility of infinite -%% recursion resulting from display lists calling one another, a limit is placed on the nesting -%% level of display lists during display-list execution. This limit must be at least 64, -%% and it depends on the implementation. -%% -%% GL state is not saved and restored across a call to ``gl:callLists''. Thus, changes -%% made to GL state during the execution of the display lists remain after execution is completed. -%% Use {@link gl:pushAttrib/1} , {@link gl:pushAttrib/1} , {@link gl:pushMatrix/0} , and {@link gl:pushMatrix/0} -%% to preserve GL state across ``gl:callLists'' calls. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCallLists.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glCallLists.xml">external</a> documentation. -spec callLists(Lists) -> 'ok' when Lists :: [integer()]. callLists(Lists) -> ListsLen = length(Lists), @@ -2965,7 +1122,7 @@ callLists(Lists) -> %% by adding `Base' to each offset. Names that reference valid display lists are executed; %% the others are ignored. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glListBase.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glListBase.xml">external</a> documentation. -spec listBase(Base) -> 'ok' when Base :: integer(). listBase(Base) -> cast(5109, <<Base:?GLuint>>). @@ -2977,66 +1134,7 @@ listBase(Base) -> %% ten ways the vertices are interpreted. Taking n as an integer count starting at one, %% and N as the total number of vertices specified, the interpretations are as follows: %% -%% `?GL_POINTS': Treats each vertex as a single point. Vertex n defines point n. -%% N points are drawn. -%% -%% `?GL_LINES': Treats each pair of vertices as an independent line segment. Vertices -%% 2 n-1 and 2 n define line n. N/2 lines are drawn. -%% -%% `?GL_LINE_STRIP': Draws a connected group of line segments from the first vertex -%% to the last. Vertices n and n+1 define line n. N-1 lines are drawn. -%% -%% `?GL_LINE_LOOP': Draws a connected group of line segments from the first vertex -%% to the last, then back to the first. Vertices n and n+1 define line n. The last -%% line, however, is defined by vertices N and 1. N lines are drawn. -%% -%% `?GL_TRIANGLES': Treats each triplet of vertices as an independent triangle. Vertices -%% 3 n-2, 3 n-1, and 3 n define triangle n. N/3 triangles are drawn. -%% -%% `?GL_TRIANGLE_STRIP': Draws a connected group of triangles. One triangle is defined -%% for each vertex presented after the first two vertices. For odd n, vertices n, n+1, -%% and n+2 define triangle n. For even n, vertices n+1, n, and n+2 define triangle -%% n. N-2 triangles are drawn. -%% -%% `?GL_TRIANGLE_FAN': Draws a connected group of triangles. One triangle is defined -%% for each vertex presented after the first two vertices. Vertices 1, n+1, and n+2 -%% define triangle n. N-2 triangles are drawn. -%% -%% `?GL_QUADS': Treats each group of four vertices as an independent quadrilateral. -%% Vertices 4 n-3, 4 n-2, 4 n-1, and 4 n define quadrilateral n. N/4 quadrilaterals -%% are drawn. -%% -%% `?GL_QUAD_STRIP': Draws a connected group of quadrilaterals. One quadrilateral is -%% defined for each pair of vertices presented after the first pair. Vertices 2 n-1, 2 -%% n, 2 n+2, and 2 n+1 define quadrilateral n. N/2-1 quadrilaterals are drawn. Note -%% that the order in which vertices are used to construct a quadrilateral from strip data -%% is different from that used with independent data. -%% -%% `?GL_POLYGON': Draws a single, convex polygon. Vertices 1 through N define this -%% polygon. -%% -%% Only a subset of GL commands can be used between ``gl:'begin''' and {@link gl:'begin'/1} . -%% The commands are {@link gl:vertex2d/2} , {@link gl:color3b/3} , {@link gl:secondaryColor3b/3} , {@link gl:indexd/1} -%% , {@link gl:normal3b/3} , {@link gl:fogCoordf/1} , {@link gl:texCoord1d/1} , {@link gl:multiTexCoord1d/2} -%% , {@link gl:vertexAttrib1d/2} , {@link gl:evalCoord1d/1} , {@link gl:evalPoint1/1} , {@link gl:arrayElement/1} -%% , {@link gl:materialf/3} , and {@link gl:edgeFlag/1} . Also, it is acceptable to use {@link gl:callList/1} -%% or {@link gl:callLists/1} to execute display lists that include only the preceding commands. -%% If any other GL command is executed between ``gl:'begin''' and {@link gl:'begin'/1} , the error -%% flag is set and the command is ignored. -%% -%% Regardless of the value chosen for `Mode' , there is no limit to the number of vertices -%% that can be defined between ``gl:'begin''' and {@link gl:'begin'/1} . Lines, triangles, quadrilaterals, -%% and polygons that are incompletely specified are not drawn. Incomplete specification results -%% when either too few vertices are provided to specify even a single primitive or when an -%% incorrect multiple of vertices is specified. The incomplete primitive is ignored; the -%% rest are drawn. -%% -%% The minimum specification of vertices for each primitive is as follows: 1 for a point, -%% 2 for a line, 3 for a triangle, 4 for a quadrilateral, and 3 for a polygon. Modes that -%% require a certain multiple of vertices are `?GL_LINES' (2), `?GL_TRIANGLES' -%% (3), `?GL_QUADS' (4), and `?GL_QUAD_STRIP' (2). -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBegin.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glBegin.xml">external</a> documentation. -spec 'begin'(Mode) -> 'ok' when Mode :: enum(). 'begin'(Mode) -> cast(5110, <<Mode:?GLenum>>). @@ -3053,10 +1151,7 @@ listBase(Base) -> %% point, line, and polygon vertices. The current color, normal, texture coordinates, and %% fog coordinate are associated with the vertex when ``gl:vertex'' is called. %% -%% When only x and y are specified, z defaults to 0 and w defaults to 1. When x, -%% y, and z are specified, w defaults to 1. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glVertex.xml">external</a> documentation. -spec vertex2d(X, Y) -> 'ok' when X :: float(),Y :: float(). vertex2d(X,Y) -> cast(5112, <<X:?GLdouble,Y:?GLdouble>>). @@ -3182,16 +1277,7 @@ vertex4sv({X,Y,Z,W}) -> vertex4s(X,Y,Z,W). %% mapping that maps the most positive representable integer value to 1.0 and the most negative %% representable integer value to -1.0. %% -%% Normals specified with ``gl:normal'' need not have unit length. If `?GL_NORMALIZE' -%% is enabled, then normals of any length specified with ``gl:normal'' are normalized after -%% transformation. If `?GL_RESCALE_NORMAL' is enabled, normals are scaled by a scaling -%% factor derived from the modelview matrix. `?GL_RESCALE_NORMAL' requires that the -%% originally specified normals were of unit length, and that the modelview matrix contain -%% only uniform scales for proper results. To enable and disable normalization, call {@link gl:enable/1} -%% and {@link gl:enable/1} with either `?GL_NORMALIZE' or `?GL_RESCALE_NORMAL'. -%% Normalization is initially disabled. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glNormal.xml">external</a> documentation. -spec normal3b(Nx, Ny, Nz) -> 'ok' when Nx :: integer(),Ny :: integer(),Nz :: integer(). normal3b(Nx,Ny,Nz) -> cast(5124, <<Nx:?GLbyte,Ny:?GLbyte,Nz:?GLbyte>>). @@ -3245,15 +1331,7 @@ normal3sv({Nx,Ny,Nz}) -> normal3s(Nx,Ny,Nz). %% ``gl:index'' updates the current (single-valued) color index. It takes one argument, %% the new value for the current color index. %% -%% The current index is stored as a floating-point value. Integer values are converted directly -%% to floating-point values, with no special mapping. The initial value is 1. -%% -%% Index values outside the representable range of the color index buffer are not clamped. -%% However, before an index is dithered (if enabled) and written to the frame buffer, it -%% is converted to fixed-point format. Any bits in the integer portion of the resulting fixed-point -%% value that do not correspond to bits in the frame buffer are masked out. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIndex.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glIndex.xml">external</a> documentation. -spec indexd(C) -> 'ok' when C :: float(). indexd(C) -> cast(5129, <<C:?GLdouble>>). @@ -3310,24 +1388,7 @@ indexubv({C}) -> indexub(C). %% green, and blue values explicitly and set the current alpha value to 1.0 (full intensity) %% implicitly. ``gl:color4'' variants specify all four color components explicitly. %% -%% ``gl:color3b'', ``gl:color4b'', ``gl:color3s'', ``gl:color4s'', ``gl:color3i'', -%% and ``gl:color4i'' take three or four signed byte, short, or long integers as arguments. -%% When `v' is appended to the name, the color commands can take a pointer to an array -%% of such values. -%% -%% Current color values are stored in floating-point format, with unspecified mantissa and -%% exponent sizes. Unsigned integer color components, when specified, are linearly mapped -%% to floating-point values such that the largest representable value maps to 1.0 (full intensity), -%% and 0 maps to 0.0 (zero intensity). Signed integer color components, when specified, are -%% linearly mapped to floating-point values such that the most positive representable value -%% maps to 1.0, and the most negative representable value maps to -1.0. (Note that this -%% mapping does not convert 0 precisely to 0.0.) Floating-point values are mapped directly. -%% -%% Neither floating-point nor signed integer values are clamped to the range [0 1] before the -%% current color is updated. However, color components are clamped to this range before they -%% are interpolated or written into a color buffer. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColor.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glColor.xml">external</a> documentation. -spec color3b(Red, Green, Blue) -> 'ok' when Red :: integer(),Green :: integer(),Blue :: integer(). color3b(Red,Green,Blue) -> cast(5134, <<Red:?GLbyte,Green:?GLbyte,Blue:?GLbyte>>). @@ -3494,13 +1555,7 @@ color4usv({Red,Green,Blue,Alpha}) -> color4us(Red,Green,Blue,Alpha). %% Similarly, ``gl:texCoord3'' specifies the texture coordinates as (s t r 1), and ``gl:texCoord4'' %% defines all four components explicitly as (s t r q). %% -%% The current texture coordinates are part of the data that is associated with each vertex -%% and with the current raster position. Initially, the values for `s', `t', `r' -%% , and `q' are (0, 0, 0, 1). -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoord.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTexCoord.xml">external</a> documentation. -spec texCoord1d(S) -> 'ok' when S :: float(). texCoord1d(S) -> cast(5150, <<S:?GLdouble>>). @@ -3666,41 +1721,7 @@ texCoord4sv({S,T,R,Q}) -> texCoord4s(S,T,R,Q). %% subpixel accuracy. See {@link gl:bitmap/7} , {@link gl:drawPixels/5} , and {@link gl:copyPixels/5} %% . %% -%% The current raster position consists of three window coordinates ( x, y, z), a clip -%% coordinate value ( w), an eye coordinate distance, a valid bit, and associated color -%% data and texture coordinates. The w coordinate is a clip coordinate, because w is -%% not projected to window coordinates. ``gl:rasterPos4'' specifies object coordinates x, -%% y, z, and w explicitly. ``gl:rasterPos3'' specifies object coordinate x, y, and -%% z explicitly, while w is implicitly set to 1. ``gl:rasterPos2'' uses the argument -%% values for x and y while implicitly setting z and w to 0 and 1. -%% -%% The object coordinates presented by ``gl:rasterPos'' are treated just like those of a {@link gl:vertex2d/2} -%% command: They are transformed by the current modelview and projection matrices and passed -%% to the clipping stage. If the vertex is not culled, then it is projected and scaled to -%% window coordinates, which become the new current raster position, and the `?GL_CURRENT_RASTER_POSITION_VALID' -%% flag is set. If the vertex `is' culled, then the valid bit is cleared and the current -%% raster position and associated color and texture coordinates are undefined. -%% -%% The current raster position also includes some associated color data and texture coordinates. -%% If lighting is enabled, then `?GL_CURRENT_RASTER_COLOR' (in RGBA mode) or `?GL_CURRENT_RASTER_INDEX' -%% (in color index mode) is set to the color produced by the lighting calculation (see {@link gl:lightf/3} -%% , {@link gl:lightModelf/2} , and {@link gl:shadeModel/1} ). If lighting is disabled, current -%% color (in RGBA mode, state variable `?GL_CURRENT_COLOR') or color index (in color -%% index mode, state variable `?GL_CURRENT_INDEX') is used to update the current raster -%% color. `?GL_CURRENT_RASTER_SECONDARY_COLOR' (in RGBA mode) is likewise updated. -%% -%% Likewise, `?GL_CURRENT_RASTER_TEXTURE_COORDS' is updated as a function of `?GL_CURRENT_TEXTURE_COORDS' -%% , based on the texture matrix and the texture generation functions (see {@link gl:texGend/3} ). -%% Finally, the distance from the origin of the eye coordinate system to the vertex as transformed -%% by only the modelview matrix replaces `?GL_CURRENT_RASTER_DISTANCE'. -%% -%% Initially, the current raster position is (0, 0, 0, 1), the current raster distance is -%% 0, the valid bit is set, the associated RGBA color is (1, 1, 1, 1), the associated color -%% index is 1, and the associated texture coordinates are (0, 0, 0, 1). In RGBA mode, `?GL_CURRENT_RASTER_INDEX' -%% is always 1; in color index mode, the current raster RGBA color always maintains its -%% initial value. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glRasterPos.xml">external</a> documentation. -spec rasterPos2d(X, Y) -> 'ok' when X :: float(),Y :: float(). rasterPos2d(X,Y) -> cast(5166, <<X:?GLdouble,Y:?GLdouble>>). @@ -3826,13 +1847,7 @@ rasterPos4sv({X,Y,Z,W}) -> rasterPos4s(X,Y,Z,W). %% coordinates or as two pointers to arrays, each containing an (x y) pair. The resulting rectangle %% is defined in the z=0 plane. %% -%% ``gl:rect''( `X1' , `Y1' , `X2' , `Y2' ) is exactly equivalent to the -%% following sequence: glBegin(`?GL_POLYGON'); glVertex2( `X1' , `Y1' ); glVertex2( -%% `X2' , `Y1' ); glVertex2( `X2' , `Y2' ); glVertex2( `X1' , `Y2' ); -%% glEnd(); Note that if the second vertex is above and to the right of the first vertex, -%% the rectangle is constructed with a counterclockwise winding. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRect.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glRect.xml">external</a> documentation. -spec rectd(X1, Y1, X2, Y2) -> 'ok' when X1 :: float(),Y1 :: float(),X2 :: float(),Y2 :: float(). rectd(X1,Y1,X2,Y2) -> cast(5178, <<X1:?GLdouble,Y1:?GLdouble,X2:?GLdouble,Y2:?GLdouble>>). @@ -3888,21 +1903,7 @@ rectsv({V1,V2},{V1,V2}) -> %% to be packed into a single array or stored in separate arrays. (Single-array storage may %% be more efficient on some implementations; see {@link gl:interleavedArrays/3} .) %% -%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2} -%% ) while a vertex array is specified, `Pointer' is treated as a byte offset into the -%% buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING' -%% ) is saved as vertex array client-side state (`?GL_VERTEX_ARRAY_BUFFER_BINDING'). -%% -%% When a vertex array is specified, `Size' , `Type' , `Stride' , and `Pointer' -%% are saved as client-side state, in addition to the current vertex array buffer object -%% binding. -%% -%% To enable and disable the vertex array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1} -%% with the argument `?GL_VERTEX_ARRAY'. If enabled, the vertex array is used when {@link gl:arrayElement/1} -%% , {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements' -%% , or {@link gl:drawRangeElements/6} is called. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexPointer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glVertexPointer.xml">external</a> documentation. -spec vertexPointer(Size, Type, Stride, Ptr) -> 'ok' when Size :: integer(),Type :: enum(),Stride :: integer(),Ptr :: offset()|mem(). vertexPointer(Size,Type,Stride,Ptr) when is_integer(Ptr) -> cast(5186, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei,Ptr:?GLuint>>); @@ -3918,22 +1919,7 @@ vertexPointer(Size,Type,Stride,Ptr) -> %% to be packed into a single array or stored in separate arrays. (Single-array storage may %% be more efficient on some implementations; see {@link gl:interleavedArrays/3} .) %% -%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2} -%% ) while a normal array is specified, `Pointer' is treated as a byte offset into the -%% buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING' -%% ) is saved as normal vertex array client-side state (`?GL_NORMAL_ARRAY_BUFFER_BINDING' -%% ). -%% -%% When a normal array is specified, `Type' , `Stride' , and `Pointer' are -%% saved as client-side state, in addition to the current vertex array buffer object binding. -%% -%% -%% To enable and disable the normal array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1} -%% with the argument `?GL_NORMAL_ARRAY'. If enabled, the normal array is used when {@link gl:drawArrays/3} -%% , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements', {@link gl:drawRangeElements/6} -%% , or {@link gl:arrayElement/1} is called. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNormalPointer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glNormalPointer.xml">external</a> documentation. -spec normalPointer(Type, Stride, Ptr) -> 'ok' when Type :: enum(),Stride :: integer(),Ptr :: offset()|mem(). normalPointer(Type,Stride,Ptr) when is_integer(Ptr) -> cast(5188, <<Type:?GLenum,Stride:?GLsizei,Ptr:?GLuint>>); @@ -3950,22 +1936,7 @@ normalPointer(Type,Stride,Ptr) -> %% to be packed into a single array or stored in separate arrays. (Single-array storage may %% be more efficient on some implementations; see {@link gl:interleavedArrays/3} .) %% -%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2} -%% ) while a color array is specified, `Pointer' is treated as a byte offset into the -%% buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING' -%% ) is saved as color vertex array client-side state (`?GL_COLOR_ARRAY_BUFFER_BINDING'). -%% -%% -%% When a color array is specified, `Size' , `Type' , `Stride' , and `Pointer' -%% are saved as client-side state, in addition to the current vertex array buffer object -%% binding. -%% -%% To enable and disable the color array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1} -%% with the argument `?GL_COLOR_ARRAY'. If enabled, the color array is used when {@link gl:drawArrays/3} -%% , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements', {@link gl:drawRangeElements/6} -%% , or {@link gl:arrayElement/1} is called. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorPointer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glColorPointer.xml">external</a> documentation. -spec colorPointer(Size, Type, Stride, Ptr) -> 'ok' when Size :: integer(),Type :: enum(),Stride :: integer(),Ptr :: offset()|mem(). colorPointer(Size,Type,Stride,Ptr) when is_integer(Ptr) -> cast(5190, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei,Ptr:?GLuint>>); @@ -3980,22 +1951,7 @@ colorPointer(Size,Type,Stride,Ptr) -> %% specifies the byte stride from one color index to the next, allowing vertices and attributes %% to be packed into a single array or stored in separate arrays. %% -%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2} -%% ) while a color index array is specified, `Pointer' is treated as a byte offset into -%% the buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING' -%% ) is saved as color index vertex array client-side state (`?GL_INDEX_ARRAY_BUFFER_BINDING' -%% ). -%% -%% When a color index array is specified, `Type' , `Stride' , and `Pointer' -%% are saved as client-side state, in addition to the current vertex array buffer object -%% binding. -%% -%% To enable and disable the color index array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1} -%% with the argument `?GL_INDEX_ARRAY'. If enabled, the color index array is used when -%% {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements' -%% , {@link gl:drawRangeElements/6} , or {@link gl:arrayElement/1} is called. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIndexPointer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glIndexPointer.xml">external</a> documentation. -spec indexPointer(Type, Stride, Ptr) -> 'ok' when Type :: enum(),Stride :: integer(),Ptr :: offset()|mem(). indexPointer(Type,Stride,Ptr) when is_integer(Ptr) -> cast(5192, <<Type:?GLenum,Stride:?GLsizei,Ptr:?GLuint>>); @@ -4013,23 +1969,7 @@ indexPointer(Type,Stride,Ptr) -> %% array or stored in separate arrays. (Single-array storage may be more efficient on some %% implementations; see {@link gl:interleavedArrays/3} .) %% -%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2} -%% ) while a texture coordinate array is specified, `Pointer' is treated as a byte offset -%% into the buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING' -%% ) is saved as texture coordinate vertex array client-side state (`?GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING' -%% ). -%% -%% When a texture coordinate array is specified, `Size' , `Type' , `Stride' , -%% and `Pointer' are saved as client-side state, in addition to the current vertex array -%% buffer object binding. -%% -%% To enable and disable a texture coordinate array, call {@link gl:enableClientState/1} -%% and {@link gl:enableClientState/1} with the argument `?GL_TEXTURE_COORD_ARRAY'. If -%% enabled, the texture coordinate array is used when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} -%% , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements', -%% or {@link gl:drawRangeElements/6} is called. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexCoordPointer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTexCoordPointer.xml">external</a> documentation. -spec texCoordPointer(Size, Type, Stride, Ptr) -> 'ok' when Size :: integer(),Type :: enum(),Stride :: integer(),Ptr :: offset()|mem(). texCoordPointer(Size,Type,Stride,Ptr) when is_integer(Ptr) -> cast(5194, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei,Ptr:?GLuint>>); @@ -4044,21 +1984,7 @@ texCoordPointer(Size,Type,Stride,Ptr) -> %% flag to the next, allowing vertices and attributes to be packed into a single array or %% stored in separate arrays. %% -%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2} -%% ) while an edge flag array is specified, `Pointer' is treated as a byte offset into -%% the buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING' -%% ) is saved as edge flag vertex array client-side state (`?GL_EDGE_FLAG_ARRAY_BUFFER_BINDING' -%% ). -%% -%% When an edge flag array is specified, `Stride' and `Pointer' are saved as client-side -%% state, in addition to the current vertex array buffer object binding. -%% -%% To enable and disable the edge flag array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1} -%% with the argument `?GL_EDGE_FLAG_ARRAY'. If enabled, the edge flag array is used -%% when {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements' -%% , {@link gl:drawRangeElements/6} , or {@link gl:arrayElement/1} is called. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEdgeFlagPointer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glEdgeFlagPointer.xml">external</a> documentation. -spec edgeFlagPointer(Stride, Ptr) -> 'ok' when Stride :: integer(),Ptr :: offset()|mem(). edgeFlagPointer(Stride,Ptr) when is_integer(Ptr) -> cast(5196, <<Stride:?GLsizei,Ptr:?GLuint>>); @@ -4075,18 +2001,7 @@ edgeFlagPointer(Stride,Ptr) -> %% is not enabled, no drawing occurs but the attributes corresponding to the enabled arrays %% are modified. %% -%% Use ``gl:arrayElement'' to construct primitives by indexing vertex data, rather than -%% by streaming through arrays of data in first-to-last order. Because each call specifies -%% only a single vertex, it is possible to explicitly specify per-primitive attributes such -%% as a single normal for each triangle. -%% -%% Changes made to array data between the execution of {@link gl:'begin'/1} and the corresponding -%% execution of {@link gl:'begin'/1} may affect calls to ``gl:arrayElement'' that are made within -%% the same {@link gl:'begin'/1} / {@link gl:'begin'/1} period in nonsequential ways. That is, a call -%% to ``gl:arrayElement'' that precedes a change to array data may access the changed data, -%% and a call that follows a change to array data may access original data. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glArrayElement.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glArrayElement.xml">external</a> documentation. -spec arrayElement(I) -> 'ok' when I :: integer(). arrayElement(I) -> cast(5198, <<I:?GLint>>). @@ -4099,15 +2014,7 @@ arrayElement(I) -> %% and use them to construct a sequence of primitives with a single call to ``gl:drawArrays'' %% . %% -%% When ``gl:drawArrays'' is called, it uses `Count' sequential elements from each -%% enabled array to construct a sequence of geometric primitives, beginning with element `First' -%% . `Mode' specifies what kind of primitives are constructed and how the array elements -%% construct those primitives. -%% -%% Vertex attributes that are modified by ``gl:drawArrays'' have an unspecified value -%% after ``gl:drawArrays'' returns. Attributes that aren't modified remain well defined. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawArrays.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawArrays.xhtml">external</a> documentation. -spec drawArrays(Mode, First, Count) -> 'ok' when Mode :: enum(),First :: integer(),Count :: integer(). drawArrays(Mode,First,Count) -> cast(5199, <<Mode:?GLenum,First:?GLint,Count:?GLsizei>>). @@ -4120,16 +2027,7 @@ drawArrays(Mode,First,Count) -> %% and so on, and use them to construct a sequence of primitives with a single call to ``gl:drawElements'' %% . %% -%% When ``gl:drawElements'' is called, it uses `Count' sequential elements from an -%% enabled array, starting at `Indices' to construct a sequence of geometric primitives. -%% `Mode' specifies what kind of primitives are constructed and how the array elements -%% construct these primitives. If more than one array is enabled, each is used. -%% -%% Vertex attributes that are modified by ``gl:drawElements'' have an unspecified value -%% after ``gl:drawElements'' returns. Attributes that aren't modified maintain their previous -%% values. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElements.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElements.xhtml">external</a> documentation. -spec drawElements(Mode, Count, Type, Indices) -> 'ok' when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(). drawElements(Mode,Count,Type,Indices) when is_integer(Indices) -> cast(5200, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint>>); @@ -4143,21 +2041,7 @@ drawElements(Mode,Count,Type,Indices) -> %% and vertex arrays whose elements are part of a larger aggregate array element. For some %% implementations, this is more efficient than specifying the arrays separately. %% -%% If `Stride' is 0, the aggregate elements are stored consecutively. Otherwise, `Stride' -%% bytes occur between the beginning of one aggregate array element and the beginning of -%% the next aggregate array element. -%% -%% `Format' serves as a ``key'' describing the extraction of individual arrays from -%% the aggregate array. If `Format' contains a T, then texture coordinates are extracted -%% from the interleaved array. If C is present, color values are extracted. If N is present, -%% normal coordinates are extracted. Vertex coordinates are always extracted. -%% -%% The digits 2, 3, and 4 denote how many values are extracted. F indicates that values -%% are extracted as floating-point values. Colors may also be extracted as 4 unsigned bytes -%% if 4UB follows the C. If a color is extracted as 4 unsigned bytes, the vertex array element -%% which follows is located at the first possible floating-point aligned address. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glInterleavedArrays.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glInterleavedArrays.xml">external</a> documentation. -spec interleavedArrays(Format, Stride, Pointer) -> 'ok' when Format :: enum(),Stride :: integer(),Pointer :: offset()|mem(). interleavedArrays(Format,Stride,Pointer) when is_integer(Pointer) -> cast(5202, <<Format:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>); @@ -4175,23 +2059,7 @@ interleavedArrays(Format,Stride,Pointer) -> %% result of lighting if lighting is enabled, or it is the current color at the time the %% vertex was specified if lighting is disabled. %% -%% Flat and smooth shading are indistinguishable for points. Starting when {@link gl:'begin'/1} -%% is issued and counting vertices and primitives from 1, the GL gives each flat-shaded line -%% segment i the computed color of vertex i+1, its second vertex. Counting similarly -%% from 1, the GL gives each flat-shaded polygon the computed color of the vertex listed -%% in the following table. This is the last vertex to specify the polygon in all cases except -%% single polygons, where the first vertex specifies the flat-shaded color. -%% -%% <table><tbody><tr><td>` Primitive Type of Polygon ' i</td><td>` Vertex '</td></tr> -%% </tbody><tbody><tr><td> Single polygon ( i== 1) </td><td> 1 </td></tr><tr><td> Triangle -%% strip </td><td> i+2</td></tr><tr><td> Triangle fan </td><td> i+2</td></tr><tr><td> Independent -%% triangle </td><td> 3 i</td></tr><tr><td> Quad strip </td><td> 2 i+2</td></tr><tr><td> -%% Independent quad </td><td> 4 i</td></tr></tbody></table> -%% -%% Flat and smooth shading are specified by ``gl:shadeModel'' with `Mode' set to `?GL_FLAT' -%% and `?GL_SMOOTH', respectively. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShadeModel.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glShadeModel.xml">external</a> documentation. -spec shadeModel(Mode) -> 'ok' when Mode :: enum(). shadeModel(Mode) -> cast(5204, <<Mode:?GLenum>>). @@ -4204,88 +2072,7 @@ shadeModel(Mode) -> %% parameters, again by symbolic name. `Params' is either a single value or a pointer %% to an array that contains the new values. %% -%% To enable and disable lighting calculation, call {@link gl:enable/1} and {@link gl:enable/1} -%% with argument `?GL_LIGHTING'. Lighting is initially disabled. When it is enabled, -%% light sources that are enabled contribute to the lighting calculation. Light source i -%% is enabled and disabled using {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_LIGHT' -%% i. -%% -%% The ten light parameters are as follows: -%% -%% `?GL_AMBIENT': `Params' contains four integer or floating-point values that -%% specify the ambient RGBA intensity of the light. Integer values are mapped linearly such -%% that the most positive representable value maps to 1.0, and the most negative representable -%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point -%% values are clamped. The initial ambient light intensity is (0, 0, 0, 1). -%% -%% `?GL_DIFFUSE': `Params' contains four integer or floating-point values that -%% specify the diffuse RGBA intensity of the light. Integer values are mapped linearly such -%% that the most positive representable value maps to 1.0, and the most negative representable -%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point -%% values are clamped. The initial value for `?GL_LIGHT0' is (1, 1, 1, 1); for other -%% lights, the initial value is (0, 0, 0, 1). -%% -%% `?GL_SPECULAR': `Params' contains four integer or floating-point values that -%% specify the specular RGBA intensity of the light. Integer values are mapped linearly such -%% that the most positive representable value maps to 1.0, and the most negative representable -%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point -%% values are clamped. The initial value for `?GL_LIGHT0' is (1, 1, 1, 1); for other -%% lights, the initial value is (0, 0, 0, 1). -%% -%% `?GL_POSITION': `Params' contains four integer or floating-point values that -%% specify the position of the light in homogeneous object coordinates. Both integer and -%% floating-point values are mapped directly. Neither integer nor floating-point values are -%% clamped. -%% -%% The position is transformed by the modelview matrix when ``gl:light'' is called (just -%% as if it were a point), and it is stored in eye coordinates. If the w component of the -%% position is 0, the light is treated as a directional source. Diffuse and specular lighting -%% calculations take the light's direction, but not its actual position, into account, and -%% attenuation is disabled. Otherwise, diffuse and specular lighting calculations are based -%% on the actual location of the light in eye coordinates, and attenuation is enabled. The -%% initial position is (0, 0, 1, 0); thus, the initial light source is directional, parallel -%% to, and in the direction of the -z axis. -%% -%% `?GL_SPOT_DIRECTION': `Params' contains three integer or floating-point values -%% that specify the direction of the light in homogeneous object coordinates. Both integer -%% and floating-point values are mapped directly. Neither integer nor floating-point values -%% are clamped. -%% -%% The spot direction is transformed by the upper 3x3 of the modelview matrix when ``gl:light'' -%% is called, and it is stored in eye coordinates. It is significant only when `?GL_SPOT_CUTOFF' -%% is not 180, which it is initially. The initial direction is (0 0 -1). -%% -%% `?GL_SPOT_EXPONENT': `Params' is a single integer or floating-point value that -%% specifies the intensity distribution of the light. Integer and floating-point values are -%% mapped directly. Only values in the range [0 128] are accepted. -%% -%% Effective light intensity is attenuated by the cosine of the angle between the direction -%% of the light and the direction from the light to the vertex being lighted, raised to the -%% power of the spot exponent. Thus, higher spot exponents result in a more focused light -%% source, regardless of the spot cutoff angle (see `?GL_SPOT_CUTOFF', next paragraph). -%% The initial spot exponent is 0, resulting in uniform light distribution. -%% -%% `?GL_SPOT_CUTOFF': `Params' is a single integer or floating-point value that -%% specifies the maximum spread angle of a light source. Integer and floating-point values -%% are mapped directly. Only values in the range [0 90] and the special value 180 are accepted. -%% If the angle between the direction of the light and the direction from the light to the -%% vertex being lighted is greater than the spot cutoff angle, the light is completely masked. -%% Otherwise, its intensity is controlled by the spot exponent and the attenuation factors. -%% The initial spot cutoff is 180, resulting in uniform light distribution. -%% -%% `?GL_CONSTANT_ATTENUATION' -%% -%% `?GL_LINEAR_ATTENUATION' -%% -%% `?GL_QUADRATIC_ATTENUATION': `Params' is a single integer or floating-point -%% value that specifies one of the three light attenuation factors. Integer and floating-point -%% values are mapped directly. Only nonnegative values are accepted. If the light is positional, -%% rather than directional, its intensity is attenuated by the reciprocal of the sum of the -%% constant factor, the linear factor times the distance between the light and the vertex -%% being lighted, and the quadratic factor times the square of the same distance. The initial -%% attenuation factors are (1, 0, 0), resulting in no attenuation. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLight.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLight.xml">external</a> documentation. -spec lightf(Light, Pname, Param) -> 'ok' when Light :: enum(),Pname :: enum(),Param :: float(). lightf(Light,Pname,Param) -> cast(5205, <<Light:?GLenum,Pname:?GLenum,Param:?GLfloat>>). @@ -4318,73 +2105,7 @@ lightiv(Light,Pname,Params) -> %% implementation dependent constant that is greater than or equal to eight. `Pname' %% specifies one of ten light source parameters, again by symbolic name. %% -%% The following parameters are defined: -%% -%% `?GL_AMBIENT': `Params' returns four integer or floating-point values representing -%% the ambient intensity of the light source. Integer values, when requested, are linearly -%% mapped from the internal floating-point representation such that 1.0 maps to the most -%% positive representable integer value, and -1.0 maps to the most negative representable -%% integer value. If the internal value is outside the range [-1 1], the corresponding integer -%% return value is undefined. The initial value is (0, 0, 0, 1). -%% -%% `?GL_DIFFUSE': `Params' returns four integer or floating-point values representing -%% the diffuse intensity of the light source. Integer values, when requested, are linearly -%% mapped from the internal floating-point representation such that 1.0 maps to the most -%% positive representable integer value, and -1.0 maps to the most negative representable -%% integer value. If the internal value is outside the range [-1 1], the corresponding integer -%% return value is undefined. The initial value for `?GL_LIGHT0' is (1, 1, 1, 1); for -%% other lights, the initial value is (0, 0, 0, 0). -%% -%% `?GL_SPECULAR': `Params' returns four integer or floating-point values representing -%% the specular intensity of the light source. Integer values, when requested, are linearly -%% mapped from the internal floating-point representation such that 1.0 maps to the most -%% positive representable integer value, and -1.0 maps to the most negative representable -%% integer value. If the internal value is outside the range [-1 1], the corresponding integer -%% return value is undefined. The initial value for `?GL_LIGHT0' is (1, 1, 1, 1); for -%% other lights, the initial value is (0, 0, 0, 0). -%% -%% `?GL_POSITION': `Params' returns four integer or floating-point values representing -%% the position of the light source. Integer values, when requested, are computed by rounding -%% the internal floating-point values to the nearest integer value. The returned values are -%% those maintained in eye coordinates. They will not be equal to the values specified using -%% {@link gl:lightf/3} , unless the modelview matrix was identity at the time {@link gl:lightf/3} -%% was called. The initial value is (0, 0, 1, 0). -%% -%% `?GL_SPOT_DIRECTION': `Params' returns three integer or floating-point values -%% representing the direction of the light source. Integer values, when requested, are computed -%% by rounding the internal floating-point values to the nearest integer value. The returned -%% values are those maintained in eye coordinates. They will not be equal to the values specified -%% using {@link gl:lightf/3} , unless the modelview matrix was identity at the time {@link gl:lightf/3} -%% was called. Although spot direction is normalized before being used in the lighting equation, -%% the returned values are the transformed versions of the specified values prior to normalization. -%% The initial value is (0 0 -1). -%% -%% `?GL_SPOT_EXPONENT': `Params' returns a single integer or floating-point value -%% representing the spot exponent of the light. An integer value, when requested, is computed -%% by rounding the internal floating-point representation to the nearest integer. The initial -%% value is 0. -%% -%% `?GL_SPOT_CUTOFF': `Params' returns a single integer or floating-point value -%% representing the spot cutoff angle of the light. An integer value, when requested, is -%% computed by rounding the internal floating-point representation to the nearest integer. -%% The initial value is 180. -%% -%% `?GL_CONSTANT_ATTENUATION': `Params' returns a single integer or floating-point -%% value representing the constant (not distance-related) attenuation of the light. An integer -%% value, when requested, is computed by rounding the internal floating-point representation -%% to the nearest integer. The initial value is 1. -%% -%% `?GL_LINEAR_ATTENUATION': `Params' returns a single integer or floating-point -%% value representing the linear attenuation of the light. An integer value, when requested, -%% is computed by rounding the internal floating-point representation to the nearest integer. -%% The initial value is 0. -%% -%% `?GL_QUADRATIC_ATTENUATION': `Params' returns a single integer or floating-point -%% value representing the quadratic attenuation of the light. An integer value, when requested, -%% is computed by rounding the internal floating-point representation to the nearest integer. -%% The initial value is 0. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetLight.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetLight.xml">external</a> documentation. -spec getLightfv(Light, Pname) -> {float(),float(),float(),float()} when Light :: enum(),Pname :: enum(). getLightfv(Light,Pname) -> call(5209, <<Light:?GLenum,Pname:?GLenum>>). @@ -4400,63 +2121,7 @@ getLightiv(Light,Pname) -> %% ``gl:lightModel'' sets the lighting model parameter. `Pname' names a parameter %% and `Params' gives the new value. There are three lighting model parameters: %% -%% `?GL_LIGHT_MODEL_AMBIENT': `Params' contains four integer or floating-point -%% values that specify the ambient RGBA intensity of the entire scene. Integer values are -%% mapped linearly such that the most positive representable value maps to 1.0, and the most -%% negative representable value maps to -1.0. Floating-point values are mapped directly. -%% Neither integer nor floating-point values are clamped. The initial ambient scene intensity -%% is (0.2, 0.2, 0.2, 1.0). -%% -%% `?GL_LIGHT_MODEL_COLOR_CONTROL': `Params' must be either `?GL_SEPARATE_SPECULAR_COLOR' -%% or `?GL_SINGLE_COLOR'. `?GL_SINGLE_COLOR' specifies that a single color is -%% generated from the lighting computation for a vertex. `?GL_SEPARATE_SPECULAR_COLOR' -%% specifies that the specular color computation of lighting be stored separately from the -%% remainder of the lighting computation. The specular color is summed into the generated -%% fragment's color after the application of texture mapping (if enabled). The initial value -%% is `?GL_SINGLE_COLOR'. -%% -%% `?GL_LIGHT_MODEL_LOCAL_VIEWER': `Params' is a single integer or floating-point -%% value that specifies how specular reflection angles are computed. If `Params' is -%% 0 (or 0.0), specular reflection angles take the view direction to be parallel to and in -%% the direction of the -`z' axis, regardless of the location of the vertex in eye coordinates. -%% Otherwise, specular reflections are computed from the origin of the eye coordinate system. -%% The initial value is 0. -%% -%% `?GL_LIGHT_MODEL_TWO_SIDE': `Params' is a single integer or floating-point value -%% that specifies whether one- or two-sided lighting calculations are done for polygons. -%% It has no effect on the lighting calculations for points, lines, or bitmaps. If `Params' -%% is 0 (or 0.0), one-sided lighting is specified, and only the `front' material parameters -%% are used in the lighting equation. Otherwise, two-sided lighting is specified. In this -%% case, vertices of back-facing polygons are lighted using the `back' material parameters -%% and have their normals reversed before the lighting equation is evaluated. Vertices of -%% front-facing polygons are always lighted using the `front' material parameters, with -%% no change to their normals. The initial value is 0. -%% -%% In RGBA mode, the lighted color of a vertex is the sum of the material emission intensity, -%% the product of the material ambient reflectance and the lighting model full-scene ambient -%% intensity, and the contribution of each enabled light source. Each light source contributes -%% the sum of three terms: ambient, diffuse, and specular. The ambient light source contribution -%% is the product of the material ambient reflectance and the light's ambient intensity. -%% The diffuse light source contribution is the product of the material diffuse reflectance, -%% the light's diffuse intensity, and the dot product of the vertex's normal with the normalized -%% vector from the vertex to the light source. The specular light source contribution is -%% the product of the material specular reflectance, the light's specular intensity, and -%% the dot product of the normalized vertex-to-eye and vertex-to-light vectors, raised to -%% the power of the shininess of the material. All three light source contributions are attenuated -%% equally based on the distance from the vertex to the light source and on light source -%% direction, spread exponent, and spread cutoff angle. All dot products are replaced with -%% 0 if they evaluate to a negative value. -%% -%% The alpha component of the resulting lighted color is set to the alpha value of the material -%% diffuse reflectance. -%% -%% In color index mode, the value of the lighted index of a vertex ranges from the ambient -%% to the specular values passed to {@link gl:materialf/3} using `?GL_COLOR_INDEXES'. -%% Diffuse and specular coefficients, computed with a (.30, .59, .11) weighting of the lights' -%% colors, the shininess of the material, and the same reflection and attenuation equations -%% as in the RGBA case, determine how much above ambient the resulting index is. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLightModel.xml">external</a> documentation. -spec lightModelf(Pname, Param) -> 'ok' when Pname :: enum(),Param :: float(). lightModelf(Pname,Param) -> cast(5211, <<Pname:?GLenum,Param:?GLfloat>>). @@ -4490,60 +2155,7 @@ lightModeliv(Pname,Params) -> %% to shade back-facing polygons only when two-sided lighting is enabled. Refer to the {@link gl:lightModelf/2} %% reference page for details concerning one- and two-sided lighting calculations. %% -%% ``gl:material'' takes three arguments. The first, `Face' , specifies whether the `?GL_FRONT' -%% materials, the `?GL_BACK' materials, or both `?GL_FRONT_AND_BACK' materials -%% will be modified. The second, `Pname' , specifies which of several parameters in one -%% or both sets will be modified. The third, `Params' , specifies what value or values -%% will be assigned to the specified parameter. -%% -%% Material parameters are used in the lighting equation that is optionally applied to each -%% vertex. The equation is discussed in the {@link gl:lightModelf/2} reference page. The parameters -%% that can be specified using ``gl:material'', and their interpretations by the lighting -%% equation, are as follows: -%% -%% `?GL_AMBIENT': `Params' contains four integer or floating-point values that -%% specify the ambient RGBA reflectance of the material. Integer values are mapped linearly -%% such that the most positive representable value maps to 1.0, and the most negative representable -%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point -%% values are clamped. The initial ambient reflectance for both front- and back-facing materials -%% is (0.2, 0.2, 0.2, 1.0). -%% -%% `?GL_DIFFUSE': `Params' contains four integer or floating-point values that -%% specify the diffuse RGBA reflectance of the material. Integer values are mapped linearly -%% such that the most positive representable value maps to 1.0, and the most negative representable -%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point -%% values are clamped. The initial diffuse reflectance for both front- and back-facing materials -%% is (0.8, 0.8, 0.8, 1.0). -%% -%% `?GL_SPECULAR': `Params' contains four integer or floating-point values that -%% specify the specular RGBA reflectance of the material. Integer values are mapped linearly -%% such that the most positive representable value maps to 1.0, and the most negative representable -%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point -%% values are clamped. The initial specular reflectance for both front- and back-facing materials -%% is (0, 0, 0, 1). -%% -%% `?GL_EMISSION': `Params' contains four integer or floating-point values that -%% specify the RGBA emitted light intensity of the material. Integer values are mapped linearly -%% such that the most positive representable value maps to 1.0, and the most negative representable -%% value maps to -1.0. Floating-point values are mapped directly. Neither integer nor floating-point -%% values are clamped. The initial emission intensity for both front- and back-facing materials -%% is (0, 0, 0, 1). -%% -%% `?GL_SHININESS': `Params' is a single integer or floating-point value that specifies -%% the RGBA specular exponent of the material. Integer and floating-point values are mapped -%% directly. Only values in the range [0 128] are accepted. The initial specular exponent for both -%% front- and back-facing materials is 0. -%% -%% `?GL_AMBIENT_AND_DIFFUSE': Equivalent to calling ``gl:material'' twice with the -%% same parameter values, once with `?GL_AMBIENT' and once with `?GL_DIFFUSE'. -%% -%% `?GL_COLOR_INDEXES': `Params' contains three integer or floating-point values -%% specifying the color indices for ambient, diffuse, and specular lighting. These three -%% values, and `?GL_SHININESS', are the only material values used by the color index -%% mode lighting equation. Refer to the {@link gl:lightModelf/2} reference page for a discussion -%% of color index lighting. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMaterial.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glMaterial.xml">external</a> documentation. -spec materialf(Face, Pname, Param) -> 'ok' when Face :: enum(),Pname :: enum(),Param :: float(). materialf(Face,Pname,Param) -> cast(5215, <<Face:?GLenum,Pname:?GLenum,Param:?GLfloat>>). @@ -4573,46 +2185,7 @@ materialiv(Face,Pname,Params) -> %% ``gl:getMaterial'' returns in `Params' the value or values of parameter `Pname' %% of material `Face' . Six parameters are defined: %% -%% `?GL_AMBIENT': `Params' returns four integer or floating-point values representing -%% the ambient reflectance of the material. Integer values, when requested, are linearly -%% mapped from the internal floating-point representation such that 1.0 maps to the most -%% positive representable integer value, and -1.0 maps to the most negative representable -%% integer value. If the internal value is outside the range [-1 1], the corresponding integer -%% return value is undefined. The initial value is (0.2, 0.2, 0.2, 1.0) -%% -%% `?GL_DIFFUSE': `Params' returns four integer or floating-point values representing -%% the diffuse reflectance of the material. Integer values, when requested, are linearly -%% mapped from the internal floating-point representation such that 1.0 maps to the most -%% positive representable integer value, and -1.0 maps to the most negative representable -%% integer value. If the internal value is outside the range [-1 1], the corresponding integer -%% return value is undefined. The initial value is (0.8, 0.8, 0.8, 1.0). -%% -%% `?GL_SPECULAR': `Params' returns four integer or floating-point values representing -%% the specular reflectance of the material. Integer values, when requested, are linearly -%% mapped from the internal floating-point representation such that 1.0 maps to the most -%% positive representable integer value, and -1.0 maps to the most negative representable -%% integer value. If the internal value is outside the range [-1 1], the corresponding integer -%% return value is undefined. The initial value is (0, 0, 0, 1). -%% -%% `?GL_EMISSION': `Params' returns four integer or floating-point values representing -%% the emitted light intensity of the material. Integer values, when requested, are linearly -%% mapped from the internal floating-point representation such that 1.0 maps to the most -%% positive representable integer value, and -1.0 maps to the most negative representable -%% integer value. If the internal value is outside the range [-1 1], the corresponding integer -%% return value is undefined. The initial value is (0, 0, 0, 1). -%% -%% `?GL_SHININESS': `Params' returns one integer or floating-point value representing -%% the specular exponent of the material. Integer values, when requested, are computed by -%% rounding the internal floating-point value to the nearest integer value. The initial value -%% is 0. -%% -%% `?GL_COLOR_INDEXES': `Params' returns three integer or floating-point values -%% representing the ambient, diffuse, and specular indices of the material. These indices -%% are used only for color index lighting. (All the other parameters are used only for RGBA -%% lighting.) Integer values, when requested, are computed by rounding the internal floating-point -%% values to the nearest integer values. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMaterial.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetMaterial.xml">external</a> documentation. -spec getMaterialfv(Face, Pname) -> {float(),float(),float(),float()} when Face :: enum(),Pname :: enum(). getMaterialfv(Face,Pname) -> call(5219, <<Face:?GLenum,Pname:?GLenum>>). @@ -4629,11 +2202,7 @@ getMaterialiv(Face,Pname) -> %% is enabled, the material parameter or parameters specified by `Mode' , of the material %% or materials specified by `Face' , track the current color at all times. %% -%% To enable and disable `?GL_COLOR_MATERIAL', call {@link gl:enable/1} and {@link gl:enable/1} -%% with argument `?GL_COLOR_MATERIAL'. `?GL_COLOR_MATERIAL' is initially disabled. -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorMaterial.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glColorMaterial.xml">external</a> documentation. -spec colorMaterial(Face, Mode) -> 'ok' when Face :: enum(),Mode :: enum(). colorMaterial(Face,Mode) -> cast(5221, <<Face:?GLenum,Mode:?GLenum>>). @@ -4645,17 +2214,7 @@ colorMaterial(Face,Mode) -> %% position, and a given element is in the mth row and nth column of the pixel rectangle, %% then pixels whose centers are in the rectangle with corners at %% -%% ( xr+n. xfactor, yr+m. yfactor) -%% -%% ( xr+(n+1). xfactor, yr+(m+1). yfactor) -%% -%% are candidates for replacement. Any pixel whose center lies on the bottom or left edge -%% of this rectangular region is also modified. -%% -%% Pixel zoom factors are not limited to positive values. Negative zoom factors reflect -%% the resulting image about the current raster position. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelZoom.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPixelZoom.xml">external</a> documentation. -spec pixelZoom(Xfactor, Yfactor) -> 'ok' when Xfactor :: float(),Yfactor :: float(). pixelZoom(Xfactor,Yfactor) -> cast(5222, <<Xfactor:?GLfloat,Yfactor:?GLfloat>>). @@ -4669,181 +2228,7 @@ pixelZoom(Xfactor,Yfactor) -> %% , {@link gl:compressedTexSubImage1D/7} , {@link gl:compressedTexSubImage2D/9} or {@link gl:compressedTexSubImage1D/7} %% . %% -%% `Pname' is a symbolic constant indicating the parameter to be set, and `Param' -%% is the new value. Six of the twelve storage parameters affect how pixel data is returned -%% to client memory. They are as follows: -%% -%% `?GL_PACK_SWAP_BYTES': If true, byte ordering for multibyte color components, depth -%% components, or stencil indices is reversed. That is, if a four-byte component consists -%% of bytes b 0, b 1, b 2, b 3, it is stored in memory as b 3, b 2, b 1, b 0 if `?GL_PACK_SWAP_BYTES' -%% is true. `?GL_PACK_SWAP_BYTES' has no effect on the memory order of components within -%% a pixel, only on the order of bytes within components or indices. For example, the three -%% components of a `?GL_RGB' format pixel are always stored with red first, green second, -%% and blue third, regardless of the value of `?GL_PACK_SWAP_BYTES'. -%% -%% `?GL_PACK_LSB_FIRST': If true, bits are ordered within a byte from least significant -%% to most significant; otherwise, the first bit in each byte is the most significant one. -%% -%% `?GL_PACK_ROW_LENGTH': If greater than 0, `?GL_PACK_ROW_LENGTH' defines the -%% number of pixels in a row. If the first pixel of a row is placed at location p in memory, -%% then the location of the first pixel of the next row is obtained by skipping -%% -%% k={n l(a/s) |(s n l)/a| s>= a s< a) -%% -%% components or indices, where n is the number of components or indices in a pixel, l -%% is the number of pixels in a row (`?GL_PACK_ROW_LENGTH' if it is greater than 0, -%% the width argument to the pixel routine otherwise), a is the value of `?GL_PACK_ALIGNMENT' -%% , and s is the size, in bytes, of a single component (if a< s, then it is as if a= -%% s). In the case of 1-bit values, the location of the next row is obtained by skipping -%% -%% k=8 a |(n l)/(8 a)| -%% -%% components or indices. -%% -%% The word `component' in this description refers to the nonindex values red, green, -%% blue, alpha, and depth. Storage format `?GL_RGB', for example, has three components -%% per pixel: first red, then green, and finally blue. -%% -%% `?GL_PACK_IMAGE_HEIGHT': If greater than 0, `?GL_PACK_IMAGE_HEIGHT' defines -%% the number of pixels in an image three-dimensional texture volume, where ``image'' is -%% defined by all pixels sharing the same third dimension index. If the first pixel of a -%% row is placed at location p in memory, then the location of the first pixel of the next -%% row is obtained by skipping -%% -%% k={n l h(a/s) |(s n l h)/a| s>= a s< a) -%% -%% components or indices, where n is the number of components or indices in a pixel, l -%% is the number of pixels in a row (`?GL_PACK_ROW_LENGTH' if it is greater than 0, -%% the width argument to {@link gl:texImage3D/10} otherwise), h is the number of rows in -%% a pixel image (`?GL_PACK_IMAGE_HEIGHT' if it is greater than 0, the height argument -%% to the {@link gl:texImage3D/10} routine otherwise), a is the value of `?GL_PACK_ALIGNMENT' -%% , and s is the size, in bytes, of a single component (if a< s, then it is as if -%% a=s). -%% -%% The word `component' in this description refers to the nonindex values red, green, -%% blue, alpha, and depth. Storage format `?GL_RGB', for example, has three components -%% per pixel: first red, then green, and finally blue. -%% -%% `?GL_PACK_SKIP_PIXELS', `?GL_PACK_SKIP_ROWS', and `?GL_PACK_SKIP_IMAGES' -%% -%% These values are provided as a convenience to the programmer; they provide no functionality -%% that cannot be duplicated simply by incrementing the pointer passed to {@link gl:readPixels/7} -%% . Setting `?GL_PACK_SKIP_PIXELS' to i is equivalent to incrementing the pointer -%% by i n components or indices, where n is the number of components or indices in each -%% pixel. Setting `?GL_PACK_SKIP_ROWS' to j is equivalent to incrementing the pointer -%% by j m components or indices, where m is the number of components or indices per -%% row, as just computed in the `?GL_PACK_ROW_LENGTH' section. Setting `?GL_PACK_SKIP_IMAGES' -%% to k is equivalent to incrementing the pointer by k p, where p is the number of -%% components or indices per image, as computed in the `?GL_PACK_IMAGE_HEIGHT' section. -%% -%% -%% `?GL_PACK_ALIGNMENT': Specifies the alignment requirements for the start of each -%% pixel row in memory. The allowable values are 1 (byte-alignment), 2 (rows aligned to even-numbered -%% bytes), 4 (word-alignment), and 8 (rows start on double-word boundaries). -%% -%% The other six of the twelve storage parameters affect how pixel data is read from client -%% memory. These values are significant for {@link gl:texImage1D/8} , {@link gl:texImage2D/9} , {@link gl:texImage3D/10} -%% , {@link gl:texSubImage1D/7} , {@link gl:texSubImage1D/7} , and {@link gl:texSubImage1D/7} -%% -%% They are as follows: -%% -%% `?GL_UNPACK_SWAP_BYTES': If true, byte ordering for multibyte color components, -%% depth components, or stencil indices is reversed. That is, if a four-byte component consists -%% of bytes b 0, b 1, b 2, b 3, it is taken from memory as b 3, b 2, b 1, b 0 if `?GL_UNPACK_SWAP_BYTES' -%% is true. `?GL_UNPACK_SWAP_BYTES' has no effect on the memory order of components -%% within a pixel, only on the order of bytes within components or indices. For example, -%% the three components of a `?GL_RGB' format pixel are always stored with red first, -%% green second, and blue third, regardless of the value of `?GL_UNPACK_SWAP_BYTES'. -%% -%% `?GL_UNPACK_LSB_FIRST': If true, bits are ordered within a byte from least significant -%% to most significant; otherwise, the first bit in each byte is the most significant one. -%% -%% `?GL_UNPACK_ROW_LENGTH': If greater than 0, `?GL_UNPACK_ROW_LENGTH' defines -%% the number of pixels in a row. If the first pixel of a row is placed at location p in -%% memory, then the location of the first pixel of the next row is obtained by skipping -%% -%% k={n l(a/s) |(s n l)/a| s>= a s< a) -%% -%% components or indices, where n is the number of components or indices in a pixel, l -%% is the number of pixels in a row (`?GL_UNPACK_ROW_LENGTH' if it is greater than 0, -%% the width argument to the pixel routine otherwise), a is the value of `?GL_UNPACK_ALIGNMENT' -%% , and s is the size, in bytes, of a single component (if a< s, then it is as if a= -%% s). In the case of 1-bit values, the location of the next row is obtained by skipping -%% -%% k=8 a |(n l)/(8 a)| -%% -%% components or indices. -%% -%% The word `component' in this description refers to the nonindex values red, green, -%% blue, alpha, and depth. Storage format `?GL_RGB', for example, has three components -%% per pixel: first red, then green, and finally blue. -%% -%% `?GL_UNPACK_IMAGE_HEIGHT': If greater than 0, `?GL_UNPACK_IMAGE_HEIGHT' defines -%% the number of pixels in an image of a three-dimensional texture volume. Where ``image'' -%% is defined by all pixel sharing the same third dimension index. If the first pixel of -%% a row is placed at location p in memory, then the location of the first pixel of the -%% next row is obtained by skipping -%% -%% k={n l h(a/s) |(s n l h)/a| s>= a s< a) -%% -%% components or indices, where n is the number of components or indices in a pixel, l -%% is the number of pixels in a row (`?GL_UNPACK_ROW_LENGTH' if it is greater than 0, -%% the width argument to {@link gl:texImage3D/10} otherwise), h is the number of rows in -%% an image (`?GL_UNPACK_IMAGE_HEIGHT' if it is greater than 0, the height argument -%% to {@link gl:texImage3D/10} otherwise), a is the value of `?GL_UNPACK_ALIGNMENT', -%% and s is the size, in bytes, of a single component (if a< s, then it is as if a=s). -%% -%% -%% The word `component' in this description refers to the nonindex values red, green, -%% blue, alpha, and depth. Storage format `?GL_RGB', for example, has three components -%% per pixel: first red, then green, and finally blue. -%% -%% `?GL_UNPACK_SKIP_PIXELS' and `?GL_UNPACK_SKIP_ROWS' -%% -%% These values are provided as a convenience to the programmer; they provide no functionality -%% that cannot be duplicated by incrementing the pointer passed to {@link gl:texImage1D/8} , {@link gl:texImage2D/9} -%% , {@link gl:texSubImage1D/7} or {@link gl:texSubImage1D/7} . Setting `?GL_UNPACK_SKIP_PIXELS' -%% to i is equivalent to incrementing the pointer by i n components or indices, where -%% n is the number of components or indices in each pixel. Setting `?GL_UNPACK_SKIP_ROWS' -%% to j is equivalent to incrementing the pointer by j k components or indices, where -%% k is the number of components or indices per row, as just computed in the `?GL_UNPACK_ROW_LENGTH' -%% section. -%% -%% `?GL_UNPACK_ALIGNMENT': Specifies the alignment requirements for the start of each -%% pixel row in memory. The allowable values are 1 (byte-alignment), 2 (rows aligned to even-numbered -%% bytes), 4 (word-alignment), and 8 (rows start on double-word boundaries). -%% -%% The following table gives the type, initial value, and range of valid values for each -%% storage parameter that can be set with ``gl:pixelStore''. -%% -%% <table><tbody><tr><td> `Pname' </td><td>` Type '</td><td>` Initial Value '</td> -%% <td>` Valid Range '</td></tr></tbody><tbody><tr><td>`?GL_PACK_SWAP_BYTES'</td><td> -%% boolean </td><td> false </td><td> true or false </td></tr><tr><td>`?GL_PACK_LSB_FIRST' -%% </td><td> boolean </td><td> false </td><td> true or false </td></tr><tr><td>`?GL_PACK_ROW_LENGTH' -%% </td><td> integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_PACK_IMAGE_HEIGHT'</td> -%% <td> integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_PACK_SKIP_ROWS'</td><td> -%% integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_PACK_SKIP_PIXELS'</td><td> integer -%% </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_PACK_SKIP_IMAGES'</td><td> integer </td><td> -%% 0 </td><td>[0)</td></tr><tr><td>`?GL_PACK_ALIGNMENT'</td><td> integer </td><td> 4 </td> -%% <td> 1, 2, 4, or 8 </td></tr><tr><td>`?GL_UNPACK_SWAP_BYTES'</td><td> boolean </td><td> -%% false </td><td> true or false </td></tr><tr><td>`?GL_UNPACK_LSB_FIRST'</td><td> -%% boolean </td><td> false </td><td> true or false </td></tr><tr><td>`?GL_UNPACK_ROW_LENGTH' -%% </td><td> integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_UNPACK_IMAGE_HEIGHT'</td> -%% <td> integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_UNPACK_SKIP_ROWS'</td><td> -%% integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_UNPACK_SKIP_PIXELS'</td><td> -%% integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_UNPACK_SKIP_IMAGES'</td><td> -%% integer </td><td> 0 </td><td>[0)</td></tr><tr><td>`?GL_UNPACK_ALIGNMENT'</td><td> integer -%% </td><td> 4 </td><td> 1, 2, 4, or 8 </td></tr></tbody></table> -%% -%% ``gl:pixelStoref'' can be used to set any pixel store parameter. If the parameter type -%% is boolean, then if `Param' is 0, the parameter is false; otherwise it is set to -%% true. If `Pname' is a integer type parameter, `Param' is rounded to the nearest -%% integer. -%% -%% Likewise, ``gl:pixelStorei'' can also be used to set any of the pixel store parameters. -%% Boolean parameters are set to false if `Param' is 0 and true otherwise. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelStore.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPixelStore.xhtml">external</a> documentation. -spec pixelStoref(Pname, Param) -> 'ok' when Pname :: enum(),Param :: float(). pixelStoref(Pname,Param) -> cast(5223, <<Pname:?GLenum,Param:?GLfloat>>). @@ -4874,134 +2259,7 @@ pixelStorei(Pname,Param) -> %% ) control the unpacking of pixels being read from client memory and the packing of pixels %% being written back into client memory. %% -%% Pixel transfer operations handle four fundamental pixel types: `color', `color index' -%% , `depth', and `stencil'. `Color' pixels consist of four floating-point -%% values with unspecified mantissa and exponent sizes, scaled such that 0 represents zero -%% intensity and 1 represents full intensity. `Color indices' comprise a single fixed-point -%% value, with unspecified precision to the right of the binary point. `Depth' pixels -%% comprise a single floating-point value, with unspecified mantissa and exponent sizes, -%% scaled such that 0.0 represents the minimum depth buffer value, and 1.0 represents the -%% maximum depth buffer value. Finally, `stencil' pixels comprise a single fixed-point -%% value, with unspecified precision to the right of the binary point. -%% -%% The pixel transfer operations performed on the four basic pixel types are as follows: -%% -%% `Color': Each of the four color components is multiplied by a scale factor, then -%% added to a bias factor. That is, the red component is multiplied by `?GL_RED_SCALE', -%% then added to `?GL_RED_BIAS'; the green component is multiplied by `?GL_GREEN_SCALE' -%% , then added to `?GL_GREEN_BIAS'; the blue component is multiplied by `?GL_BLUE_SCALE' -%% , then added to `?GL_BLUE_BIAS'; and the alpha component is multiplied by `?GL_ALPHA_SCALE' -%% , then added to `?GL_ALPHA_BIAS'. After all four color components are scaled and -%% biased, each is clamped to the range [0 1]. All color, scale, and bias values are specified -%% with ``gl:pixelTransfer''. -%% -%% If `?GL_MAP_COLOR' is true, each color component is scaled by the size of the corresponding -%% color-to-color map, then replaced by the contents of that map indexed by the scaled component. -%% That is, the red component is scaled by `?GL_PIXEL_MAP_R_TO_R_SIZE', then replaced -%% by the contents of `?GL_PIXEL_MAP_R_TO_R' indexed by itself. The green component -%% is scaled by `?GL_PIXEL_MAP_G_TO_G_SIZE', then replaced by the contents of `?GL_PIXEL_MAP_G_TO_G' -%% indexed by itself. The blue component is scaled by `?GL_PIXEL_MAP_B_TO_B_SIZE', -%% then replaced by the contents of `?GL_PIXEL_MAP_B_TO_B' indexed by itself. And the -%% alpha component is scaled by `?GL_PIXEL_MAP_A_TO_A_SIZE', then replaced by the contents -%% of `?GL_PIXEL_MAP_A_TO_A' indexed by itself. All components taken from the maps are -%% then clamped to the range [0 1]. `?GL_MAP_COLOR' is specified with ``gl:pixelTransfer''. -%% The contents of the various maps are specified with {@link gl:pixelMapfv/3} . -%% -%% If the ARB_imaging extension is supported, each of the four color components may be scaled -%% and biased after transformation by the color matrix. That is, the red component is multiplied -%% by `?GL_POST_COLOR_MATRIX_RED_SCALE', then added to `?GL_POST_COLOR_MATRIX_RED_BIAS' -%% ; the green component is multiplied by `?GL_POST_COLOR_MATRIX_GREEN_SCALE', then -%% added to `?GL_POST_COLOR_MATRIX_GREEN_BIAS'; the blue component is multiplied by `?GL_POST_COLOR_MATRIX_BLUE_SCALE' -%% , then added to `?GL_POST_COLOR_MATRIX_BLUE_BIAS'; and the alpha component is multiplied -%% by `?GL_POST_COLOR_MATRIX_ALPHA_SCALE', then added to `?GL_POST_COLOR_MATRIX_ALPHA_BIAS' -%% . After all four color components are scaled and biased, each is clamped to the range [0 -%% 1]. -%% -%% Similarly, if the ARB_imaging extension is supported, each of the four color components -%% may be scaled and biased after processing by the enabled convolution filter. That is, -%% the red component is multiplied by `?GL_POST_CONVOLUTION_RED_SCALE', then added to `?GL_POST_CONVOLUTION_RED_BIAS' -%% ; the green component is multiplied by `?GL_POST_CONVOLUTION_GREEN_SCALE', then added -%% to `?GL_POST_CONVOLUTION_GREEN_BIAS'; the blue component is multiplied by `?GL_POST_CONVOLUTION_BLUE_SCALE' -%% , then added to `?GL_POST_CONVOLUTION_BLUE_BIAS'; and the alpha component is multiplied -%% by `?GL_POST_CONVOLUTION_ALPHA_SCALE', then added to `?GL_POST_CONVOLUTION_ALPHA_BIAS' -%% . After all four color components are scaled and biased, each is clamped to the range [0 -%% 1]. -%% -%% `Color index': Each color index is shifted left by `?GL_INDEX_SHIFT' bits; -%% any bits beyond the number of fraction bits carried by the fixed-point index are filled -%% with zeros. If `?GL_INDEX_SHIFT' is negative, the shift is to the right, again zero -%% filled. Then `?GL_INDEX_OFFSET' is added to the index. `?GL_INDEX_SHIFT' and `?GL_INDEX_OFFSET' -%% are specified with ``gl:pixelTransfer''. -%% -%% From this point, operation diverges depending on the required format of the resulting -%% pixels. If the resulting pixels are to be written to a color index buffer, or if they -%% are being read back to client memory in `?GL_COLOR_INDEX' format, the pixels continue -%% to be treated as indices. If `?GL_MAP_COLOR' is true, each index is masked by 2 n-1 -%% , where n is `?GL_PIXEL_MAP_I_TO_I_SIZE', then replaced by the contents of `?GL_PIXEL_MAP_I_TO_I' -%% indexed by the masked value. `?GL_MAP_COLOR' is specified with ``gl:pixelTransfer'' -%% . The contents of the index map is specified with {@link gl:pixelMapfv/3} . -%% -%% If the resulting pixels are to be written to an RGBA color buffer, or if they are read -%% back to client memory in a format other than `?GL_COLOR_INDEX', the pixels are converted -%% from indices to colors by referencing the four maps `?GL_PIXEL_MAP_I_TO_R', `?GL_PIXEL_MAP_I_TO_G' -%% , `?GL_PIXEL_MAP_I_TO_B', and `?GL_PIXEL_MAP_I_TO_A'. Before being dereferenced, -%% the index is masked by 2 n-1, where n is `?GL_PIXEL_MAP_I_TO_R_SIZE' for the -%% red map, `?GL_PIXEL_MAP_I_TO_G_SIZE' for the green map, `?GL_PIXEL_MAP_I_TO_B_SIZE' -%% for the blue map, and `?GL_PIXEL_MAP_I_TO_A_SIZE' for the alpha map. All components -%% taken from the maps are then clamped to the range [0 1]. The contents of the four maps is -%% specified with {@link gl:pixelMapfv/3} . -%% -%% `Depth': Each depth value is multiplied by `?GL_DEPTH_SCALE', added to `?GL_DEPTH_BIAS' -%% , then clamped to the range [0 1]. -%% -%% `Stencil': Each index is shifted `?GL_INDEX_SHIFT' bits just as a color index -%% is, then added to `?GL_INDEX_OFFSET'. If `?GL_MAP_STENCIL' is true, each index -%% is masked by 2 n-1, where n is `?GL_PIXEL_MAP_S_TO_S_SIZE', then replaced by -%% the contents of `?GL_PIXEL_MAP_S_TO_S' indexed by the masked value. -%% -%% The following table gives the type, initial value, and range of valid values for each -%% of the pixel transfer parameters that are set with ``gl:pixelTransfer''. -%% -%% <table><tbody><tr><td> `Pname' </td><td>` Type '</td><td>` Initial Value '</td> -%% <td>` Valid Range '</td></tr></tbody><tbody><tr><td>`?GL_MAP_COLOR'</td><td> -%% boolean </td><td> false </td><td> true/false </td></tr><tr><td>`?GL_MAP_STENCIL'</td> -%% <td> boolean </td><td> false </td><td> true/false </td></tr><tr><td>`?GL_INDEX_SHIFT'</td> -%% <td> integer </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_INDEX_OFFSET'</td><td> integer -%% </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_RED_SCALE'</td><td> float </td><td> 1 </td> -%% <td>(-)</td></tr><tr><td>`?GL_GREEN_SCALE'</td><td> float </td><td> 1 </td><td>(-)</td></tr> -%% <tr><td>`?GL_BLUE_SCALE'</td><td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_ALPHA_SCALE' -%% </td><td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_DEPTH_SCALE'</td><td> -%% float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_RED_BIAS'</td><td> float </td><td> -%% 0 </td><td>(-)</td></tr><tr><td>`?GL_GREEN_BIAS'</td><td> float </td><td> 0 </td><td>(-)</td> -%% </tr><tr><td>`?GL_BLUE_BIAS'</td><td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_ALPHA_BIAS' -%% </td><td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_DEPTH_BIAS'</td><td> -%% float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_RED_SCALE'</td><td> -%% float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_GREEN_SCALE'</td> -%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_BLUE_SCALE'</td> -%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_ALPHA_SCALE'</td> -%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_RED_BIAS'</td> -%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_GREEN_BIAS'</td> -%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_BLUE_BIAS'</td> -%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_COLOR_MATRIX_ALPHA_BIAS'</td> -%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_RED_SCALE'</td> -%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_GREEN_SCALE'</td> -%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_BLUE_SCALE'</td> -%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_ALPHA_SCALE'</td> -%% <td> float </td><td> 1 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_RED_BIAS'</td> -%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_GREEN_BIAS'</td> -%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_BLUE_BIAS'</td> -%% <td> float </td><td> 0 </td><td>(-)</td></tr><tr><td>`?GL_POST_CONVOLUTION_ALPHA_BIAS'</td> -%% <td> float </td><td> 0 </td><td>(-)</td></tr></tbody></table> -%% -%% ``gl:pixelTransferf'' can be used to set any pixel transfer parameter. If the parameter -%% type is boolean, 0 implies false and any other value implies true. If `Pname' is -%% an integer parameter, `Param' is rounded to the nearest integer. -%% -%% Likewise, ``gl:pixelTransferi'' can be used to set any of the pixel transfer parameters. -%% Boolean parameters are set to false if `Param' is 0 and to true otherwise. `Param' -%% is converted to floating point before being assigned to real-valued parameters. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelTransfer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPixelTransfer.xml">external</a> documentation. -spec pixelTransferf(Pname, Param) -> 'ok' when Pname :: enum(),Param :: float(). pixelTransferf(Pname,Param) -> cast(5225, <<Pname:?GLenum,Param:?GLfloat>>). @@ -5025,72 +2283,7 @@ pixelTransferi(Pname,Param) -> %% page, and partly in the reference pages for the pixel and texture image commands. Only %% the specification of the maps is described in this reference page. %% -%% `Map' is a symbolic map name, indicating one of ten maps to set. `Mapsize' specifies -%% the number of entries in the map, and `Values' is a pointer to an array of `Mapsize' -%% map values. -%% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a pixel transfer map is specified, `Values' is -%% treated as a byte offset into the buffer object's data store. -%% -%% The ten maps are as follows: -%% -%% `?GL_PIXEL_MAP_I_TO_I': Maps color indices to color indices. -%% -%% `?GL_PIXEL_MAP_S_TO_S': Maps stencil indices to stencil indices. -%% -%% `?GL_PIXEL_MAP_I_TO_R': Maps color indices to red components. -%% -%% `?GL_PIXEL_MAP_I_TO_G': Maps color indices to green components. -%% -%% `?GL_PIXEL_MAP_I_TO_B': Maps color indices to blue components. -%% -%% `?GL_PIXEL_MAP_I_TO_A': Maps color indices to alpha components. -%% -%% `?GL_PIXEL_MAP_R_TO_R': Maps red components to red components. -%% -%% `?GL_PIXEL_MAP_G_TO_G': Maps green components to green components. -%% -%% `?GL_PIXEL_MAP_B_TO_B': Maps blue components to blue components. -%% -%% `?GL_PIXEL_MAP_A_TO_A': Maps alpha components to alpha components. -%% -%% The entries in a map can be specified as single-precision floating-point numbers, unsigned -%% short integers, or unsigned int integers. Maps that store color component values (all -%% but `?GL_PIXEL_MAP_I_TO_I' and `?GL_PIXEL_MAP_S_TO_S') retain their values in -%% floating-point format, with unspecified mantissa and exponent sizes. Floating-point values -%% specified by ``gl:pixelMapfv'' are converted directly to the internal floating-point -%% format of these maps, then clamped to the range [0,1]. Unsigned integer values specified -%% by ``gl:pixelMapusv'' and ``gl:pixelMapuiv'' are converted linearly such that the -%% largest representable integer maps to 1.0, and 0 maps to 0.0. -%% -%% Maps that store indices, `?GL_PIXEL_MAP_I_TO_I' and `?GL_PIXEL_MAP_S_TO_S', -%% retain their values in fixed-point format, with an unspecified number of bits to the right -%% of the binary point. Floating-point values specified by ``gl:pixelMapfv'' are converted -%% directly to the internal fixed-point format of these maps. Unsigned integer values specified -%% by ``gl:pixelMapusv'' and ``gl:pixelMapuiv'' specify integer values, with all 0's -%% to the right of the binary point. -%% -%% The following table shows the initial sizes and values for each of the maps. Maps that -%% are indexed by either color or stencil indices must have `Mapsize' = 2 n for some -%% n or the results are undefined. The maximum allowable size for each map depends on the -%% implementation and can be determined by calling {@link gl:getBooleanv/1} with argument `?GL_MAX_PIXEL_MAP_TABLE' -%% . The single maximum applies to all maps; it is at least 32. <table><tbody><tr><td> `Map' -%% </td><td>` Lookup Index '</td><td>` Lookup Value '</td><td>` Initial Size '</td> -%% <td>` Initial Value '</td></tr></tbody><tbody><tr><td>`?GL_PIXEL_MAP_I_TO_I'</td> -%% <td> color index </td><td> color index </td><td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_S_TO_S' -%% </td><td> stencil index </td><td> stencil index </td><td> 1 </td><td> 0 </td></tr><tr><td> -%% `?GL_PIXEL_MAP_I_TO_R'</td><td> color index </td><td> R </td><td> 1 </td><td> 0 </td> -%% </tr><tr><td>`?GL_PIXEL_MAP_I_TO_G'</td><td> color index </td><td> G </td><td> 1 </td> -%% <td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_I_TO_B'</td><td> color index </td><td> B </td> -%% <td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_I_TO_A'</td><td> color index </td> -%% <td> A </td><td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_R_TO_R'</td><td> R </td> -%% <td> R </td><td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_G_TO_G'</td><td> G </td> -%% <td> G </td><td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_B_TO_B'</td><td> B </td> -%% <td> B </td><td> 1 </td><td> 0 </td></tr><tr><td>`?GL_PIXEL_MAP_A_TO_A'</td><td> A </td> -%% <td> A </td><td> 1 </td><td> 0 </td></tr></tbody></table> -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPixelMap.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPixelMap.xml">external</a> documentation. -spec pixelMapfv(Map, Mapsize, Values) -> 'ok' when Map :: enum(),Mapsize :: integer(),Values :: binary(). pixelMapfv(Map,Mapsize,Values) -> send_bin(Values), @@ -5121,19 +2314,7 @@ pixelMapusv(Map,Mapsize,Values) -> %% , and {@link gl:copyTexSubImage3D/9} . to map color indices, stencil indices, color components, %% and depth components to other values. %% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a pixel map is requested, `Data' is treated as -%% a byte offset into the buffer object's data store. -%% -%% Unsigned integer values, if requested, are linearly mapped from the internal fixed or -%% floating-point representation such that 1.0 maps to the largest representable integer -%% value, and 0.0 maps to 0. Return unsigned integer values are undefined if the map value -%% was not in the range [0,1]. -%% -%% To determine the required size of `Map' , call {@link gl:getBooleanv/1} with the appropriate -%% symbolic constant. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetPixelMap.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetPixelMap.xml">external</a> documentation. -spec getPixelMapfv(Map, Values) -> 'ok' when Map :: enum(),Values :: mem(). getPixelMapfv(Map,Values) -> send_bin(Values), @@ -5160,42 +2341,7 @@ getPixelMapusv(Map,Values) -> %% using the current raster color or index. Frame buffer pixels corresponding to 0's in the %% bitmap are not modified. %% -%% ``gl:bitmap'' takes seven arguments. The first pair specifies the width and height of -%% the bitmap image. The second pair specifies the location of the bitmap origin relative -%% to the lower left corner of the bitmap image. The third pair of arguments specifies `x' -%% and `y' offsets to be added to the current raster position after the bitmap has -%% been drawn. The final argument is a pointer to the bitmap image itself. -%% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a bitmap image is specified, `Bitmap' is treated -%% as a byte offset into the buffer object's data store. -%% -%% The bitmap image is interpreted like image data for the {@link gl:drawPixels/5} command, -%% with `Width' and `Height' corresponding to the width and height arguments of -%% that command, and with `type' set to `?GL_BITMAP' and `format' set to `?GL_COLOR_INDEX' -%% . Modes specified using {@link gl:pixelStoref/2} affect the interpretation of bitmap image -%% data; modes specified using {@link gl:pixelTransferf/2} do not. -%% -%% If the current raster position is invalid, ``gl:bitmap'' is ignored. Otherwise, the -%% lower left corner of the bitmap image is positioned at the window coordinates -%% -%% x w=|x r-x o| -%% -%% y w=|y r-y o| -%% -%% where (x r y r) is the raster position and (x o y o) is the bitmap origin. Fragments are then generated -%% for each pixel corresponding to a 1 (one) in the bitmap image. These fragments are generated -%% using the current raster `z' coordinate, color or color index, and current raster -%% texture coordinates. They are then treated just as if they had been generated by a point, -%% line, or polygon, including texture mapping, fogging, and all per-fragment operations -%% such as alpha and depth testing. -%% -%% After the bitmap has been drawn, the `x' and `y' coordinates of the current -%% raster position are offset by `Xmove' and `Ymove' . No change is made to the `z' -%% coordinate of the current raster position, or to the current raster color, texture coordinates, -%% or index. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBitmap.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glBitmap.xml">external</a> documentation. -spec bitmap(Width, Height, Xorig, Yorig, Xmove, Ymove, Bitmap) -> 'ok' when Width :: integer(),Height :: integer(),Xorig :: float(),Yorig :: float(),Xmove :: float(),Ymove :: float(),Bitmap :: offset()|mem(). bitmap(Width,Height,Xorig,Yorig,Xmove,Ymove,Bitmap) when is_integer(Bitmap) -> cast(5233, <<Width:?GLsizei,Height:?GLsizei,Xorig:?GLfloat,Yorig:?GLfloat,Xmove:?GLfloat,Ymove:?GLfloat,Bitmap:?GLuint>>); @@ -5212,91 +2358,7 @@ bitmap(Width,Height,Xorig,Yorig,Xmove,Ymove,Bitmap) -> %% This reference page describes the effects on ``gl:readPixels'' of most, but not all %% of the parameters specified by these three commands. %% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a block of pixels is requested, `Data' is treated -%% as a byte offset into the buffer object's data store rather than a pointer to client memory. -%% -%% -%% ``gl:readPixels'' returns values from each pixel with lower left corner at (x+i y+j) for 0<= -%% i< width and 0<= j< height. This pixel is said to be the ith pixel in the -%% jth row. Pixels are returned in row order from the lowest to the highest row, left to -%% right in each row. -%% -%% `Format' specifies the format for the returned pixel values; accepted values are: -%% -%% `?GL_STENCIL_INDEX': Stencil values are read from the stencil buffer. Each index -%% is converted to fixed point, shifted left or right depending on the value and sign of `?GL_INDEX_SHIFT' -%% , and added to `?GL_INDEX_OFFSET'. If `?GL_MAP_STENCIL' is `?GL_TRUE', -%% indices are replaced by their mappings in the table `?GL_PIXEL_MAP_S_TO_S'. -%% -%% `?GL_DEPTH_COMPONENT': Depth values are read from the depth buffer. Each component -%% is converted to floating point such that the minimum depth value maps to 0 and the maximum -%% value maps to 1. Each component is then multiplied by `?GL_DEPTH_SCALE', added to `?GL_DEPTH_BIAS' -%% , and finally clamped to the range [0 1]. -%% -%% `?GL_DEPTH_STENCIL': Values are taken from both the depth and stencil buffers. The `Type' -%% parameter must be `?GL_UNSIGNED_INT_24_8' or `?GL_FLOAT_32_UNSIGNED_INT_24_8_REV' -%% . -%% -%% `?GL_RED' -%% -%% `?GL_GREEN' -%% -%% `?GL_BLUE' -%% -%% `?GL_RGB' -%% -%% `?GL_BGR' -%% -%% `?GL_RGBA' -%% -%% `?GL_BGRA': Finally, the indices or components are converted to the proper format, -%% as specified by `Type' . If `Format' is `?GL_STENCIL_INDEX' and `Type' -%% is not `?GL_FLOAT', each index is masked with the mask value given in the following -%% table. If `Type' is `?GL_FLOAT', then each integer index is converted to single-precision -%% floating-point format. -%% -%% If `Format' is `?GL_RED', `?GL_GREEN', `?GL_BLUE', `?GL_RGB', `?GL_BGR' -%% , `?GL_RGBA', or `?GL_BGRA' and `Type' is not `?GL_FLOAT', each component -%% is multiplied by the multiplier shown in the following table. If type is `?GL_FLOAT', -%% then each component is passed as is (or converted to the client's single-precision floating-point -%% format if it is different from the one used by the GL). -%% -%% <table><tbody><tr><td> `Type' </td><td>` Index Mask '</td><td>` Component Conversion ' -%% </td></tr></tbody><tbody><tr><td>`?GL_UNSIGNED_BYTE'</td><td> 2 8-1</td><td>(2 8-1) c</td></tr> -%% <tr><td>`?GL_BYTE'</td><td> 2 7-1</td><td>((2 8-1) c-1)/2</td></tr><tr><td>`?GL_UNSIGNED_SHORT' -%% </td><td> 2 16-1</td><td>(2 16-1) c</td></tr><tr><td>`?GL_SHORT'</td><td> 2 15-1</td><td>((2 -%% 16-1) -%% c-1)/2</td> -%% </tr><tr><td>`?GL_UNSIGNED_INT'</td><td> 2 32-1</td><td>(2 32-1) c</td></tr><tr><td>`?GL_INT' -%% </td><td> 2 31-1</td><td>((2 32-1) c-1)/2</td></tr><tr><td>`?GL_HALF_FLOAT'</td><td> none </td><td> -%% c</td></tr><tr><td>`?GL_FLOAT'</td><td> none </td><td> c</td></tr><tr><td>`?GL_UNSIGNED_BYTE_3_3_2' -%% </td><td> 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_BYTE_2_3_3_REV'</td><td> -%% 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_6_5'</td><td> 2 N-1</td><td> -%% (2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_6_5_REV'</td><td> 2 N-1</td><td>(2 N-1) c</td></tr> -%% <tr><td>`?GL_UNSIGNED_SHORT_4_4_4_4'</td><td> 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_SHORT_4_4_4_4_REV' -%% </td><td> 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_5_5_1'</td><td> 2 -%% N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_SHORT_1_5_5_5_REV'</td><td> 2 N-1</td> -%% <td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_INT_8_8_8_8'</td><td> 2 N-1</td><td>(2 N-1) c</td></tr> -%% <tr><td>`?GL_UNSIGNED_INT_8_8_8_8_REV'</td><td> 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_INT_10_10_10_2' -%% </td><td> 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_INT_2_10_10_10_REV'</td><td> -%% 2 N-1</td><td>(2 N-1) c</td></tr><tr><td>`?GL_UNSIGNED_INT_24_8'</td><td> 2 N-1</td><td>(2 -%% N-1) -%% c</td></tr><tr><td>`?GL_UNSIGNED_INT_10F_11F_11F_REV'</td><td> -- </td><td> Special </td> -%% </tr><tr><td>`?GL_UNSIGNED_INT_5_9_9_9_REV'</td><td> -- </td><td> Special </td></tr><tr> -%% <td>`?GL_FLOAT_32_UNSIGNED_INT_24_8_REV'</td><td> none </td><td> c (Depth Only) </td> -%% </tr></tbody></table> -%% -%% Return values are placed in memory as follows. If `Format' is `?GL_STENCIL_INDEX' -%% , `?GL_DEPTH_COMPONENT', `?GL_RED', `?GL_GREEN', or `?GL_BLUE', a -%% single value is returned and the data for the ith pixel in the jth row is placed in -%% location (j) width+i. `?GL_RGB' and `?GL_BGR' return three values, `?GL_RGBA' -%% and `?GL_BGRA' return four values for each pixel, with all values corresponding -%% to a single pixel occupying contiguous space in `Data' . Storage parameters set by {@link gl:pixelStoref/2} -%% , such as `?GL_PACK_LSB_FIRST' and `?GL_PACK_SWAP_BYTES', affect the way that -%% data is written into memory. See {@link gl:pixelStoref/2} for a description. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glReadPixels.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glReadPixels.xhtml">external</a> documentation. -spec readPixels(X, Y, Width, Height, Format, Type, Pixels) -> 'ok' when X :: integer(),Y :: integer(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Pixels :: mem(). readPixels(X,Y,Width,Height,Format,Type,Pixels) -> send_bin(Pixels), @@ -5311,237 +2373,7 @@ readPixels(X,Y,Width,Height,Format,Type,Pixels) -> %% position is valid, and {@link gl:getBooleanv/1} with argument `?GL_CURRENT_RASTER_POSITION' %% to query the raster position. %% -%% Several parameters define the encoding of pixel data in memory and control the processing -%% of the pixel data before it is placed in the frame buffer. These parameters are set with -%% four commands: {@link gl:pixelStoref/2} , {@link gl:pixelTransferf/2} , {@link gl:pixelMapfv/3} , -%% and {@link gl:pixelZoom/2} . This reference page describes the effects on ``gl:drawPixels'' -%% of many, but not all, of the parameters specified by these four commands. -%% -%% Data is read from `Data' as a sequence of signed or unsigned bytes, signed or unsigned -%% shorts, signed or unsigned integers, or single-precision floating-point values, depending -%% on `Type' . When `Type' is one of `?GL_UNSIGNED_BYTE', `?GL_BYTE', `?GL_UNSIGNED_SHORT' -%% , `?GL_SHORT', `?GL_UNSIGNED_INT', `?GL_INT', or `?GL_FLOAT' each -%% of these bytes, shorts, integers, or floating-point values is interpreted as one color -%% or depth component, or one index, depending on `Format' . When `Type' is one of `?GL_UNSIGNED_BYTE_3_3_2' -%% , `?GL_UNSIGNED_SHORT_5_6_5', `?GL_UNSIGNED_SHORT_4_4_4_4', `?GL_UNSIGNED_SHORT_5_5_5_1' -%% , `?GL_UNSIGNED_INT_8_8_8_8', or `?GL_UNSIGNED_INT_10_10_10_2', each unsigned -%% value is interpreted as containing all the components for a single pixel, with the color -%% components arranged according to `Format' . When `Type' is one of `?GL_UNSIGNED_BYTE_2_3_3_REV' -%% , `?GL_UNSIGNED_SHORT_5_6_5_REV', `?GL_UNSIGNED_SHORT_4_4_4_4_REV', `?GL_UNSIGNED_SHORT_1_5_5_5_REV' -%% , `?GL_UNSIGNED_INT_8_8_8_8_REV', or `?GL_UNSIGNED_INT_2_10_10_10_REV', each -%% unsigned value is interpreted as containing all color components, specified by `Format' -%% , for a single pixel in a reversed order. Indices are always treated individually. Color -%% components are treated as groups of one, two, three, or four values, again based on `Format' -%% . Both individual indices and groups of components are referred to as pixels. If `Type' -%% is `?GL_BITMAP', the data must be unsigned bytes, and `Format' must be either `?GL_COLOR_INDEX' -%% or `?GL_STENCIL_INDEX'. Each unsigned byte is treated as eight 1-bit pixels, with -%% bit ordering determined by `?GL_UNPACK_LSB_FIRST' (see {@link gl:pixelStoref/2} ). -%% -%% width×height pixels are read from memory, starting at location `Data' . By default, -%% these pixels are taken from adjacent memory locations, except that after all `Width' -%% pixels are read, the read pointer is advanced to the next four-byte boundary. The four-byte -%% row alignment is specified by {@link gl:pixelStoref/2} with argument `?GL_UNPACK_ALIGNMENT' -%% , and it can be set to one, two, four, or eight bytes. Other pixel store parameters specify -%% different read pointer advancements, both before the first pixel is read and after all `Width' -%% pixels are read. See the {@link gl:pixelStoref/2} reference page for details on these options. -%% -%% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a block of pixels is specified, `Data' is treated -%% as a byte offset into the buffer object's data store. -%% -%% The width×height pixels that are read from memory are each operated on in the same -%% way, based on the values of several parameters specified by {@link gl:pixelTransferf/2} -%% and {@link gl:pixelMapfv/3} . The details of these operations, as well as the target buffer -%% into which the pixels are drawn, are specific to the format of the pixels, as specified -%% by `Format' . `Format' can assume one of 13 symbolic values: -%% -%% `?GL_COLOR_INDEX': Each pixel is a single value, a color index. It is converted -%% to fixed-point format, with an unspecified number of bits to the right of the binary point, -%% regardless of the memory data type. Floating-point values convert to true fixed-point -%% values. Signed and unsigned integer data is converted with all fraction bits set to 0. -%% Bitmap data convert to either 0 or 1. -%% -%% Each fixed-point index is then shifted left by `?GL_INDEX_SHIFT' bits and added to `?GL_INDEX_OFFSET' -%% . If `?GL_INDEX_SHIFT' is negative, the shift is to the right. In either case, zero -%% bits fill otherwise unspecified bit locations in the result. -%% -%% If the GL is in RGBA mode, the resulting index is converted to an RGBA pixel with the -%% help of the `?GL_PIXEL_MAP_I_TO_R', `?GL_PIXEL_MAP_I_TO_G', `?GL_PIXEL_MAP_I_TO_B' -%% , and `?GL_PIXEL_MAP_I_TO_A' tables. If the GL is in color index mode, and if `?GL_MAP_COLOR' -%% is true, the index is replaced with the value that it references in lookup table `?GL_PIXEL_MAP_I_TO_I' -%% . Whether the lookup replacement of the index is done or not, the integer part of the -%% index is then ANDed with 2 b-1, where b is the number of bits in a color index buffer. -%% -%% -%% The GL then converts the resulting indices or RGBA colors to fragments by attaching the -%% current raster position `z' coordinate and texture coordinates to each pixel, then -%% assigning x and y window coordinates to the nth fragment such that x n=x r+n% width -%% -%% -%% y n=y r+|n/width| -%% -%% where (x r y r) is the current raster position. These pixel fragments are then treated just like -%% the fragments generated by rasterizing points, lines, or polygons. Texture mapping, fog, -%% and all the fragment operations are applied before the fragments are written to the frame -%% buffer. -%% -%% `?GL_STENCIL_INDEX': Each pixel is a single value, a stencil index. It is converted -%% to fixed-point format, with an unspecified number of bits to the right of the binary point, -%% regardless of the memory data type. Floating-point values convert to true fixed-point -%% values. Signed and unsigned integer data is converted with all fraction bits set to 0. -%% Bitmap data convert to either 0 or 1. -%% -%% Each fixed-point index is then shifted left by `?GL_INDEX_SHIFT' bits, and added -%% to `?GL_INDEX_OFFSET'. If `?GL_INDEX_SHIFT' is negative, the shift is to the -%% right. In either case, zero bits fill otherwise unspecified bit locations in the result. -%% If `?GL_MAP_STENCIL' is true, the index is replaced with the value that it references -%% in lookup table `?GL_PIXEL_MAP_S_TO_S'. Whether the lookup replacement of the index -%% is done or not, the integer part of the index is then ANDed with 2 b-1, where b is -%% the number of bits in the stencil buffer. The resulting stencil indices are then written -%% to the stencil buffer such that the nth index is written to location -%% -%% x n=x r+n% width -%% -%% y n=y r+|n/width| -%% -%% where (x r y r) is the current raster position. Only the pixel ownership test, the scissor test, -%% and the stencil writemask affect these write operations. -%% -%% `?GL_DEPTH_COMPONENT': Each pixel is a single-depth component. Floating-point data -%% is converted directly to an internal floating-point format with unspecified precision. -%% Signed integer data is mapped linearly to the internal floating-point format such that -%% the most positive representable integer value maps to 1.0, and the most negative representable -%% value maps to -1.0. Unsigned integer data is mapped similarly: the largest integer value -%% maps to 1.0, and 0 maps to 0.0. The resulting floating-point depth value is then multiplied -%% by `?GL_DEPTH_SCALE' and added to `?GL_DEPTH_BIAS'. The result is clamped to -%% the range [0 1]. -%% -%% The GL then converts the resulting depth components to fragments by attaching the current -%% raster position color or color index and texture coordinates to each pixel, then assigning -%% x and y window coordinates to the nth fragment such that -%% -%% x n=x r+n% width -%% -%% y n=y r+|n/width| -%% -%% where (x r y r) is the current raster position. These pixel fragments are then treated just like -%% the fragments generated by rasterizing points, lines, or polygons. Texture mapping, fog, -%% and all the fragment operations are applied before the fragments are written to the frame -%% buffer. -%% -%% `?GL_RGBA' -%% -%% `?GL_BGRA': Each pixel is a four-component group: For `?GL_RGBA', the red component -%% is first, followed by green, followed by blue, followed by alpha; for `?GL_BGRA' -%% the order is blue, green, red and then alpha. Floating-point values are converted directly -%% to an internal floating-point format with unspecified precision. Signed integer values -%% are mapped linearly to the internal floating-point format such that the most positive -%% representable integer value maps to 1.0, and the most negative representable value maps -%% to -1.0. (Note that this mapping does not convert 0 precisely to 0.0.) Unsigned integer -%% data is mapped similarly: The largest integer value maps to 1.0, and 0 maps to 0.0. The -%% resulting floating-point color values are then multiplied by `?GL_c_SCALE' and added -%% to `?GL_c_BIAS', where `c' is RED, GREEN, BLUE, and ALPHA for the respective -%% color components. The results are clamped to the range [0 1]. -%% -%% If `?GL_MAP_COLOR' is true, each color component is scaled by the size of lookup -%% table `?GL_PIXEL_MAP_c_TO_c', then replaced by the value that it references in that -%% table. `c' is R, G, B, or A respectively. -%% -%% The GL then converts the resulting RGBA colors to fragments by attaching the current -%% raster position `z' coordinate and texture coordinates to each pixel, then assigning -%% x and y window coordinates to the nth fragment such that -%% -%% x n=x r+n% width -%% -%% y n=y r+|n/width| -%% -%% where (x r y r) is the current raster position. These pixel fragments are then treated just like -%% the fragments generated by rasterizing points, lines, or polygons. Texture mapping, fog, -%% and all the fragment operations are applied before the fragments are written to the frame -%% buffer. -%% -%% `?GL_RED': Each pixel is a single red component. This component is converted to -%% the internal floating-point format in the same way the red component of an RGBA pixel -%% is. It is then converted to an RGBA pixel with green and blue set to 0, and alpha set -%% to 1. After this conversion, the pixel is treated as if it had been read as an RGBA pixel. -%% -%% -%% `?GL_GREEN': Each pixel is a single green component. This component is converted -%% to the internal floating-point format in the same way the green component of an RGBA pixel -%% is. It is then converted to an RGBA pixel with red and blue set to 0, and alpha set to -%% 1. After this conversion, the pixel is treated as if it had been read as an RGBA pixel. -%% -%% `?GL_BLUE': Each pixel is a single blue component. This component is converted to -%% the internal floating-point format in the same way the blue component of an RGBA pixel -%% is. It is then converted to an RGBA pixel with red and green set to 0, and alpha set to -%% 1. After this conversion, the pixel is treated as if it had been read as an RGBA pixel. -%% -%% `?GL_ALPHA': Each pixel is a single alpha component. This component is converted -%% to the internal floating-point format in the same way the alpha component of an RGBA pixel -%% is. It is then converted to an RGBA pixel with red, green, and blue set to 0. After this -%% conversion, the pixel is treated as if it had been read as an RGBA pixel. -%% -%% `?GL_RGB' -%% -%% `?GL_BGR': Each pixel is a three-component group: red first, followed by green, -%% followed by blue; for `?GL_BGR', the first component is blue, followed by green and -%% then red. Each component is converted to the internal floating-point format in the same -%% way the red, green, and blue components of an RGBA pixel are. The color triple is converted -%% to an RGBA pixel with alpha set to 1. After this conversion, the pixel is treated as if -%% it had been read as an RGBA pixel. -%% -%% `?GL_LUMINANCE': Each pixel is a single luminance component. This component is converted -%% to the internal floating-point format in the same way the red component of an RGBA pixel -%% is. It is then converted to an RGBA pixel with red, green, and blue set to the converted -%% luminance value, and alpha set to 1. After this conversion, the pixel is treated as if -%% it had been read as an RGBA pixel. -%% -%% `?GL_LUMINANCE_ALPHA': Each pixel is a two-component group: luminance first, followed -%% by alpha. The two components are converted to the internal floating-point format in the -%% same way the red component of an RGBA pixel is. They are then converted to an RGBA pixel -%% with red, green, and blue set to the converted luminance value, and alpha set to the converted -%% alpha value. After this conversion, the pixel is treated as if it had been read as an -%% RGBA pixel. -%% -%% The following table summarizes the meaning of the valid constants for the `type' -%% parameter: -%% -%% <table><tbody><tr><td>` Type '</td><td>` Corresponding Type '</td></tr></tbody><tbody> -%% <tr><td>`?GL_UNSIGNED_BYTE'</td><td> unsigned 8-bit integer </td></tr><tr><td>`?GL_BYTE' -%% </td><td> signed 8-bit integer </td></tr><tr><td>`?GL_BITMAP'</td><td> single bits -%% in unsigned 8-bit integers </td></tr><tr><td>`?GL_UNSIGNED_SHORT'</td><td> unsigned -%% 16-bit integer </td></tr><tr><td>`?GL_SHORT'</td><td> signed 16-bit integer </td></tr> -%% <tr><td>`?GL_UNSIGNED_INT'</td><td> unsigned 32-bit integer </td></tr><tr><td>`?GL_INT' -%% </td><td> 32-bit integer </td></tr><tr><td>`?GL_FLOAT'</td><td> single-precision -%% floating-point </td></tr><tr><td>`?GL_UNSIGNED_BYTE_3_3_2'</td><td> unsigned 8-bit -%% integer </td></tr><tr><td>`?GL_UNSIGNED_BYTE_2_3_3_REV'</td><td> unsigned 8-bit -%% integer with reversed component ordering </td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_6_5'</td> -%% <td> unsigned 16-bit integer </td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_6_5_REV'</td><td> -%% unsigned 16-bit integer with reversed component ordering </td></tr><tr><td>`?GL_UNSIGNED_SHORT_4_4_4_4' -%% </td><td> unsigned 16-bit integer </td></tr><tr><td>`?GL_UNSIGNED_SHORT_4_4_4_4_REV'</td> -%% <td> unsigned 16-bit integer with reversed component ordering </td></tr><tr><td>`?GL_UNSIGNED_SHORT_5_5_5_1' -%% </td><td> unsigned 16-bit integer </td></tr><tr><td>`?GL_UNSIGNED_SHORT_1_5_5_5_REV'</td> -%% <td> unsigned 16-bit integer with reversed component ordering </td></tr><tr><td>`?GL_UNSIGNED_INT_8_8_8_8' -%% </td><td> unsigned 32-bit integer </td></tr><tr><td>`?GL_UNSIGNED_INT_8_8_8_8_REV'</td> -%% <td> unsigned 32-bit integer with reversed component ordering </td></tr><tr><td>`?GL_UNSIGNED_INT_10_10_10_2' -%% </td><td> unsigned 32-bit integer </td></tr><tr><td>`?GL_UNSIGNED_INT_2_10_10_10_REV'</td> -%% <td> unsigned 32-bit integer with reversed component ordering </td></tr></tbody></table> -%% -%% The rasterization described so far assumes pixel zoom factors of 1. If {@link gl:pixelZoom/2} -%% is used to change the x and y pixel zoom factors, pixels are converted to fragments -%% as follows. If (x r y r) is the current raster position, and a given pixel is in the nth column -%% and mth row of the pixel rectangle, then fragments are generated for pixels whose centers -%% are in the rectangle with corners at -%% -%% (x r+(zoom x) n y r+(zoom y) m) -%% -%% (x r+(zoom x)(n+1) y r+(zoom y)(m+1)) -%% -%% where zoom x is the value of `?GL_ZOOM_X' and zoom y is the value of `?GL_ZOOM_Y' -%% . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawPixels.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glDrawPixels.xml">external</a> documentation. -spec drawPixels(Width, Height, Format, Type, Pixels) -> 'ok' when Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem(). drawPixels(Width,Height,Format,Type,Pixels) when is_integer(Pixels) -> cast(5236, <<Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>); @@ -5557,98 +2389,7 @@ drawPixels(Width,Height,Format,Type,Pixels) -> %% window. Results of copies from outside the window, or from regions of the window that %% are not exposed, are hardware dependent and undefined. %% -%% `X' and `Y' specify the window coordinates of the lower left corner of the rectangular -%% region to be copied. `Width' and `Height' specify the dimensions of the rectangular -%% region to be copied. Both `Width' and `Height' must not be negative. -%% -%% Several parameters control the processing of the pixel data while it is being copied. -%% These parameters are set with three commands: {@link gl:pixelTransferf/2} , {@link gl:pixelMapfv/3} -%% , and {@link gl:pixelZoom/2} . This reference page describes the effects on ``gl:copyPixels'' -%% of most, but not all, of the parameters specified by these three commands. -%% -%% ``gl:copyPixels'' copies values from each pixel with the lower left-hand corner at (x+i -%% y+j) -%% for 0<= i< width and 0<= j< height. This pixel is said to be the ith -%% pixel in the jth row. Pixels are copied in row order from the lowest to the highest -%% row, left to right in each row. -%% -%% `Type' specifies whether color, depth, or stencil data is to be copied. The details -%% of the transfer for each data type are as follows: -%% -%% `?GL_COLOR': Indices or RGBA colors are read from the buffer currently specified -%% as the read source buffer (see {@link gl:readBuffer/1} ). If the GL is in color index mode, -%% each index that is read from this buffer is converted to a fixed-point format with an -%% unspecified number of bits to the right of the binary point. Each index is then shifted -%% left by `?GL_INDEX_SHIFT' bits, and added to `?GL_INDEX_OFFSET'. If `?GL_INDEX_SHIFT' -%% is negative, the shift is to the right. In either case, zero bits fill otherwise unspecified -%% bit locations in the result. If `?GL_MAP_COLOR' is true, the index is replaced with -%% the value that it references in lookup table `?GL_PIXEL_MAP_I_TO_I'. Whether the -%% lookup replacement of the index is done or not, the integer part of the index is then -%% ANDed with 2 b-1, where b is the number of bits in a color index buffer. -%% -%% If the GL is in RGBA mode, the red, green, blue, and alpha components of each pixel that -%% is read are converted to an internal floating-point format with unspecified precision. -%% The conversion maps the largest representable component value to 1.0, and component value -%% 0 to 0.0. The resulting floating-point color values are then multiplied by `?GL_c_SCALE' -%% and added to `?GL_c_BIAS', where `c' is RED, GREEN, BLUE, and ALPHA for the -%% respective color components. The results are clamped to the range [0,1]. If `?GL_MAP_COLOR' -%% is true, each color component is scaled by the size of lookup table `?GL_PIXEL_MAP_c_TO_c' -%% , then replaced by the value that it references in that table. `c' is R, G, B, or -%% A. -%% -%% If the ARB_imaging extension is supported, the color values may be additionally processed -%% by color-table lookups, color-matrix transformations, and convolution filters. -%% -%% The GL then converts the resulting indices or RGBA colors to fragments by attaching the -%% current raster position `z' coordinate and texture coordinates to each pixel, then -%% assigning window coordinates (x r+i y r+j), where (x r y r) is the current raster position, and the pixel was -%% the ith pixel in the jth row. These pixel fragments are then treated just like the -%% fragments generated by rasterizing points, lines, or polygons. Texture mapping, fog, and -%% all the fragment operations are applied before the fragments are written to the frame -%% buffer. -%% -%% `?GL_DEPTH': Depth values are read from the depth buffer and converted directly -%% to an internal floating-point format with unspecified precision. The resulting floating-point -%% depth value is then multiplied by `?GL_DEPTH_SCALE' and added to `?GL_DEPTH_BIAS' -%% . The result is clamped to the range [0,1]. -%% -%% The GL then converts the resulting depth components to fragments by attaching the current -%% raster position color or color index and texture coordinates to each pixel, then assigning -%% window coordinates (x r+i y r+j), where (x r y r) is the current raster position, and the pixel was the ith -%% pixel in the jth row. These pixel fragments are then treated just like the fragments -%% generated by rasterizing points, lines, or polygons. Texture mapping, fog, and all the -%% fragment operations are applied before the fragments are written to the frame buffer. -%% -%% `?GL_STENCIL': Stencil indices are read from the stencil buffer and converted to -%% an internal fixed-point format with an unspecified number of bits to the right of the -%% binary point. Each fixed-point index is then shifted left by `?GL_INDEX_SHIFT' bits, -%% and added to `?GL_INDEX_OFFSET'. If `?GL_INDEX_SHIFT' is negative, the shift -%% is to the right. In either case, zero bits fill otherwise unspecified bit locations in -%% the result. If `?GL_MAP_STENCIL' is true, the index is replaced with the value that -%% it references in lookup table `?GL_PIXEL_MAP_S_TO_S'. Whether the lookup replacement -%% of the index is done or not, the integer part of the index is then ANDed with 2 b-1, -%% where b is the number of bits in the stencil buffer. The resulting stencil indices are -%% then written to the stencil buffer such that the index read from the ith location of -%% the jth row is written to location (x r+i y r+j), where (x r y r) is the current raster position. Only the -%% pixel ownership test, the scissor test, and the stencil writemask affect these write operations. -%% -%% -%% The rasterization described thus far assumes pixel zoom factors of 1.0. If {@link gl:pixelZoom/2} -%% is used to change the x and y pixel zoom factors, pixels are converted to fragments -%% as follows. If (x r y r) is the current raster position, and a given pixel is in the ith location -%% in the jth row of the source pixel rectangle, then fragments are generated for pixels -%% whose centers are in the rectangle with corners at -%% -%% (x r+(zoom x) i y r+(zoom y) j) -%% -%% and -%% -%% (x r+(zoom x)(i+1) y r+(zoom y)(j+1)) -%% -%% where zoom x is the value of `?GL_ZOOM_X' and zoom y is the value of `?GL_ZOOM_Y' -%% . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyPixels.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glCopyPixels.xml">external</a> documentation. -spec copyPixels(X, Y, Width, Height, Type) -> 'ok' when X :: integer(),Y :: integer(),Width :: integer(),Height :: integer(),Type :: enum(). copyPixels(X,Y,Width,Height,Type) -> cast(5238, <<X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei,Type:?GLenum>>). @@ -5661,57 +2402,7 @@ copyPixels(X,Y,Width,Height,Type) -> %% typically used in multipass rendering algorithms to achieve special effects, such as decals, %% outlining, and constructive solid geometry rendering. %% -%% The stencil test conditionally eliminates a pixel based on the outcome of a comparison -%% between the reference value and the value in the stencil buffer. To enable and disable -%% the test, call {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_STENCIL_TEST' -%% . To specify actions based on the outcome of the stencil test, call {@link gl:stencilOp/3} -%% or {@link gl:stencilOpSeparate/4} . -%% -%% There can be two separate sets of `Func' , `Ref' , and `Mask' parameters; -%% one affects back-facing polygons, and the other affects front-facing polygons as well -%% as other non-polygon primitives. {@link gl:stencilFunc/3} sets both front and back stencil -%% state to the same values. Use {@link gl:stencilFuncSeparate/4} to set front and back stencil -%% state to different values. -%% -%% `Func' is a symbolic constant that determines the stencil comparison function. It -%% accepts one of eight values, shown in the following list. `Ref' is an integer reference -%% value that is used in the stencil comparison. It is clamped to the range [0 2 n-1], where n -%% is the number of bitplanes in the stencil buffer. `Mask' is bitwise ANDed with both -%% the reference value and the stored stencil value, with the ANDed values participating -%% in the comparison. -%% -%% If `stencil' represents the value stored in the corresponding stencil buffer location, -%% the following list shows the effect of each comparison function that can be specified by `Func' -%% . Only if the comparison succeeds is the pixel passed through to the next stage in the -%% rasterization process (see {@link gl:stencilOp/3} ). All tests treat `stencil' values -%% as unsigned integers in the range [0 2 n-1], where n is the number of bitplanes in the stencil -%% buffer. -%% -%% The following values are accepted by `Func' : -%% -%% `?GL_NEVER': Always fails. -%% -%% `?GL_LESS': Passes if ( `Ref' & `Mask' ) < ( `stencil' & `Mask' -%% ). -%% -%% `?GL_LEQUAL': Passes if ( `Ref' & `Mask' ) <= ( `stencil' -%% & `Mask' ). -%% -%% `?GL_GREATER': Passes if ( `Ref' & `Mask' ) > ( `stencil' -%% & `Mask' ). -%% -%% `?GL_GEQUAL': Passes if ( `Ref' & `Mask' ) >= ( `stencil' -%% & `Mask' ). -%% -%% `?GL_EQUAL': Passes if ( `Ref' & `Mask' ) = ( `stencil' & `Mask' -%% ). -%% -%% `?GL_NOTEQUAL': Passes if ( `Ref' & `Mask' ) != ( `stencil' & -%% `Mask' ). -%% -%% `?GL_ALWAYS': Always passes. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilFunc.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glStencilFunc.xhtml">external</a> documentation. -spec stencilFunc(Func, Ref, Mask) -> 'ok' when Func :: enum(),Ref :: integer(),Mask :: integer(). stencilFunc(Func,Ref,Mask) -> cast(5239, <<Func:?GLenum,Ref:?GLint,Mask:?GLuint>>). @@ -5724,12 +2415,7 @@ stencilFunc(Func,Ref,Mask) -> %% bit in the stencil buffer. Where a 0 appears, the corresponding bit is write-protected. %% Initially, all bits are enabled for writing. %% -%% There can be two separate `Mask' writemasks; one affects back-facing polygons, and -%% the other affects front-facing polygons as well as other non-polygon primitives. {@link gl:stencilMask/1} -%% sets both front and back stencil writemasks to the same values. Use {@link gl:stencilMaskSeparate/2} -%% to set front and back stencil writemasks to different values. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilMask.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glStencilMask.xhtml">external</a> documentation. -spec stencilMask(Mask) -> 'ok' when Mask :: integer(). stencilMask(Mask) -> cast(5240, <<Mask:?GLuint>>). @@ -5742,55 +2428,7 @@ stencilMask(Mask) -> %% used in multipass rendering algorithms to achieve special effects, such as decals, outlining, %% and constructive solid geometry rendering. %% -%% The stencil test conditionally eliminates a pixel based on the outcome of a comparison -%% between the value in the stencil buffer and a reference value. To enable and disable the -%% test, call {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_STENCIL_TEST' -%% ; to control it, call {@link gl:stencilFunc/3} or {@link gl:stencilFuncSeparate/4} . -%% -%% There can be two separate sets of `Sfail' , `Dpfail' , and `Dppass' parameters; -%% one affects back-facing polygons, and the other affects front-facing polygons as well -%% as other non-polygon primitives. {@link gl:stencilOp/3} sets both front and back stencil -%% state to the same values. Use {@link gl:stencilOpSeparate/4} to set front and back stencil -%% state to different values. -%% -%% ``gl:stencilOp'' takes three arguments that indicate what happens to the stored stencil -%% value while stenciling is enabled. If the stencil test fails, no change is made to the -%% pixel's color or depth buffers, and `Sfail' specifies what happens to the stencil -%% buffer contents. The following eight actions are possible. -%% -%% `?GL_KEEP': Keeps the current value. -%% -%% `?GL_ZERO': Sets the stencil buffer value to 0. -%% -%% `?GL_REPLACE': Sets the stencil buffer value to `ref', as specified by {@link gl:stencilFunc/3} -%% . -%% -%% `?GL_INCR': Increments the current stencil buffer value. Clamps to the maximum representable -%% unsigned value. -%% -%% `?GL_INCR_WRAP': Increments the current stencil buffer value. Wraps stencil buffer -%% value to zero when incrementing the maximum representable unsigned value. -%% -%% `?GL_DECR': Decrements the current stencil buffer value. Clamps to 0. -%% -%% `?GL_DECR_WRAP': Decrements the current stencil buffer value. Wraps stencil buffer -%% value to the maximum representable unsigned value when decrementing a stencil buffer value -%% of zero. -%% -%% `?GL_INVERT': Bitwise inverts the current stencil buffer value. -%% -%% Stencil buffer values are treated as unsigned integers. When incremented and decremented, -%% values are clamped to 0 and 2 n-1, where n is the value returned by querying `?GL_STENCIL_BITS' -%% . -%% -%% The other two arguments to ``gl:stencilOp'' specify stencil buffer actions that depend -%% on whether subsequent depth buffer tests succeed ( `Dppass' ) or fail ( `Dpfail' ) -%% (see {@link gl:depthFunc/1} ). The actions are specified using the same eight symbolic constants -%% as `Sfail' . Note that `Dpfail' is ignored when there is no depth buffer, or -%% when the depth buffer is not enabled. In these cases, `Sfail' and `Dppass' specify -%% stencil action when the stencil test fails and passes, respectively. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilOp.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glStencilOp.xhtml">external</a> documentation. -spec stencilOp(Fail, Zfail, Zpass) -> 'ok' when Fail :: enum(),Zfail :: enum(),Zpass :: enum(). stencilOp(Fail,Zfail,Zpass) -> cast(5241, <<Fail:?GLenum,Zfail:?GLenum,Zpass:?GLenum>>). @@ -5801,7 +2439,7 @@ stencilOp(Fail,Zfail,Zpass) -> %% buffer. `S' is masked with 2 m-1, where m is the number of bits in the stencil %% buffer. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearStencil.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glClearStencil.xhtml">external</a> documentation. -spec clearStencil(S) -> 'ok' when S :: integer(). clearStencil(S) -> cast(5242, <<S:?GLint>>). @@ -5818,69 +2456,7 @@ clearStencil(S) -> %% is either `?GL_OBJECT_PLANE' or `?GL_EYE_PLANE', `Params' contains coefficients %% for the corresponding texture generation function. %% -%% If the texture generation function is `?GL_OBJECT_LINEAR', the function -%% -%% g=p 1×x o+p 2×y o+p 3×z o+p 4×w o -%% -%% is used, where g is the value computed for the coordinate named in `Coord' , p 1, -%% p 2, p 3, and p 4 are the four values supplied in `Params' , and x o, y o, z o, -%% and w o are the object coordinates of the vertex. This function can be used, for example, -%% to texture-map terrain using sea level as a reference plane (defined by p 1, p 2, p -%% 3, and p 4). The altitude of a terrain vertex is computed by the `?GL_OBJECT_LINEAR' -%% coordinate generation function as its distance from sea level; that altitude can then -%% be used to index the texture image to map white snow onto peaks and green grass onto foothills. -%% -%% -%% If the texture generation function is `?GL_EYE_LINEAR', the function -%% -%% g=(p 1)"×x e+(p 2)"×y e+(p 3)"×z e+(p 4)"×w e -%% -%% is used, where -%% -%% ((p 1)" (p 2)" (p 3)" (p 4)")=(p 1 p 2 p 3 p 4) M -1 -%% -%% and x e, y e, z e, and w e are the eye coordinates of the vertex, p 1, p 2, p 3, -%% and p 4 are the values supplied in `Params' , and M is the modelview matrix when ``gl:texGen'' -%% is invoked. If M is poorly conditioned or singular, texture coordinates generated by -%% the resulting function may be inaccurate or undefined. -%% -%% Note that the values in `Params' define a reference plane in eye coordinates. The -%% modelview matrix that is applied to them may not be the same one in effect when the polygon -%% vertices are transformed. This function establishes a field of texture coordinates that -%% can produce dynamic contour lines on moving objects. -%% -%% If the texture generation function is `?GL_SPHERE_MAP' and `Coord' is either `?GL_S' -%% or `?GL_T', s and t texture coordinates are generated as follows. Let `u' -%% be the unit vector pointing from the origin to the polygon vertex (in eye coordinates). -%% Let `n' sup prime be the current normal, after transformation to eye coordinates. -%% Let -%% -%% f=(f x f y f z) T be the reflection vector such that -%% -%% f=u-2 n" (n") T u -%% -%% Finally, let m=2 ((f x) 2+(f y) 2+(f z+1) 2). Then the values assigned to the s and t texture coordinates -%% are -%% -%% s=f x/m+1/2 -%% -%% t=f y/m+1/2 -%% -%% To enable or disable a texture-coordinate generation function, call {@link gl:enable/1} -%% or {@link gl:enable/1} with one of the symbolic texture-coordinate names (`?GL_TEXTURE_GEN_S' -%% , `?GL_TEXTURE_GEN_T', `?GL_TEXTURE_GEN_R', or `?GL_TEXTURE_GEN_Q') as -%% the argument. When enabled, the specified texture coordinate is computed according to -%% the generating function associated with that coordinate. When disabled, subsequent vertices -%% take the specified texture coordinate from the current set of texture coordinates. Initially, -%% all texture generation functions are set to `?GL_EYE_LINEAR' and are disabled. Both -%% s plane equations are (1, 0, 0, 0), both t plane equations are (0, 1, 0, 0), and all -%% r and q plane equations are (0, 0, 0, 0). -%% -%% When the ARB_multitexture extension is supported, ``gl:texGen'' sets the texture generation -%% parameters for the currently active texture unit, selected with {@link gl:activeTexture/1} . -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexGen.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTexGen.xml">external</a> documentation. -spec texGend(Coord, Pname, Param) -> 'ok' when Coord :: enum(),Pname :: enum(),Param :: float(). texGend(Coord,Pname,Param) -> cast(5243, <<Coord:?GLenum,Pname:?GLenum,Param:?GLdouble>>). @@ -5925,22 +2501,7 @@ texGeniv(Coord,Pname,Params) -> %% of the (`s', `t', `r', `q') texture coordinates, using the symbolic %% constant `?GL_S', `?GL_T', `?GL_R', or `?GL_Q'. %% -%% `Pname' specifies one of three symbolic names: -%% -%% `?GL_TEXTURE_GEN_MODE': `Params' returns the single-valued texture generation -%% function, a symbolic constant. The initial value is `?GL_EYE_LINEAR'. -%% -%% `?GL_OBJECT_PLANE': `Params' returns the four plane equation coefficients that -%% specify object linear-coordinate generation. Integer values, when requested, are mapped -%% directly from the internal floating-point representation. -%% -%% `?GL_EYE_PLANE': `Params' returns the four plane equation coefficients that -%% specify eye linear-coordinate generation. Integer values, when requested, are mapped directly -%% from the internal floating-point representation. The returned values are those maintained -%% in eye coordinates. They are not equal to the values specified using {@link gl:texGend/3} , -%% unless the modelview matrix was identity when {@link gl:texGend/3} was called. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexGen.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetTexGen.xml">external</a> documentation. -spec getTexGendv(Coord, Pname) -> {float(),float(),float(),float()} when Coord :: enum(),Pname :: enum(). getTexGendv(Coord,Pname) -> call(5249, <<Coord:?GLenum,Pname:?GLenum>>). @@ -5959,14 +2520,14 @@ getTexGeniv(Coord,Pname) -> %% @doc glTexEnvf %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexEnvf.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec texEnvf(Target, Pname, Param) -> 'ok' when Target :: enum(),Pname :: enum(),Param :: float(). texEnvf(Target,Pname,Param) -> cast(5252, <<Target:?GLenum,Pname:?GLenum,Param:?GLfloat>>). %% @doc glTexEnvi %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexEnvi.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec texEnvi(Target, Pname, Param) -> 'ok' when Target :: enum(),Pname :: enum(),Param :: integer(). texEnvi(Target,Pname,Param) -> cast(5253, <<Target:?GLenum,Pname:?GLenum,Param:?GLint>>). @@ -5980,158 +2541,7 @@ texEnvi(Target,Pname,Param) -> %% , `?GL_ALPHA_SCALE', `?GL_SRC0_RGB', `?GL_SRC1_RGB', `?GL_SRC2_RGB', `?GL_SRC0_ALPHA' %% , `?GL_SRC1_ALPHA', or `?GL_SRC2_ALPHA'. %% -%% If `Pname' is `?GL_TEXTURE_ENV_MODE', then `Params' is (or points to) -%% the symbolic name of a texture function. Six texture functions may be specified: `?GL_ADD' -%% , `?GL_MODULATE', `?GL_DECAL', `?GL_BLEND', `?GL_REPLACE', or `?GL_COMBINE' -%% . -%% -%% The following table shows the correspondence of filtered texture values R t, G t, B t, -%% A t, L t, I t to texture source components. C s and A s are used by the texture functions -%% described below. -%% -%% <table><tbody><tr><td> Texture Base Internal Format </td><td> C s</td><td> A s</td></tr></tbody> -%% <tbody><tr><td>`?GL_ALPHA'</td><td> (0, 0, 0) </td><td> A t</td></tr><tr><td>`?GL_LUMINANCE' -%% </td><td> ( L t, L t, L t ) </td><td> 1 </td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td> -%% <td> ( L t, L t, L t ) </td><td> A t</td></tr><tr><td>`?GL_INTENSITY'</td><td> ( -%% I t, I t, I t ) </td><td> I t</td></tr><tr><td>`?GL_RGB'</td><td> ( R t, G t, B -%% t ) </td><td> 1 </td></tr><tr><td>`?GL_RGBA'</td><td> ( R t, G t, B t ) </td><td> -%% A t</td></tr></tbody></table> -%% -%% A texture function acts on the fragment to be textured using the texture image value -%% that applies to the fragment (see {@link gl:texParameterf/3} ) and produces an RGBA color -%% for that fragment. The following table shows how the RGBA color is produced for each of -%% the first five texture functions that can be chosen. C is a triple of color values (RGB) -%% and A is the associated alpha value. RGBA values extracted from a texture image are in -%% the range [0,1]. The subscript p refers to the color computed from the previous texture -%% stage (or the incoming fragment if processing texture stage 0), the subscript s to the -%% texture source color, the subscript c to the texture environment color, and the subscript -%% v indicates a value produced by the texture function. -%% -%% <table><tbody><tr><td> Texture Base Internal Format </td><td>`?Value'</td><td>`?GL_REPLACE' -%% Function </td><td>`?GL_MODULATE' Function </td><td>`?GL_DECAL' Function </td><td> -%% `?GL_BLEND' Function </td><td>`?GL_ADD' Function </td></tr></tbody><tbody><tr><td> -%% `?GL_ALPHA'</td><td> C v=</td><td> C p</td><td> C p</td><td> undefined </td><td> C p</td> -%% <td> C p</td></tr><tr><td></td><td> A v=</td><td> A s</td><td> A p A s</td><td></td><td> -%% A v=A p A s</td><td> A p A s</td></tr><tr><td>`?GL_LUMINANCE'</td><td> C v=</td><td> -%% C s</td><td> C p C s</td><td> undefined </td><td> C p (1-C s)+C c C s</td><td> C p+C s</td></tr> -%% <tr><td> (or 1) </td><td> A v=</td><td> A p</td><td> A p</td><td></td><td> A p</td><td> A -%% p</td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td> C v=</td><td> C s</td><td> C p C -%% s</td><td> undefined </td><td> C p (1-C s)+C c C s</td><td> C p+C s</td></tr><tr><td> (or 2) </td> -%% <td> A v=</td><td> A s</td><td> A p A s</td><td></td><td> A p A s</td><td> A p A s</td> -%% </tr><tr><td>`?GL_INTENSITY'</td><td> C v=</td><td> C s</td><td> C p C s</td><td> -%% undefined </td><td> C p (1-C s)+C c C s</td><td> C p+C s</td></tr><tr><td></td><td> A v=</td><td> -%% A s</td><td> A p A s</td><td></td><td> A p (1-A s)+A c A s</td><td> A p+A s</td></tr><tr><td>`?GL_RGB' -%% </td><td> C v=</td><td> C s</td><td> C p C s</td><td> C s</td><td> C p (1-C s)+C c C s</td><td> -%% C p+C s</td></tr><tr><td> (or 3) </td><td> A v=</td><td> A p</td><td> A p</td><td> A p</td> -%% <td> A p</td><td> A p</td></tr><tr><td>`?GL_RGBA'</td><td> C v=</td><td> C s</td><td> -%% C p C s</td><td> C p (1-A s)+C s A s</td><td> C p (1-C s)+C c C s</td><td> C p+C s</td></tr><tr><td> -%% (or 4) </td><td> A v=</td><td> A s</td><td> A p A s</td><td> A p</td><td> A p A s</td><td> -%% A p A s</td></tr></tbody></table> -%% -%% If `Pname' is `?GL_TEXTURE_ENV_MODE', and `Params' is `?GL_COMBINE', -%% the form of the texture function depends on the values of `?GL_COMBINE_RGB' and `?GL_COMBINE_ALPHA' -%% . -%% -%% The following describes how the texture sources, as specified by `?GL_SRC0_RGB', `?GL_SRC1_RGB' -%% , `?GL_SRC2_RGB', `?GL_SRC0_ALPHA', `?GL_SRC1_ALPHA', and `?GL_SRC2_ALPHA' -%% , are combined to produce a final texture color. In the following tables, `?GL_SRC0_c' -%% is represented by Arg0, `?GL_SRC1_c' is represented by Arg1, and `?GL_SRC2_c' -%% is represented by Arg2. -%% -%% `?GL_COMBINE_RGB' accepts any of `?GL_REPLACE', `?GL_MODULATE', `?GL_ADD' -%% , `?GL_ADD_SIGNED', `?GL_INTERPOLATE', `?GL_SUBTRACT', `?GL_DOT3_RGB', -%% or `?GL_DOT3_RGBA'. -%% -%% <table><tbody><tr><td>`?GL_COMBINE_RGB'</td><td>` Texture Function '</td></tr></tbody> -%% <tbody><tr><td>`?GL_REPLACE'</td><td> Arg0</td></tr><tr><td>`?GL_MODULATE'</td><td> -%% Arg0×Arg1</td></tr><tr><td>`?GL_ADD'</td><td> Arg0+Arg1</td></tr><tr><td>`?GL_ADD_SIGNED' -%% </td><td> Arg0+Arg1-0.5</td></tr><tr><td>`?GL_INTERPOLATE'</td><td> Arg0×Arg2+Arg1×(1- -%% Arg2)</td> -%% </tr><tr><td>`?GL_SUBTRACT'</td><td> Arg0-Arg1</td></tr><tr><td>`?GL_DOT3_RGB' -%% or `?GL_DOT3_RGBA'</td><td> 4×((((Arg0 r)-0.5)×((Arg1 r)-0.5))+(((Arg0 g)-0.5)×((Arg1 g)-0.5))+(((Arg0 b)-0.5)×((Arg1 b)-0.5)))</td></tr></tbody></table> -%% -%% The scalar results for `?GL_DOT3_RGB' and `?GL_DOT3_RGBA' are placed into each -%% of the 3 (RGB) or 4 (RGBA) components on output. -%% -%% Likewise, `?GL_COMBINE_ALPHA' accepts any of `?GL_REPLACE', `?GL_MODULATE', -%% `?GL_ADD', `?GL_ADD_SIGNED', `?GL_INTERPOLATE', or `?GL_SUBTRACT'. -%% The following table describes how alpha values are combined: -%% -%% <table><tbody><tr><td>`?GL_COMBINE_ALPHA'</td><td>` Texture Function '</td></tr> -%% </tbody><tbody><tr><td>`?GL_REPLACE'</td><td> Arg0</td></tr><tr><td>`?GL_MODULATE' -%% </td><td> Arg0×Arg1</td></tr><tr><td>`?GL_ADD'</td><td> Arg0+Arg1</td></tr><tr><td>`?GL_ADD_SIGNED' -%% </td><td> Arg0+Arg1-0.5</td></tr><tr><td>`?GL_INTERPOLATE'</td><td> Arg0×Arg2+Arg1×(1- -%% Arg2)</td> -%% </tr><tr><td>`?GL_SUBTRACT'</td><td> Arg0-Arg1</td></tr></tbody></table> -%% -%% In the following tables, the value C s represents the color sampled from the currently -%% bound texture, C c represents the constant texture-environment color, C f represents -%% the primary color of the incoming fragment, and C p represents the color computed from -%% the previous texture stage or C f if processing texture stage 0. Likewise, A s, A c, -%% A f, and A p represent the respective alpha values. -%% -%% The following table describes the values assigned to Arg0, Arg1, and Arg2 based upon -%% the RGB sources and operands: -%% -%% <table><tbody><tr><td>`?GL_SRCn_RGB'</td><td>`?GL_OPERANDn_RGB'</td><td>` Argument Value ' -%% </td></tr></tbody><tbody><tr><td>`?GL_TEXTURE'</td><td>`?GL_SRC_COLOR'</td><td>(C -%% s)</td> -%% </tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_COLOR'</td><td> 1-(C s)</td></tr><tr><td></td><td> -%% `?GL_SRC_ALPHA'</td><td>(A s)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'</td> -%% <td> 1-(A s)</td></tr><tr><td>`?GL_TEXTUREn'</td><td>`?GL_SRC_COLOR'</td><td>(C s)</td></tr> -%% <tr><td></td><td>`?GL_ONE_MINUS_SRC_COLOR'</td><td> 1-(C s)</td></tr><tr><td></td><td>`?GL_SRC_ALPHA' -%% </td><td>(A s)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A s)</td></tr><tr> -%% <td>`?GL_CONSTANT'</td><td>`?GL_SRC_COLOR'</td><td>(C c)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_COLOR' -%% </td><td> 1-(C c)</td></tr><tr><td></td><td>`?GL_SRC_ALPHA'</td><td>(A c)</td></tr><tr><td></td> -%% <td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A c)</td></tr><tr><td>`?GL_PRIMARY_COLOR'</td> -%% <td>`?GL_SRC_COLOR'</td><td>(C f)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_COLOR'</td> -%% <td> 1-(C f)</td></tr><tr><td></td><td>`?GL_SRC_ALPHA'</td><td>(A f)</td></tr><tr><td></td><td> -%% `?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A f)</td></tr><tr><td>`?GL_PREVIOUS'</td><td>`?GL_SRC_COLOR' -%% </td><td>(C p)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_COLOR'</td><td> 1-(C p)</td></tr><tr> -%% <td></td><td>`?GL_SRC_ALPHA'</td><td>(A p)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA' -%% </td><td> 1-(A p)</td></tr></tbody></table> -%% -%% For `?GL_TEXTUREn' sources, C s and A s represent the color and alpha, respectively, -%% produced from texture stage n. -%% -%% The follow table describes the values assigned to Arg0, Arg1, and Arg2 based upon -%% the alpha sources and operands: -%% -%% <table><tbody><tr><td>`?GL_SRCn_ALPHA'</td><td>`?GL_OPERANDn_ALPHA'</td><td>` Argument Value ' -%% </td></tr></tbody><tbody><tr><td>`?GL_TEXTURE'</td><td>`?GL_SRC_ALPHA'</td><td>(A -%% s)</td> -%% </tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A s)</td></tr><tr><td>`?GL_TEXTUREn' -%% </td><td>`?GL_SRC_ALPHA'</td><td>(A s)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA' -%% </td><td> 1-(A s)</td></tr><tr><td>`?GL_CONSTANT'</td><td>`?GL_SRC_ALPHA'</td><td>(A -%% c)</td> -%% </tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A c)</td></tr><tr><td>`?GL_PRIMARY_COLOR' -%% </td><td>`?GL_SRC_ALPHA'</td><td>(A f)</td></tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA' -%% </td><td> 1-(A f)</td></tr><tr><td>`?GL_PREVIOUS'</td><td>`?GL_SRC_ALPHA'</td><td>(A -%% p)</td> -%% </tr><tr><td></td><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td> 1-(A p)</td></tr></tbody></table> -%% -%% -%% The RGB and alpha results of the texture function are multipled by the values of `?GL_RGB_SCALE' -%% and `?GL_ALPHA_SCALE', respectively, and clamped to the range [0 1]. -%% -%% If `Pname' is `?GL_TEXTURE_ENV_COLOR', `Params' is a pointer to an array -%% that holds an RGBA color consisting of four values. Integer color components are interpreted -%% linearly such that the most positive integer maps to 1.0, and the most negative integer -%% maps to -1.0. The values are clamped to the range [0,1] when they are specified. C c -%% takes these four values. -%% -%% If `Pname' is `?GL_TEXTURE_LOD_BIAS', the value specified is added to the texture -%% level-of-detail parameter, that selects which mipmap, or mipmaps depending upon the selected -%% `?GL_TEXTURE_MIN_FILTER', will be sampled. -%% -%% `?GL_TEXTURE_ENV_MODE' defaults to `?GL_MODULATE' and `?GL_TEXTURE_ENV_COLOR' -%% defaults to (0, 0, 0, 0). -%% -%% If `Target' is `?GL_POINT_SPRITE' and `Pname' is `?GL_COORD_REPLACE', -%% the boolean value specified is used to either enable or disable point sprite texture coordinate -%% replacement. The default value is `?GL_FALSE'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTexEnv.xml">external</a> documentation. -spec texEnvfv(Target, Pname, Params) -> 'ok' when Target :: enum(),Pname :: enum(),Params :: tuple(). texEnvfv(Target,Pname,Params) -> cast(5254, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint, @@ -6149,80 +2559,7 @@ texEnviv(Target,Pname,Params) -> %% ``gl:getTexEnv'' returns in `Params' selected values of a texture environment that %% was specified with {@link gl:texEnvfv/3} . `Target' specifies a texture environment. %% -%% When `Target' is `?GL_TEXTURE_FILTER_CONTROL', `Pname' must be `?GL_TEXTURE_LOD_BIAS' -%% . When `Target' is `?GL_POINT_SPRITE', `Pname' must be `?GL_COORD_REPLACE' -%% . When `Target' is `?GL_TEXTURE_ENV', `Pname' can be `?GL_TEXTURE_ENV_MODE' -%% , `?GL_TEXTURE_ENV_COLOR', `?GL_COMBINE_RGB', `?GL_COMBINE_ALPHA', `?GL_RGB_SCALE' -%% , `?GL_ALPHA_SCALE', `?GL_SRC0_RGB', `?GL_SRC1_RGB', `?GL_SRC2_RGB', -%% `?GL_SRC0_ALPHA', `?GL_SRC1_ALPHA', or `?GL_SRC2_ALPHA'. -%% -%% `Pname' names a specific texture environment parameter, as follows: -%% -%% `?GL_TEXTURE_ENV_MODE': `Params' returns the single-valued texture environment -%% mode, a symbolic constant. The initial value is `?GL_MODULATE'. -%% -%% `?GL_TEXTURE_ENV_COLOR': `Params' returns four integer or floating-point values -%% that are the texture environment color. Integer values, when requested, are linearly mapped -%% from the internal floating-point representation such that 1.0 maps to the most positive -%% representable integer, and -1.0 maps to the most negative representable integer. The -%% initial value is (0, 0, 0, 0). -%% -%% `?GL_TEXTURE_LOD_BIAS': `Params' returns a single floating-point value that -%% is the texture level-of-detail bias. The initial value is 0. -%% -%% `?GL_COMBINE_RGB': `Params' returns a single symbolic constant value representing -%% the current RGB combine mode. The initial value is `?GL_MODULATE'. -%% -%% `?GL_COMBINE_ALPHA': `Params' returns a single symbolic constant value representing -%% the current alpha combine mode. The initial value is `?GL_MODULATE'. -%% -%% `?GL_SRC0_RGB': `Params' returns a single symbolic constant value representing -%% the texture combiner zero's RGB source. The initial value is `?GL_TEXTURE'. -%% -%% `?GL_SRC1_RGB': `Params' returns a single symbolic constant value representing -%% the texture combiner one's RGB source. The initial value is `?GL_PREVIOUS'. -%% -%% `?GL_SRC2_RGB': `Params' returns a single symbolic constant value representing -%% the texture combiner two's RGB source. The initial value is `?GL_CONSTANT'. -%% -%% `?GL_SRC0_ALPHA': `Params' returns a single symbolic constant value representing -%% the texture combiner zero's alpha source. The initial value is `?GL_TEXTURE'. -%% -%% `?GL_SRC1_ALPHA': `Params' returns a single symbolic constant value representing -%% the texture combiner one's alpha source. The initial value is `?GL_PREVIOUS'. -%% -%% `?GL_SRC2_ALPHA': `Params' returns a single symbolic constant value representing -%% the texture combiner two's alpha source. The initial value is `?GL_CONSTANT'. -%% -%% `?GL_OPERAND0_RGB': `Params' returns a single symbolic constant value representing -%% the texture combiner zero's RGB operand. The initial value is `?GL_SRC_COLOR'. -%% -%% `?GL_OPERAND1_RGB': `Params' returns a single symbolic constant value representing -%% the texture combiner one's RGB operand. The initial value is `?GL_SRC_COLOR'. -%% -%% `?GL_OPERAND2_RGB': `Params' returns a single symbolic constant value representing -%% the texture combiner two's RGB operand. The initial value is `?GL_SRC_ALPHA'. -%% -%% `?GL_OPERAND0_ALPHA': `Params' returns a single symbolic constant value representing -%% the texture combiner zero's alpha operand. The initial value is `?GL_SRC_ALPHA'. -%% -%% `?GL_OPERAND1_ALPHA': `Params' returns a single symbolic constant value representing -%% the texture combiner one's alpha operand. The initial value is `?GL_SRC_ALPHA'. -%% -%% `?GL_OPERAND2_ALPHA': `Params' returns a single symbolic constant value representing -%% the texture combiner two's alpha operand. The initial value is `?GL_SRC_ALPHA'. -%% -%% `?GL_RGB_SCALE': `Params' returns a single floating-point value representing -%% the current RGB texture combiner scaling factor. The initial value is 1.0. -%% -%% `?GL_ALPHA_SCALE': `Params' returns a single floating-point value representing -%% the current alpha texture combiner scaling factor. The initial value is 1.0. -%% -%% `?GL_COORD_REPLACE': `Params' returns a single boolean value representing the -%% current point sprite texture coordinate replacement enable state. The initial value is `?GL_FALSE' -%% . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexEnv.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetTexEnv.xml">external</a> documentation. -spec getTexEnvfv(Target, Pname) -> {float(),float(),float(),float()} when Target :: enum(),Pname :: enum(). getTexEnvfv(Target,Pname) -> call(5256, <<Target:?GLenum,Pname:?GLenum>>). @@ -6240,218 +2577,7 @@ getTexEnviv(Target,Pname) -> %% , `?GL_TEXTURE_2D', `?GL_TEXTURE_1D_ARRAY', `?GL_TEXTURE_2D_ARRAY', `?GL_TEXTURE_RECTANGLE' %% , or `?GL_TEXTURE_3D'. The following symbols are accepted in `Pname' : %% -%% `?GL_TEXTURE_BASE_LEVEL': Specifies the index of the lowest defined mipmap level. -%% This is an integer value. The initial value is 0. -%% -%% -%% -%% `?GL_TEXTURE_BORDER_COLOR': The data in `Params' specifies four values that -%% define the border values that should be used for border texels. If a texel is sampled -%% from the border of the texture, the values of `?GL_TEXTURE_BORDER_COLOR' are interpreted -%% as an RGBA color to match the texture's internal format and substituted for the non-existent -%% texel data. If the texture contains depth components, the first component of `?GL_TEXTURE_BORDER_COLOR' -%% is interpreted as a depth value. The initial value is ( 0.0, 0.0, 0.0, 0.0 ). -%% -%% If the values for `?GL_TEXTURE_BORDER_COLOR' are specified with ``gl:texParameterIiv'' -%% or ``gl:texParameterIuiv'', the values are stored unmodified with an internal data -%% type of integer. If specified with ``gl:texParameteriv'', they are converted to floating -%% point with the following equation: f=2 c+1 2 b-/1. If specified with ``gl:texParameterfv'' -%% , they are stored unmodified as floating-point values. -%% -%% `?GL_TEXTURE_COMPARE_FUNC': Specifies the comparison operator used when `?GL_TEXTURE_COMPARE_MODE' -%% is set to `?GL_COMPARE_REF_TO_TEXTURE'. Permissible values are: <table><tbody><tr><td> -%% ` Texture Comparison Function '</td><td>` Computed result '</td></tr></tbody><tbody> -%% <tr><td>`?GL_LEQUAL'</td><td> result={1.0 0.0 r<=(D t) r>(D t))</td></tr><tr><td>`?GL_GEQUAL'</td><td> -%% result={1.0 0.0 r>=(D t) r<(D t))</td></tr><tr><td>`?GL_LESS'</td><td> result={1.0 0.0 r<(D t) r>=(D t))</td></tr><tr><td>`?GL_GREATER' -%% </td><td> result={1.0 0.0 r>(D t) r<=(D t))</td></tr><tr><td>`?GL_EQUAL'</td><td> result={1.0 0.0 r=(D t) r&ne; -%% (D t))</td></tr><tr><td>`?GL_NOTEQUAL' -%% </td><td> result={1.0 0.0 r&ne;(D t) r=(D t))</td></tr><tr><td>`?GL_ALWAYS'</td><td> result=1.0</td></tr><tr><td> -%% `?GL_NEVER'</td><td> result=0.0</td></tr></tbody></table> where r is the current -%% interpolated texture coordinate, and D t is the depth texture value sampled from the -%% currently bound depth texture. result is assigned to the the red channel. -%% -%% `?GL_TEXTURE_COMPARE_MODE': Specifies the texture comparison mode for currently -%% bound depth textures. That is, a texture whose internal format is `?GL_DEPTH_COMPONENT_*' -%% ; see {@link gl:texImage2D/9} ) Permissible values are: -%% -%% `?GL_COMPARE_REF_TO_TEXTURE': Specifies that the interpolated and clamped r texture -%% coordinate should be compared to the value in the currently bound depth texture. See the -%% discussion of `?GL_TEXTURE_COMPARE_FUNC' for details of how the comparison is evaluated. -%% The result of the comparison is assigned to the red channel. -%% -%% `?GL_NONE': Specifies that the red channel should be assigned the appropriate value -%% from the currently bound depth texture. -%% -%% `?GL_TEXTURE_LOD_BIAS': `Params' specifies a fixed bias value that is to be -%% added to the level-of-detail parameter for the texture before texture sampling. The specified -%% value is added to the shader-supplied bias value (if any) and subsequently clamped into -%% the implementation-defined range [( - bias max)(bias max)], where bias max is the value of the implementation -%% defined constant `?GL_MAX_TEXTURE_LOD_BIAS'. The initial value is 0.0. -%% -%% `?GL_TEXTURE_MIN_FILTER': The texture minifying function is used whenever the level-of-detail -%% function used when sampling from the texture determines that the texture should be minified. -%% There are six defined minifying functions. Two of them use either the nearest texture -%% elements or a weighted average of multiple texture elements to compute the texture value. -%% The other four use mipmaps. -%% -%% A mipmap is an ordered set of arrays representing the same image at progressively lower -%% resolutions. If the texture has dimensions 2 n×2 m, there are max(n m)+1 mipmaps. The first -%% mipmap is the original texture, with dimensions 2 n×2 m. Each subsequent mipmap has -%% dimensions 2(k-1)×2(l-1), where 2 k×2 l are the dimensions of the previous mipmap, until either -%% k=0 or l=0. At that point, subsequent mipmaps have dimension 1×2(l-1) or 2(k-1)×1 until -%% the final mipmap, which has dimension 1×1. To define the mipmaps, call {@link gl:texImage1D/8} -%% , {@link gl:texImage2D/9} , {@link gl:texImage3D/10} , {@link gl:copyTexImage1D/7} , or {@link gl:copyTexImage2D/8} -%% with the `level' argument indicating the order of the mipmaps. Level 0 is the original -%% texture; level max(n m) is the final 1×1 mipmap. -%% -%% `Params' supplies a function for minifying the texture as one of the following: -%% -%% `?GL_NEAREST': Returns the value of the texture element that is nearest (in Manhattan -%% distance) to the specified texture coordinates. -%% -%% `?GL_LINEAR': Returns the weighted average of the four texture elements that are -%% closest to the specified texture coordinates. These can include items wrapped or repeated -%% from other parts of a texture, depending on the values of `?GL_TEXTURE_WRAP_S' and `?GL_TEXTURE_WRAP_T' -%% , and on the exact mapping. -%% -%% `?GL_NEAREST_MIPMAP_NEAREST': Chooses the mipmap that most closely matches the size -%% of the pixel being textured and uses the `?GL_NEAREST' criterion (the texture element -%% closest to the specified texture coordinates) to produce a texture value. -%% -%% `?GL_LINEAR_MIPMAP_NEAREST': Chooses the mipmap that most closely matches the size -%% of the pixel being textured and uses the `?GL_LINEAR' criterion (a weighted average -%% of the four texture elements that are closest to the specified texture coordinates) to -%% produce a texture value. -%% -%% `?GL_NEAREST_MIPMAP_LINEAR': Chooses the two mipmaps that most closely match the -%% size of the pixel being textured and uses the `?GL_NEAREST' criterion (the texture -%% element closest to the specified texture coordinates ) to produce a texture value from -%% each mipmap. The final texture value is a weighted average of those two values. -%% -%% `?GL_LINEAR_MIPMAP_LINEAR': Chooses the two mipmaps that most closely match the -%% size of the pixel being textured and uses the `?GL_LINEAR' criterion (a weighted -%% average of the texture elements that are closest to the specified texture coordinates) -%% to produce a texture value from each mipmap. The final texture value is a weighted average -%% of those two values. -%% -%% As more texture elements are sampled in the minification process, fewer aliasing artifacts -%% will be apparent. While the `?GL_NEAREST' and `?GL_LINEAR' minification functions -%% can be faster than the other four, they sample only one or multiple texture elements to -%% determine the texture value of the pixel being rendered and can produce moire patterns -%% or ragged transitions. The initial value of `?GL_TEXTURE_MIN_FILTER' is `?GL_NEAREST_MIPMAP_LINEAR' -%% . -%% -%% -%% -%% `?GL_TEXTURE_MAG_FILTER': The texture magnification function is used whenever the -%% level-of-detail function used when sampling from the texture determines that the texture -%% should be magified. It sets the texture magnification function to either `?GL_NEAREST' -%% or `?GL_LINEAR' (see below). `?GL_NEAREST' is generally faster than `?GL_LINEAR' -%% , but it can produce textured images with sharper edges because the transition between -%% texture elements is not as smooth. The initial value of `?GL_TEXTURE_MAG_FILTER' is `?GL_LINEAR' -%% . -%% -%% `?GL_NEAREST': Returns the value of the texture element that is nearest (in Manhattan -%% distance) to the specified texture coordinates. -%% -%% `?GL_LINEAR': Returns the weighted average of the texture elements that are closest -%% to the specified texture coordinates. These can include items wrapped or repeated from -%% other parts of a texture, depending on the values of `?GL_TEXTURE_WRAP_S' and `?GL_TEXTURE_WRAP_T' -%% , and on the exact mapping. -%% -%% -%% -%% `?GL_TEXTURE_MIN_LOD': Sets the minimum level-of-detail parameter. This floating-point -%% value limits the selection of highest resolution mipmap (lowest mipmap level). The initial -%% value is -1000. -%% -%% -%% -%% `?GL_TEXTURE_MAX_LOD': Sets the maximum level-of-detail parameter. This floating-point -%% value limits the selection of the lowest resolution mipmap (highest mipmap level). The -%% initial value is 1000. -%% -%% -%% -%% `?GL_TEXTURE_MAX_LEVEL': Sets the index of the highest defined mipmap level. This -%% is an integer value. The initial value is 1000. -%% -%% -%% -%% `?GL_TEXTURE_SWIZZLE_R': Sets the swizzle that will be applied to the r component -%% of a texel before it is returned to the shader. Valid values for `Param' are `?GL_RED' -%% , `?GL_GREEN', `?GL_BLUE', `?GL_ALPHA', `?GL_ZERO' and `?GL_ONE'. -%% If `?GL_TEXTURE_SWIZZLE_R' is `?GL_RED', the value for r will be taken from -%% the first channel of the fetched texel. If `?GL_TEXTURE_SWIZZLE_R' is `?GL_GREEN' -%% , the value for r will be taken from the second channel of the fetched texel. If `?GL_TEXTURE_SWIZZLE_R' -%% is `?GL_BLUE', the value for r will be taken from the third channel of the fetched -%% texel. If `?GL_TEXTURE_SWIZZLE_R' is `?GL_ALPHA', the value for r will be taken -%% from the fourth channel of the fetched texel. If `?GL_TEXTURE_SWIZZLE_R' is `?GL_ZERO' -%% , the value for r will be subtituted with 0.0. If `?GL_TEXTURE_SWIZZLE_R' is `?GL_ONE' -%% , the value for r will be subtituted with 1.0. The initial value is `?GL_RED'. -%% -%% -%% -%% `?GL_TEXTURE_SWIZZLE_G': Sets the swizzle that will be applied to the g component -%% of a texel before it is returned to the shader. Valid values for `Param' and their -%% effects are similar to those of `?GL_TEXTURE_SWIZZLE_R'. The initial value is `?GL_GREEN' -%% . -%% -%% -%% -%% `?GL_TEXTURE_SWIZZLE_B': Sets the swizzle that will be applied to the b component -%% of a texel before it is returned to the shader. Valid values for `Param' and their -%% effects are similar to those of `?GL_TEXTURE_SWIZZLE_R'. The initial value is `?GL_BLUE' -%% . -%% -%% -%% -%% `?GL_TEXTURE_SWIZZLE_A': Sets the swizzle that will be applied to the a component -%% of a texel before it is returned to the shader. Valid values for `Param' and their -%% effects are similar to those of `?GL_TEXTURE_SWIZZLE_R'. The initial value is `?GL_ALPHA' -%% . -%% -%% -%% -%% `?GL_TEXTURE_SWIZZLE_RGBA': Sets the swizzles that will be applied to the r, g, -%% b, and a components of a texel before they are returned to the shader. Valid values for `Params' -%% and their effects are similar to those of `?GL_TEXTURE_SWIZZLE_R', except that all -%% channels are specified simultaneously. Setting the value of `?GL_TEXTURE_SWIZZLE_RGBA' -%% is equivalent (assuming no errors are generated) to setting the parameters of each of `?GL_TEXTURE_SWIZZLE_R' -%% , `?GL_TEXTURE_SWIZZLE_G', `?GL_TEXTURE_SWIZZLE_B', and `?GL_TEXTURE_SWIZZLE_A' -%% successively. -%% -%% -%% -%% `?GL_TEXTURE_WRAP_S': Sets the wrap parameter for texture coordinate s to either `?GL_CLAMP_TO_EDGE' -%% , `?GL_CLAMP_TO_BORDER', `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. `?GL_CLAMP_TO_EDGE' -%% causes s coordinates to be clamped to the range [(1 2/N) 1-(1 2/N)], where N is the size of the texture -%% in the direction of clamping. `?GL_CLAMP_TO_BORDER' evaluates s coordinates in a -%% similar manner to `?GL_CLAMP_TO_EDGE'. However, in cases where clamping would have -%% occurred in `?GL_CLAMP_TO_EDGE' mode, the fetched texel data is substituted with -%% the values specified by `?GL_TEXTURE_BORDER_COLOR'. `?GL_REPEAT' causes the -%% integer part of the s coordinate to be ignored; the GL uses only the fractional part, -%% thereby creating a repeating pattern. `?GL_MIRRORED_REPEAT' causes the s coordinate -%% to be set to the fractional part of the texture coordinate if the integer part of s -%% is even; if the integer part of s is odd, then the s texture coordinate is set to 1- -%% frac(s), where frac(s) represents the fractional part of s. Initially, `?GL_TEXTURE_WRAP_S' -%% is set to `?GL_REPEAT'. -%% -%% -%% -%% `?GL_TEXTURE_WRAP_T': Sets the wrap parameter for texture coordinate t to either `?GL_CLAMP_TO_EDGE' -%% , `?GL_CLAMP_TO_BORDER', `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. See the -%% discussion under `?GL_TEXTURE_WRAP_S'. Initially, `?GL_TEXTURE_WRAP_T' is set -%% to `?GL_REPEAT'. -%% -%% -%% -%% `?GL_TEXTURE_WRAP_R': Sets the wrap parameter for texture coordinate r to either `?GL_CLAMP_TO_EDGE' -%% , `?GL_CLAMP_TO_BORDER', `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. See the -%% discussion under `?GL_TEXTURE_WRAP_S'. Initially, `?GL_TEXTURE_WRAP_R' is set -%% to `?GL_REPEAT'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexParameter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexParameter.xhtml">external</a> documentation. -spec texParameterf(Target, Pname, Param) -> 'ok' when Target :: enum(),Pname :: enum(),Param :: float(). texParameterf(Target,Pname,Param) -> cast(5258, <<Target:?GLenum,Pname:?GLenum,Param:?GLfloat>>). @@ -6486,70 +2612,7 @@ texParameteriv(Target,Pname,Params) -> %% rectangle, cube-mapped or cube-mapped array texturing, respectively. `Pname' accepts %% the same symbols as {@link gl:texParameterf/3} , with the same interpretations: %% -%% `?GL_TEXTURE_MAG_FILTER': Returns the single-valued texture magnification filter, -%% a symbolic constant. The initial value is `?GL_LINEAR'. -%% -%% `?GL_TEXTURE_MIN_FILTER': Returns the single-valued texture minification filter, -%% a symbolic constant. The initial value is `?GL_NEAREST_MIPMAP_LINEAR'. -%% -%% `?GL_TEXTURE_MIN_LOD': Returns the single-valued texture minimum level-of-detail -%% value. The initial value is -1000. -%% -%% `?GL_TEXTURE_MAX_LOD': Returns the single-valued texture maximum level-of-detail -%% value. The initial value is 1000. -%% -%% `?GL_TEXTURE_BASE_LEVEL': Returns the single-valued base texture mipmap level. The -%% initial value is 0. -%% -%% `?GL_TEXTURE_MAX_LEVEL': Returns the single-valued maximum texture mipmap array -%% level. The initial value is 1000. -%% -%% `?GL_TEXTURE_SWIZZLE_R': Returns the red component swizzle. The initial value is `?GL_RED' -%% . -%% -%% `?GL_TEXTURE_SWIZZLE_G': Returns the green component swizzle. The initial value is `?GL_GREEN' -%% . -%% -%% `?GL_TEXTURE_SWIZZLE_B': Returns the blue component swizzle. The initial value is `?GL_BLUE' -%% . -%% -%% `?GL_TEXTURE_SWIZZLE_A': Returns the alpha component swizzle. The initial value is `?GL_ALPHA' -%% . -%% -%% `?GL_TEXTURE_SWIZZLE_RGBA': Returns the component swizzle for all channels in a -%% single query. -%% -%% `?GL_TEXTURE_WRAP_S': Returns the single-valued wrapping function for texture coordinate -%% s, a symbolic constant. The initial value is `?GL_REPEAT'. -%% -%% `?GL_TEXTURE_WRAP_T': Returns the single-valued wrapping function for texture coordinate -%% t, a symbolic constant. The initial value is `?GL_REPEAT'. -%% -%% `?GL_TEXTURE_WRAP_R': Returns the single-valued wrapping function for texture coordinate -%% r, a symbolic constant. The initial value is `?GL_REPEAT'. -%% -%% `?GL_TEXTURE_BORDER_COLOR': Returns four integer or floating-point numbers that -%% comprise the RGBA color of the texture border. Floating-point values are returned in the -%% range [0 1]. Integer values are returned as a linear mapping of the internal floating-point -%% representation such that 1.0 maps to the most positive representable integer and -1.0 -%% maps to the most negative representable integer. The initial value is (0, 0, 0, 0). -%% -%% `?GL_TEXTURE_COMPARE_MODE': Returns a single-valued texture comparison mode, a symbolic -%% constant. The initial value is `?GL_NONE'. See {@link gl:texParameterf/3} . -%% -%% `?GL_TEXTURE_COMPARE_FUNC': Returns a single-valued texture comparison function, -%% a symbolic constant. The initial value is `?GL_LEQUAL'. See {@link gl:texParameterf/3} . -%% -%% -%% In addition to the parameters that may be set with {@link gl:texParameterf/3} , ``gl:getTexParameter'' -%% accepts the following read-only parameters: -%% -%% `?GL_TEXTURE_IMMUTABLE_FORMAT': Returns non-zero if the texture has an immutable -%% format. Textures become immutable if their storage is specified with {@link gl:texStorage1D/4} -%% , {@link gl:texStorage2D/5} or {@link gl:texStorage3D/6} . The initial value is `?GL_FALSE' -%% . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexParameter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetTexParameter.xhtml">external</a> documentation. -spec getTexParameterfv(Target, Pname) -> {float(),float(),float(),float()} when Target :: enum(),Pname :: enum(). getTexParameterfv(Target,Pname) -> call(5262, <<Target:?GLenum,Pname:?GLenum>>). @@ -6570,67 +2633,7 @@ getTexParameteriv(Target,Pname) -> %% , `?GL_TEXTURE_CUBE_MAP_POSITIVE_Z', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Z', or `?GL_PROXY_TEXTURE_CUBE_MAP' %% . %% -%% `?GL_MAX_TEXTURE_SIZE', and `?GL_MAX_3D_TEXTURE_SIZE' are not really descriptive -%% enough. It has to report the largest square texture image that can be accommodated with -%% mipmaps and borders, but a long skinny texture, or a texture without mipmaps and borders, -%% may easily fit in texture memory. The proxy targets allow the user to more accurately -%% query whether the GL can accommodate a texture of a given configuration. If the texture -%% cannot be accommodated, the texture state variables, which may be queried with ``gl:getTexLevelParameter'' -%% , are set to 0. If the texture can be accommodated, the texture state values will be set -%% as they would be set for a non-proxy target. -%% -%% `Pname' specifies the texture parameter whose value or values will be returned. -%% -%% The accepted parameter names are as follows: -%% -%% `?GL_TEXTURE_WIDTH': `Params' returns a single value, the width of the texture -%% image. This value includes the border of the texture image. The initial value is 0. -%% -%% `?GL_TEXTURE_HEIGHT': `Params' returns a single value, the height of the texture -%% image. This value includes the border of the texture image. The initial value is 0. -%% -%% `?GL_TEXTURE_DEPTH': `Params' returns a single value, the depth of the texture -%% image. This value includes the border of the texture image. The initial value is 0. -%% -%% `?GL_TEXTURE_INTERNAL_FORMAT': `Params' returns a single value, the internal -%% format of the texture image. -%% -%% `?GL_TEXTURE_RED_TYPE', -%% -%% `?GL_TEXTURE_GREEN_TYPE', -%% -%% `?GL_TEXTURE_BLUE_TYPE', -%% -%% `?GL_TEXTURE_ALPHA_TYPE', -%% -%% `?GL_TEXTURE_DEPTH_TYPE': The data type used to store the component. The types `?GL_NONE' -%% , `?GL_SIGNED_NORMALIZED', `?GL_UNSIGNED_NORMALIZED', `?GL_FLOAT', `?GL_INT' -%% , and `?GL_UNSIGNED_INT' may be returned to indicate signed normalized fixed-point, -%% unsigned normalized fixed-point, floating-point, integer unnormalized, and unsigned integer -%% unnormalized components, respectively. -%% -%% `?GL_TEXTURE_RED_SIZE', -%% -%% `?GL_TEXTURE_GREEN_SIZE', -%% -%% `?GL_TEXTURE_BLUE_SIZE', -%% -%% `?GL_TEXTURE_ALPHA_SIZE', -%% -%% `?GL_TEXTURE_DEPTH_SIZE': The internal storage resolution of an individual component. -%% The resolution chosen by the GL will be a close match for the resolution requested by -%% the user with the component argument of {@link gl:texImage1D/8} , {@link gl:texImage2D/9} , {@link gl:texImage3D/10} -%% , {@link gl:copyTexImage1D/7} , and {@link gl:copyTexImage2D/8} . The initial value is 0. -%% -%% `?GL_TEXTURE_COMPRESSED': `Params' returns a single boolean value indicating -%% if the texture image is stored in a compressed internal format. The initiali value is `?GL_FALSE' -%% . -%% -%% `?GL_TEXTURE_COMPRESSED_IMAGE_SIZE': `Params' returns a single integer value, -%% the number of unsigned bytes of the compressed texture image that would be returned from {@link gl:getCompressedTexImage/3} -%% . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexLevelParameter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetTexLevelParameter.xhtml">external</a> documentation. -spec getTexLevelParameterfv(Target, Level, Pname) -> {float()} when Target :: enum(),Level :: integer(),Pname :: enum(). getTexLevelParameterfv(Target,Level,Pname) -> call(5264, <<Target:?GLenum,Level:?GLint,Pname:?GLenum>>). @@ -6647,107 +2650,7 @@ getTexLevelParameteriv(Target,Level,Pname) -> %% which texturing is enabled. To enable and disable one-dimensional texturing, call {@link gl:enable/1} %% and {@link gl:enable/1} with argument `?GL_TEXTURE_1D'. %% -%% Texture images are defined with ``gl:texImage1D''. The arguments describe the parameters -%% of the texture image, such as width, width of the border, level-of-detail number (see {@link gl:texParameterf/3} -%% ), and the internal resolution and format used to store the image. The last three arguments -%% describe how the image is represented in memory. -%% -%% If `Target' is `?GL_PROXY_TEXTURE_1D', no data is read from `Data' , but -%% all of the texture image state is recalculated, checked for consistency, and checked against -%% the implementation's capabilities. If the implementation cannot handle a texture of the -%% requested texture size, it sets all of the image state to 0, but does not generate an -%% error (see {@link gl:getError/0} ). To query for an entire mipmap array, use an image array -%% level greater than or equal to 1. -%% -%% If `Target' is `?GL_TEXTURE_1D', data is read from `Data' as a sequence -%% of signed or unsigned bytes, shorts, or longs, or single-precision floating-point values, -%% depending on `Type' . These values are grouped into sets of one, two, three, or four -%% values, depending on `Format' , to form elements. Each data byte is treated as eight -%% 1-bit elements, with bit ordering determined by `?GL_UNPACK_LSB_FIRST' (see {@link gl:pixelStoref/2} -%% ). -%% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated -%% as a byte offset into the buffer object's data store. -%% -%% The first element corresponds to the left end of the texture array. Subsequent elements -%% progress left-to-right through the remaining texels in the texture array. The final element -%% corresponds to the right end of the texture array. -%% -%% `Format' determines the composition of each element in `Data' . It can assume -%% one of these symbolic values: -%% -%% `?GL_RED': Each element is a single red component. The GL converts it to floating -%% point and assembles it into an RGBA element by attaching 0 for green and blue, and 1 for -%% alpha. Each component is then multiplied by the signed scale factor `?GL_c_SCALE', -%% added to the signed bias `?GL_c_BIAS', and clamped to the range [0,1]. -%% -%% `?GL_RG': Each element is a single red/green double The GL converts it to floating -%% point and assembles it into an RGBA element by attaching 0 for blue, and 1 for alpha. -%% Each component is then multiplied by the signed scale factor `?GL_c_SCALE', added -%% to the signed bias `?GL_c_BIAS', and clamped to the range [0,1]. -%% -%% `?GL_RGB' -%% -%% `?GL_BGR': Each element is an RGB triple. The GL converts it to floating point and -%% assembles it into an RGBA element by attaching 1 for alpha. Each component is then multiplied -%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS', -%% and clamped to the range [0,1]. -%% -%% `?GL_RGBA' -%% -%% `?GL_BGRA': Each element contains all four components. Each component is multiplied -%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS', -%% and clamped to the range [0,1]. -%% -%% `?GL_DEPTH_COMPONENT': Each element is a single depth value. The GL converts it -%% to floating point, multiplies by the signed scale factor `?GL_DEPTH_SCALE', adds -%% the signed bias `?GL_DEPTH_BIAS', and clamps to the range [0,1]. -%% -%% If an application wants to store the texture at a certain resolution or in a certain -%% format, it can request the resolution and format with `InternalFormat' . The GL will -%% choose an internal representation that closely approximates that requested by `InternalFormat' -%% , but it may not match exactly. (The representations specified by `?GL_RED', `?GL_RG' -%% , `?GL_RGB' and `?GL_RGBA' must match exactly.) -%% -%% `InternalFormat' may be one of the base internal formats shown in Table 1, below -%% -%% `InternalFormat' may also be one of the sized internal formats shown in Table 2, -%% below -%% -%% Finally, `InternalFormat' may also be one of the generic or compressed compressed -%% texture formats shown in Table 3 below -%% -%% If the `InternalFormat' parameter is one of the generic compressed formats, `?GL_COMPRESSED_RED' -%% , `?GL_COMPRESSED_RG', `?GL_COMPRESSED_RGB', or `?GL_COMPRESSED_RGBA', -%% the GL will replace the internal format with the symbolic constant for a specific internal -%% format and compress the texture before storage. If no corresponding internal format is -%% available, or the GL can not compress that image for any reason, the internal format is -%% instead replaced with a corresponding base internal format. -%% -%% If the `InternalFormat' parameter is `?GL_SRGB', `?GL_SRGB8', `?GL_SRGB_ALPHA' -%% or `?GL_SRGB8_ALPHA8', the texture is treated as if the red, green, or blue components -%% are encoded in the sRGB color space. Any alpha component is left unchanged. The conversion -%% from the sRGB encoded component c s to a linear component c l is: -%% -%% c l={ c s/12.92if c s&le; 0.04045( c s+0.055/1.055) 2.4if c s> 0.04045 -%% -%% Assume c s is the sRGB component in the range [0,1]. -%% -%% Use the `?GL_PROXY_TEXTURE_1D' target to try out a resolution and format. The implementation -%% will update and recompute its best match for the requested storage resolution and format. -%% To then query this state, call {@link gl:getTexLevelParameterfv/3} . If the texture cannot -%% be accommodated, texture state is set to 0. -%% -%% A one-component texture image uses only the red component of the RGBA color from `Data' -%% . A two-component image uses the R and A values. A three-component image uses the R, G, -%% and B values. A four-component image uses all of the RGBA components. -%% -%% Image-based shadowing can be enabled by comparing texture r coordinates to depth texture -%% values to generate a boolean result. See {@link gl:texParameterf/3} for details on texture -%% comparison. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage1D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage1D.xhtml">external</a> documentation. -spec texImage1D(Target, Level, InternalFormat, Width, Border, Format, Type, Pixels) -> 'ok' when Target :: enum(),Level :: integer(),InternalFormat :: integer(),Width :: integer(),Border :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem(). texImage1D(Target,Level,InternalFormat,Width,Border,Format,Type,Pixels) when is_integer(Pixels) -> cast(5266, <<Target:?GLenum,Level:?GLint,InternalFormat:?GLint,Width:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>); @@ -6759,117 +2662,7 @@ texImage1D(Target,Level,InternalFormat,Width,Border,Format,Type,Pixels) -> %% %% Texturing allows elements of an image array to be read by shaders. %% -%% To define texture images, call ``gl:texImage2D''. The arguments describe the parameters -%% of the texture image, such as height, width, width of the border, level-of-detail number -%% (see {@link gl:texParameterf/3} ), and number of color components provided. The last three -%% arguments describe how the image is represented in memory. -%% -%% If `Target' is `?GL_PROXY_TEXTURE_2D', `?GL_PROXY_TEXTURE_1D_ARRAY', `?GL_PROXY_TEXTURE_CUBE_MAP' -%% , or `?GL_PROXY_TEXTURE_RECTANGLE', no data is read from `Data' , but all of -%% the texture image state is recalculated, checked for consistency, and checked against -%% the implementation's capabilities. If the implementation cannot handle a texture of the -%% requested texture size, it sets all of the image state to 0, but does not generate an -%% error (see {@link gl:getError/0} ). To query for an entire mipmap array, use an image array -%% level greater than or equal to 1. -%% -%% If `Target' is `?GL_TEXTURE_2D', `?GL_TEXTURE_RECTANGLE' or one of the `?GL_TEXTURE_CUBE_MAP' -%% targets, data is read from `Data' as a sequence of signed or unsigned bytes, shorts, -%% or longs, or single-precision floating-point values, depending on `Type' . These values -%% are grouped into sets of one, two, three, or four values, depending on `Format' , -%% to form elements. Each data byte is treated as eight 1-bit elements, with bit ordering -%% determined by `?GL_UNPACK_LSB_FIRST' (see {@link gl:pixelStoref/2} ). -%% -%% If `Target' is `?GL_TEXTURE_1D_ARRAY', data is interpreted as an array of one-dimensional -%% images. -%% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated -%% as a byte offset into the buffer object's data store. -%% -%% The first element corresponds to the lower left corner of the texture image. Subsequent -%% elements progress left-to-right through the remaining texels in the lowest row of the -%% texture image, and then in successively higher rows of the texture image. The final element -%% corresponds to the upper right corner of the texture image. -%% -%% `Format' determines the composition of each element in `Data' . It can assume -%% one of these symbolic values: -%% -%% `?GL_RED': Each element is a single red component. The GL converts it to floating -%% point and assembles it into an RGBA element by attaching 0 for green and blue, and 1 for -%% alpha. Each component is then multiplied by the signed scale factor `?GL_c_SCALE', -%% added to the signed bias `?GL_c_BIAS', and clamped to the range [0,1]. -%% -%% `?GL_RG': Each element is a red/green double. The GL converts it to floating point -%% and assembles it into an RGBA element by attaching 0 for blue, and 1 for alpha. Each component -%% is then multiplied by the signed scale factor `?GL_c_SCALE', added to the signed -%% bias `?GL_c_BIAS', and clamped to the range [0,1]. -%% -%% `?GL_RGB' -%% -%% `?GL_BGR': Each element is an RGB triple. The GL converts it to floating point and -%% assembles it into an RGBA element by attaching 1 for alpha. Each component is then multiplied -%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS', -%% and clamped to the range [0,1]. -%% -%% `?GL_RGBA' -%% -%% `?GL_BGRA': Each element contains all four components. Each component is multiplied -%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS', -%% and clamped to the range [0,1]. -%% -%% `?GL_DEPTH_COMPONENT': Each element is a single depth value. The GL converts it -%% to floating point, multiplies by the signed scale factor `?GL_DEPTH_SCALE', adds -%% the signed bias `?GL_DEPTH_BIAS', and clamps to the range [0,1]. -%% -%% `?GL_DEPTH_STENCIL': Each element is a pair of depth and stencil values. The depth -%% component of the pair is interpreted as in `?GL_DEPTH_COMPONENT'. The stencil component -%% is interpreted based on specified the depth + stencil internal format. -%% -%% If an application wants to store the texture at a certain resolution or in a certain -%% format, it can request the resolution and format with `InternalFormat' . The GL will -%% choose an internal representation that closely approximates that requested by `InternalFormat' -%% , but it may not match exactly. (The representations specified by `?GL_RED', `?GL_RG' -%% , `?GL_RGB', and `?GL_RGBA' must match exactly.) -%% -%% `InternalFormat' may be one of the base internal formats shown in Table 1, below -%% -%% `InternalFormat' may also be one of the sized internal formats shown in Table 2, -%% below -%% -%% Finally, `InternalFormat' may also be one of the generic or compressed compressed -%% texture formats shown in Table 3 below -%% -%% If the `InternalFormat' parameter is one of the generic compressed formats, `?GL_COMPRESSED_RED' -%% , `?GL_COMPRESSED_RG', `?GL_COMPRESSED_RGB', or `?GL_COMPRESSED_RGBA', -%% the GL will replace the internal format with the symbolic constant for a specific internal -%% format and compress the texture before storage. If no corresponding internal format is -%% available, or the GL can not compress that image for any reason, the internal format is -%% instead replaced with a corresponding base internal format. -%% -%% If the `InternalFormat' parameter is `?GL_SRGB', `?GL_SRGB8', `?GL_SRGB_ALPHA' -%% , or `?GL_SRGB8_ALPHA8', the texture is treated as if the red, green, or blue components -%% are encoded in the sRGB color space. Any alpha component is left unchanged. The conversion -%% from the sRGB encoded component c s to a linear component c l is: -%% -%% c l={ c s/12.92if c s&le; 0.04045( c s+0.055/1.055) 2.4if c s> 0.04045 -%% -%% Assume c s is the sRGB component in the range [0,1]. -%% -%% Use the `?GL_PROXY_TEXTURE_2D', `?GL_PROXY_TEXTURE_1D_ARRAY', `?GL_PROXY_TEXTURE_RECTANGLE' -%% , or `?GL_PROXY_TEXTURE_CUBE_MAP' target to try out a resolution and format. The -%% implementation will update and recompute its best match for the requested storage resolution -%% and format. To then query this state, call {@link gl:getTexLevelParameterfv/3} . If the texture -%% cannot be accommodated, texture state is set to 0. -%% -%% A one-component texture image uses only the red component of the RGBA color extracted -%% from `Data' . A two-component image uses the R and G values. A three-component image -%% uses the R, G, and B values. A four-component image uses all of the RGBA components. -%% -%% Image-based shadowing can be enabled by comparing texture r coordinates to depth texture -%% values to generate a boolean result. See {@link gl:texParameterf/3} for details on texture -%% comparison. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml">external</a> documentation. -spec texImage2D(Target, Level, InternalFormat, Width, Height, Border, Format, Type, Pixels) -> 'ok' when Target :: enum(),Level :: integer(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Border :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem(). texImage2D(Target,Level,InternalFormat,Width,Height,Border,Format,Type,Pixels) when is_integer(Pixels) -> cast(5268, <<Target:?GLenum,Level:?GLint,InternalFormat:?GLint,Width:?GLsizei,Height:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>); @@ -6888,33 +2681,7 @@ texImage2D(Target,Level,InternalFormat,Width,Height,Border,Format,Type,Pixels) - %% array. See the reference page for {@link gl:texImage1D/8} for a description of the acceptable %% values for the `Format' and `Type' parameters, respectively. %% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a texture image is requested, `Img' is treated -%% as a byte offset into the buffer object's data store. -%% -%% To understand the operation of ``gl:getTexImage'', consider the selected internal four-component -%% texture image to be an RGBA color buffer the size of the image. The semantics of ``gl:getTexImage'' -%% are then identical to those of {@link gl:readPixels/7} , with the exception that no pixel -%% transfer operations are performed, when called with the same `Format' and `Type' , -%% with `x' and `y' set to 0, `width' set to the width of the texture image -%% and `height' set to 1 for 1D images, or to the height of the texture image for 2D -%% images. -%% -%% If the selected texture image does not contain four components, the following mappings -%% are applied. Single-component textures are treated as RGBA buffers with red set to the -%% single-component value, green set to 0, blue set to 0, and alpha set to 1. Two-component -%% textures are treated as RGBA buffers with red set to the value of component zero, alpha -%% set to the value of component one, and green and blue set to 0. Finally, three-component -%% textures are treated as RGBA buffers with red set to component zero, green set to component -%% one, blue set to component two, and alpha set to 1. -%% -%% To determine the required size of `Img' , use {@link gl:getTexLevelParameterfv/3} to -%% determine the dimensions of the internal texture image, then scale the required number -%% of pixels by the storage required for each pixel, based on `Format' and `Type' . -%% Be sure to take the pixel storage parameters into account, especially `?GL_PACK_ALIGNMENT' -%% . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexImage.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetTexImage.xhtml">external</a> documentation. -spec getTexImage(Target, Level, Format, Type, Pixels) -> 'ok' when Target :: enum(),Level :: integer(),Format :: enum(),Type :: enum(),Pixels :: mem(). getTexImage(Target,Level,Format,Type,Pixels) -> send_bin(Pixels), @@ -6926,13 +2693,7 @@ getTexImage(Target,Level,Format,Type,Pixels) -> %% that the names form a contiguous set of integers; however, it is guaranteed that none %% of the returned names was in use immediately before the call to ``gl:genTextures''. %% -%% The generated textures have no dimensionality; they assume the dimensionality of the -%% texture target to which they are first bound (see {@link gl:bindTexture/2} ). -%% -%% Texture names returned by a call to ``gl:genTextures'' are not returned by subsequent -%% calls, unless they are first deleted with {@link gl:deleteTextures/1} . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenTextures.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenTextures.xhtml">external</a> documentation. -spec genTextures(N) -> [integer()] when N :: integer(). genTextures(N) -> call(5271, <<N:?GLsizei>>). @@ -6944,10 +2705,7 @@ genTextures(N) -> %% for reuse (for example by {@link gl:genTextures/1} ). If a texture that is currently bound %% is deleted, the binding reverts to 0 (the default texture). %% -%% ``gl:deleteTextures'' silently ignores 0's and names that do not correspond to existing -%% textures. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteTextures.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteTextures.xhtml">external</a> documentation. -spec deleteTextures(Textures) -> 'ok' when Textures :: [integer()]. deleteTextures(Textures) -> TexturesLen = length(Textures), @@ -6964,43 +2722,7 @@ deleteTextures(Textures) -> %% When a texture is bound to a target, the previous binding for that target is automatically %% broken. %% -%% Texture names are unsigned integers. The value zero is reserved to represent the default -%% texture for each texture target. Texture names and the corresponding texture contents -%% are local to the shared object space of the current GL rendering context; two rendering -%% contexts share texture names only if they explicitly enable sharing between contexts through -%% the appropriate GL windows interfaces functions. -%% -%% You must use {@link gl:genTextures/1} to generate a set of new texture names. -%% -%% When a texture is first bound, it assumes the specified target: A texture first bound -%% to `?GL_TEXTURE_1D' becomes one-dimensional texture, a texture first bound to `?GL_TEXTURE_2D' -%% becomes two-dimensional texture, a texture first bound to `?GL_TEXTURE_3D' becomes -%% three-dimensional texture, a texture first bound to `?GL_TEXTURE_1D_ARRAY' becomes -%% one-dimensional array texture, a texture first bound to `?GL_TEXTURE_2D_ARRAY' becomes -%% two-dimensional arary texture, a texture first bound to `?GL_TEXTURE_RECTANGLE' becomes -%% rectangle texture, a, texture first bound to `?GL_TEXTURE_CUBE_MAP' becomes a cube-mapped -%% texture, a texture first bound to `?GL_TEXTURE_2D_MULTISAMPLE' becomes a two-dimensional -%% multisampled texture, and a texture first bound to `?GL_TEXTURE_2D_MULTISAMPLE_ARRAY' -%% becomes a two-dimensional multisampled array texture. The state of a one-dimensional texture -%% immediately after it is first bound is equivalent to the state of the default `?GL_TEXTURE_1D' -%% at GL initialization, and similarly for the other texture types. -%% -%% While a texture is bound, GL operations on the target to which it is bound affect the -%% bound texture, and queries of the target to which it is bound return state from the bound -%% texture. In effect, the texture targets become aliases for the textures currently bound -%% to them, and the texture name zero refers to the default textures that were bound to them -%% at initialization. -%% -%% A texture binding created with ``gl:bindTexture'' remains active until a different -%% texture is bound to the same target, or until the bound texture is deleted with {@link gl:deleteTextures/1} -%% . -%% -%% Once created, a named texture may be re-bound to its same original target as often as -%% needed. It is usually much faster to use ``gl:bindTexture'' to bind an existing named -%% texture to one of the texture targets than it is to reload the texture image using {@link gl:texImage1D/8} -%% , {@link gl:texImage2D/9} , {@link gl:texImage3D/10} or another similar function. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindTexture.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindTexture.xhtml">external</a> documentation. -spec bindTexture(Target, Texture) -> 'ok' when Target :: enum(),Texture :: integer(). bindTexture(Target,Texture) -> cast(5273, <<Target:?GLenum,Texture:?GLuint>>). @@ -7010,26 +2732,7 @@ bindTexture(Target,Texture) -> %% ``gl:prioritizeTextures'' assigns the `N' texture priorities given in `Priorities' %% to the `N' textures named in `Textures' . %% -%% The GL establishes a ``working set'' of textures that are resident in texture memory. -%% These textures may be bound to a texture target much more efficiently than textures that -%% are not resident. By specifying a priority for each texture, ``gl:prioritizeTextures'' -%% allows applications to guide the GL implementation in determining which textures should -%% be resident. -%% -%% The priorities given in `Priorities' are clamped to the range [0 1] before they are -%% assigned. 0 indicates the lowest priority; textures with priority 0 are least likely to -%% be resident. 1 indicates the highest priority; textures with priority 1 are most likely -%% to be resident. However, textures are not guaranteed to be resident until they are used. -%% -%% ``gl:prioritizeTextures'' silently ignores attempts to prioritize texture 0 or any texture -%% name that does not correspond to an existing texture. -%% -%% ``gl:prioritizeTextures'' does not require that any of the textures named by `Textures' -%% be bound to a texture target. {@link gl:texParameterf/3} may also be used to set a texture's -%% priority, but only if the texture is currently bound. This is the only way to set the -%% priority of a default texture. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPrioritizeTextures.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPrioritizeTextures.xml">external</a> documentation. -spec prioritizeTextures(Textures, Priorities) -> 'ok' when Textures :: [integer()],Priorities :: [clamp()]. prioritizeTextures(Textures,Priorities) -> TexturesLen = length(Textures), @@ -7044,20 +2747,7 @@ prioritizeTextures(Textures,Priorities) -> %% textures can be bound to a texture target much more efficiently than textures that are %% not resident. %% -%% ``gl:areTexturesResident'' queries the texture residence status of the `N' textures -%% named by the elements of `Textures' . If all the named textures are resident, ``gl:areTexturesResident'' -%% returns `?GL_TRUE', and the contents of `Residences' are undisturbed. If not -%% all the named textures are resident, ``gl:areTexturesResident'' returns `?GL_FALSE', -%% and detailed status is returned in the `N' elements of `Residences' . If an element -%% of `Residences' is `?GL_TRUE', then the texture named by the corresponding element -%% of `Textures' is resident. -%% -%% The residence status of a single bound texture may also be queried by calling {@link gl:getTexParameterfv/2} -%% with the `target' argument set to the target to which the texture is bound, and -%% the `pname' argument set to `?GL_TEXTURE_RESIDENT'. This is the only way that -%% the residence status of a default texture can be queried. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAreTexturesResident.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glAreTexturesResident.xml">external</a> documentation. -spec areTexturesResident(Textures) -> {0|1,Residences :: [0|1]} when Textures :: [integer()]. areTexturesResident(Textures) -> TexturesLen = length(Textures), @@ -7070,17 +2760,14 @@ areTexturesResident(Textures) -> %% a texture. If `Texture' is zero, or is a non-zero value that is not currently the %% name of a texture, or if an error occurs, ``gl:isTexture'' returns `?GL_FALSE'. %% -%% A name returned by {@link gl:genTextures/1} , but not yet associated with a texture by -%% calling {@link gl:bindTexture/2} , is not the name of a texture. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsTexture.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsTexture.xhtml">external</a> documentation. -spec isTexture(Texture) -> 0|1 when Texture :: integer(). isTexture(Texture) -> call(5276, <<Texture:?GLuint>>). %% @doc glTexSubImage %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec texSubImage1D(Target, Level, Xoffset, Width, Format, Type, Pixels) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),Width :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem(). texSubImage1D(Target,Level,Xoffset,Width,Format,Type,Pixels) when is_integer(Pixels) -> cast(5277, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Width:?GLsizei,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>); @@ -7090,7 +2777,7 @@ texSubImage1D(Target,Level,Xoffset,Width,Format,Type,Pixels) -> %% @doc glTexSubImage %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec texSubImage2D(Target, Level, Xoffset, Yoffset, Width, Height, Format, Type, Pixels) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem(). texSubImage2D(Target,Level,Xoffset,Yoffset,Width,Height,Format,Type,Pixels) when is_integer(Pixels) -> cast(5279, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>); @@ -7103,30 +2790,7 @@ texSubImage2D(Target,Level,Xoffset,Yoffset,Width,Height,Format,Type,Pixels) -> %% ``gl:copyTexImage1D'' defines a one-dimensional texture image with pixels from the current %% `?GL_READ_BUFFER'. %% -%% The screen-aligned pixel row with left corner at (x y) and with a length of width+2(border) defines -%% the texture array at the mipmap level specified by `Level' . `Internalformat' -%% specifies the internal format of the texture array. -%% -%% The pixels in the row are processed exactly as if {@link gl:readPixels/7} had been called, -%% but the process stops just before final conversion. At this point all pixel component -%% values are clamped to the range [0 1] and then converted to the texture's internal format -%% for storage in the texel array. -%% -%% Pixel ordering is such that lower x screen coordinates correspond to lower texture -%% coordinates. -%% -%% If any of the pixels within the specified row of the current `?GL_READ_BUFFER' are -%% outside the window associated with the current rendering context, then the values obtained -%% for those pixels are undefined. -%% -%% ``gl:copyTexImage1D'' defines a one-dimensional texture image with pixels from the current -%% `?GL_READ_BUFFER'. -%% -%% When `Internalformat' is one of the sRGB types, the GL does not automatically convert -%% the source pixels to the sRGB color space. In this case, the ``gl:pixelMap'' function -%% can be used to accomplish the conversion. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexImage1D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCopyTexImage1D.xhtml">external</a> documentation. -spec copyTexImage1D(Target, Level, Internalformat, X, Y, Width, Border) -> 'ok' when Target :: enum(),Level :: integer(),Internalformat :: enum(),X :: integer(),Y :: integer(),Width :: integer(),Border :: integer(). copyTexImage1D(Target,Level,Internalformat,X,Y,Width,Border) -> cast(5281, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,X:?GLint,Y:?GLint,Width:?GLsizei,Border:?GLint>>). @@ -7136,28 +2800,7 @@ copyTexImage1D(Target,Level,Internalformat,X,Y,Width,Border) -> %% ``gl:copyTexImage2D'' defines a two-dimensional texture image, or cube-map texture image %% with pixels from the current `?GL_READ_BUFFER'. %% -%% The screen-aligned pixel rectangle with lower left corner at ( `X' , `Y' ) and -%% with a width of width+2(border) and a height of height+2(border) defines the texture array at the mipmap -%% level specified by `Level' . `Internalformat' specifies the internal format of -%% the texture array. -%% -%% The pixels in the rectangle are processed exactly as if {@link gl:readPixels/7} had been -%% called, but the process stops just before final conversion. At this point all pixel component -%% values are clamped to the range [0 1] and then converted to the texture's internal format -%% for storage in the texel array. -%% -%% Pixel ordering is such that lower x and y screen coordinates correspond to lower s -%% and t texture coordinates. -%% -%% If any of the pixels within the specified rectangle of the current `?GL_READ_BUFFER' -%% are outside the window associated with the current rendering context, then the values -%% obtained for those pixels are undefined. -%% -%% When `Internalformat' is one of the sRGB types, the GL does not automatically convert -%% the source pixels to the sRGB color space. In this case, the ``gl:pixelMap'' function -%% can be used to accomplish the conversion. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexImage2D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCopyTexImage2D.xhtml">external</a> documentation. -spec copyTexImage2D(Target, Level, Internalformat, X, Y, Width, Height, Border) -> 'ok' when Target :: enum(),Level :: integer(),Internalformat :: enum(),X :: integer(),Y :: integer(),Width :: integer(),Height :: integer(),Border :: integer(). copyTexImage2D(Target,Level,Internalformat,X,Y,Width,Height,Border) -> cast(5282, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei,Border:?GLint>>). @@ -7168,25 +2811,7 @@ copyTexImage2D(Target,Level,Internalformat,X,Y,Width,Height,Border) -> %% pixels from the current `?GL_READ_BUFFER' (rather than from main memory, as is the %% case for {@link gl:texSubImage1D/7} ). %% -%% The screen-aligned pixel row with left corner at ( `X' , `Y' ), and with length `Width' -%% replaces the portion of the texture array with x indices `Xoffset' through xoffset -%% +width-1, inclusive. The destination in the texture array may not include any texels outside -%% the texture array as it was originally specified. -%% -%% The pixels in the row are processed exactly as if {@link gl:readPixels/7} had been called, -%% but the process stops just before final conversion. At this point, all pixel component -%% values are clamped to the range [0 1] and then converted to the texture's internal format -%% for storage in the texel array. -%% -%% It is not an error to specify a subtexture with zero width, but such a specification -%% has no effect. If any of the pixels within the specified row of the current `?GL_READ_BUFFER' -%% are outside the read window associated with the current rendering context, then the values -%% obtained for those pixels are undefined. -%% -%% No change is made to the `internalformat', `width', or `border' parameters -%% of the specified texture array or to texel values outside the specified subregion. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage1D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCopyTexSubImage1D.xhtml">external</a> documentation. -spec copyTexSubImage1D(Target, Level, Xoffset, X, Y, Width) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),X :: integer(),Y :: integer(),Width :: integer(). copyTexSubImage1D(Target,Level,Xoffset,X,Y,Width) -> cast(5283, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,X:?GLint,Y:?GLint,Width:?GLsizei>>). @@ -7197,36 +2822,14 @@ copyTexSubImage1D(Target,Level,Xoffset,X,Y,Width) -> %% image or cube-map texture image with pixels from the current `?GL_READ_BUFFER' (rather %% than from main memory, as is the case for {@link gl:texSubImage1D/7} ). %% -%% The screen-aligned pixel rectangle with lower left corner at (x y) and with width `Width' -%% and height `Height' replaces the portion of the texture array with x indices `Xoffset' -%% through xoffset+width-1, inclusive, and y indices `Yoffset' through yoffset+height -%% -1, inclusive, at the mipmap level specified by `Level' . -%% -%% The pixels in the rectangle are processed exactly as if {@link gl:readPixels/7} had been -%% called, but the process stops just before final conversion. At this point, all pixel component -%% values are clamped to the range [0 1] and then converted to the texture's internal format -%% for storage in the texel array. -%% -%% The destination rectangle in the texture array may not include any texels outside the -%% texture array as it was originally specified. It is not an error to specify a subtexture -%% with zero width or height, but such a specification has no effect. -%% -%% If any of the pixels within the specified rectangle of the current `?GL_READ_BUFFER' -%% are outside the read window associated with the current rendering context, then the values -%% obtained for those pixels are undefined. -%% -%% No change is made to the `internalformat', `width', `height', or `border' -%% parameters of the specified texture array or to texel values outside the specified subregion. -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage2D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCopyTexSubImage2D.xhtml">external</a> documentation. -spec copyTexSubImage2D(Target, Level, Xoffset, Yoffset, X, Y, Width, Height) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),X :: integer(),Y :: integer(),Width :: integer(),Height :: integer(). copyTexSubImage2D(Target,Level,Xoffset,Yoffset,X,Y,Width,Height) -> cast(5284, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>). %% @doc glMap %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMap.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec map1d(Target, U1, U2, Stride, Order, Points) -> 'ok' when Target :: enum(),U1 :: float(),U2 :: float(),Stride :: integer(),Order :: integer(),Points :: binary(). map1d(Target,U1,U2,Stride,Order,Points) -> send_bin(Points), @@ -7234,7 +2837,7 @@ map1d(Target,U1,U2,Stride,Order,Points) -> %% @doc glMap %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMap.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec map1f(Target, U1, U2, Stride, Order, Points) -> 'ok' when Target :: enum(),U1 :: float(),U2 :: float(),Stride :: integer(),Order :: integer(),Points :: binary(). map1f(Target,U1,U2,Stride,Order,Points) -> send_bin(Points), @@ -7242,7 +2845,7 @@ map1f(Target,U1,U2,Stride,Order,Points) -> %% @doc glMap %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMap.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec map2d(Target, U1, U2, Ustride, Uorder, V1, V2, Vstride, Vorder, Points) -> 'ok' when Target :: enum(),U1 :: float(),U2 :: float(),Ustride :: integer(),Uorder :: integer(),V1 :: float(),V2 :: float(),Vstride :: integer(),Vorder :: integer(),Points :: binary(). map2d(Target,U1,U2,Ustride,Uorder,V1,V2,Vstride,Vorder,Points) -> send_bin(Points), @@ -7250,7 +2853,7 @@ map2d(Target,U1,U2,Ustride,Uorder,V1,V2,Vstride,Vorder,Points) -> %% @doc glMap %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMap.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec map2f(Target, U1, U2, Ustride, Uorder, V1, V2, Vstride, Vorder, Points) -> 'ok' when Target :: enum(),U1 :: float(),U2 :: float(),Ustride :: integer(),Uorder :: integer(),V1 :: float(),V2 :: float(),Vstride :: integer(),Vorder :: integer(),Points :: binary(). map2f(Target,U1,U2,Ustride,Uorder,V1,V2,Vstride,Vorder,Points) -> send_bin(Points), @@ -7262,31 +2865,7 @@ map2f(Target,U1,U2,Ustride,Uorder,V1,V2,Vstride,Vorder,Points) -> %% parameters. `Target' chooses a map, `Query' selects a specific parameter, and `V' %% points to storage where the values will be returned. %% -%% The acceptable values for the `Target' parameter are described in the {@link gl:map1d/6} -%% and {@link gl:map1d/6} reference pages. -%% -%% `Query' can assume the following values: -%% -%% `?GL_COEFF': `V' returns the control points for the evaluator function. One-dimensional -%% evaluators return order control points, and two-dimensional evaluators return uorder×vorder -%% control points. Each control point consists of one, two, three, or four integer, single-precision -%% floating-point, or double-precision floating-point values, depending on the type of the -%% evaluator. The GL returns two-dimensional control points in row-major order, incrementing -%% the uorder index quickly and the vorder index after each row. Integer values, when -%% requested, are computed by rounding the internal floating-point values to the nearest -%% integer values. -%% -%% `?GL_ORDER': `V' returns the order of the evaluator function. One-dimensional -%% evaluators return a single value, order. The initial value is 1. Two-dimensional evaluators -%% return two values, uorder and vorder. The initial value is 1,1. -%% -%% `?GL_DOMAIN': `V' returns the linear u and v mapping parameters. One-dimensional -%% evaluators return two values, u1 and u2, as specified by {@link gl:map1d/6} . Two-dimensional -%% evaluators return four values ( u1, u2, v1, and v2) as specified by {@link gl:map1d/6} . -%% Integer values, when requested, are computed by rounding the internal floating-point values -%% to the nearest integer values. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMap.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetMap.xml">external</a> documentation. -spec getMapdv(Target, Query, V) -> 'ok' when Target :: enum(),Query :: enum(),V :: mem(). getMapdv(Target,Query,V) -> send_bin(V), @@ -7313,45 +2892,7 @@ getMapiv(Target,Query,V) -> %% To define a map, call {@link gl:map1d/6} and {@link gl:map1d/6} ; to enable and disable it, %% call {@link gl:enable/1} and {@link gl:enable/1} . %% -%% When one of the ``gl:evalCoord'' commands is issued, all currently enabled maps of -%% the indicated dimension are evaluated. Then, for each enabled map, it is as if the corresponding -%% GL command had been issued with the computed value. That is, if `?GL_MAP1_INDEX' or `?GL_MAP2_INDEX' -%% is enabled, a {@link gl:indexd/1} command is simulated. If `?GL_MAP1_COLOR_4' or `?GL_MAP2_COLOR_4' -%% is enabled, a {@link gl:color3b/3} command is simulated. If `?GL_MAP1_NORMAL' or `?GL_MAP2_NORMAL' -%% is enabled, a normal vector is produced, and if any of `?GL_MAP1_TEXTURE_COORD_1', `?GL_MAP1_TEXTURE_COORD_2' -%% , `?GL_MAP1_TEXTURE_COORD_3', `?GL_MAP1_TEXTURE_COORD_4', `?GL_MAP2_TEXTURE_COORD_1' -%% , `?GL_MAP2_TEXTURE_COORD_2', `?GL_MAP2_TEXTURE_COORD_3', or `?GL_MAP2_TEXTURE_COORD_4' -%% is enabled, then an appropriate {@link gl:texCoord1d/1} command is simulated. -%% -%% For color, color index, normal, and texture coordinates the GL uses evaluated values -%% instead of current values for those evaluations that are enabled, and current values otherwise, -%% However, the evaluated values do not update the current values. Thus, if {@link gl:vertex2d/2} -%% commands are interspersed with ``gl:evalCoord'' commands, the color, normal, and texture -%% coordinates associated with the {@link gl:vertex2d/2} commands are not affected by the values -%% generated by the ``gl:evalCoord'' commands, but only by the most recent {@link gl:color3b/3} -%% , {@link gl:indexd/1} , {@link gl:normal3b/3} , and {@link gl:texCoord1d/1} commands. -%% -%% No commands are issued for maps that are not enabled. If more than one texture evaluation -%% is enabled for a particular dimension (for example, `?GL_MAP2_TEXTURE_COORD_1' and `?GL_MAP2_TEXTURE_COORD_2' -%% ), then only the evaluation of the map that produces the larger number of coordinates -%% (in this case, `?GL_MAP2_TEXTURE_COORD_2') is carried out. `?GL_MAP1_VERTEX_4' -%% overrides `?GL_MAP1_VERTEX_3', and `?GL_MAP2_VERTEX_4' overrides `?GL_MAP2_VERTEX_3' -%% , in the same manner. If neither a three- nor a four-component vertex map is enabled for -%% the specified dimension, the ``gl:evalCoord'' command is ignored. -%% -%% If you have enabled automatic normal generation, by calling {@link gl:enable/1} with argument -%% `?GL_AUTO_NORMAL', ``gl:evalCoord2'' generates surface normals analytically, regardless -%% of the contents or enabling of the `?GL_MAP2_NORMAL' map. Let -%% -%% m=((&PartialD; p)/(&PartialD; u))×((&PartialD; p)/(&PartialD; v)) -%% -%% Then the generated normal n is n=m/(||m||) -%% -%% If automatic normal generation is disabled, the corresponding normal map `?GL_MAP2_NORMAL' -%% , if enabled, is used to produce a normal. If neither automatic normal generation nor -%% a normal map is enabled, no normal is generated for ``gl:evalCoord2'' commands. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEvalCoord.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glEvalCoord.xml">external</a> documentation. -spec evalCoord1d(U) -> 'ok' when U :: float(). evalCoord1d(U) -> cast(5292, <<U:?GLdouble>>). @@ -7397,31 +2938,7 @@ evalCoord2fv({U,V}) -> evalCoord2f(U,V). %% the integer domain of a one- or two-dimensional grid, whose range is the domain of the %% evaluation maps specified by {@link gl:map1d/6} and {@link gl:map1d/6} . %% -%% ``gl:mapGrid1'' and ``gl:mapGrid2'' specify the linear grid mappings between the i -%% (or i and j) integer grid coordinates, to the u (or u and v) floating-point -%% evaluation map coordinates. See {@link gl:map1d/6} and {@link gl:map1d/6} for details of how -%% u and v coordinates are evaluated. -%% -%% ``gl:mapGrid1'' specifies a single linear mapping such that integer grid coordinate -%% 0 maps exactly to `U1' , and integer grid coordinate `Un' maps exactly to `U2' -%% . All other integer grid coordinates i are mapped so that -%% -%% u=i(u2-u1)/un+u1 -%% -%% ``gl:mapGrid2'' specifies two such linear mappings. One maps integer grid coordinate -%% i=0 exactly to `U1' , and integer grid coordinate i=un exactly to `U2' . The -%% other maps integer grid coordinate j=0 exactly to `V1' , and integer grid coordinate -%% j=vn exactly to `V2' . Other integer grid coordinates i and j are mapped such -%% that -%% -%% u=i(u2-u1)/un+u1 -%% -%% v=j(v2-v1)/vn+v1 -%% -%% The mappings specified by ``gl:mapGrid'' are used identically by {@link gl:evalMesh1/3} -%% and {@link gl:evalPoint1/1} . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMapGrid.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glMapGrid.xml">external</a> documentation. -spec mapGrid1d(Un, U1, U2) -> 'ok' when Un :: integer(),U1 :: float(),U2 :: float(). mapGrid1d(Un,U1,U2) -> cast(5296, <<Un:?GLint,0:32,U1:?GLdouble,U2:?GLdouble>>). @@ -7452,23 +2969,7 @@ mapGrid2f(Un,U1,U2,Vn,V1,V2) -> %% . Calling ``gl:evalPoint1'' is equivalent to calling glEvalCoord1( i.&Delta; u+u %% 1 ); where &Delta; u=(u 2-u 1)/n %% -%% and n, u 1, and u 2 are the arguments to the most recent {@link gl:mapGrid1d/3} command. -%% The one absolute numeric requirement is that if i=n, then the value computed from i.&Delta; -%% u+u 1 is exactly u 2. -%% -%% In the two-dimensional case, ``gl:evalPoint2'', let -%% -%% &Delta; u=(u 2-u 1)/n -%% -%% &Delta; v=(v 2-v 1)/m -%% -%% where n, u 1, u 2, m, v 1, and v 2 are the arguments to the most recent {@link gl:mapGrid1d/3} -%% command. Then the ``gl:evalPoint2'' command is equivalent to calling glEvalCoord2( i. -%% &Delta; u+u 1, j.&Delta; v+v 1 ); The only absolute numeric requirements are -%% that if i=n, then the value computed from i.&Delta; u+u 1 is exactly u 2, and -%% if j=m, then the value computed from j.&Delta; v+v 1 is exactly v 2. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEvalPoint.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glEvalPoint.xml">external</a> documentation. -spec evalPoint1(I) -> 'ok' when I :: integer(). evalPoint1(I) -> cast(5300, <<I:?GLint>>). @@ -7487,53 +2988,7 @@ evalPoint2(I,J) -> %% evaluation maps specified by {@link gl:map1d/6} and {@link gl:map1d/6} . `Mode' determines %% whether the resulting vertices are connected as points, lines, or filled polygons. %% -%% In the one-dimensional case, ``gl:evalMesh1'', the mesh is generated as if the following -%% code fragment were executed: -%% -%% glBegin( `Type' ); for ( i = `I1' ; i <= `I2' ; i += 1 ) glEvalCoord1( -%% i.&Delta; u+u 1 ); glEnd(); where -%% -%% &Delta; u=(u 2-u 1)/n -%% -%% and n, u 1, and u 2 are the arguments to the most recent {@link gl:mapGrid1d/3} command. -%% `type' is `?GL_POINTS' if `Mode' is `?GL_POINT', or `?GL_LINES' -%% if `Mode' is `?GL_LINE'. -%% -%% The one absolute numeric requirement is that if i=n, then the value computed from i.&Delta; -%% u+u 1 is exactly u 2. -%% -%% In the two-dimensional case, ``gl:evalMesh2'', let .cp &Delta; u=(u 2-u 1)/n -%% -%% &Delta; v=(v 2-v 1)/m -%% -%% where n, u 1, u 2, m, v 1, and v 2 are the arguments to the most recent {@link gl:mapGrid1d/3} -%% command. Then, if `Mode' is `?GL_FILL', the ``gl:evalMesh2'' command is equivalent -%% to: -%% -%% for ( j = `J1' ; j < `J2' ; j += 1 ) { glBegin( GL_QUAD_STRIP ); for ( i = `I1' -%% ; i <= `I2' ; i += 1 ) { glEvalCoord2( i.&Delta; u+u 1, j.&Delta; v+v 1 -%% ); glEvalCoord2( i.&Delta; u+u 1,(j+1).&Delta; v+v 1 ); } glEnd(); } -%% -%% If `Mode' is `?GL_LINE', then a call to ``gl:evalMesh2'' is equivalent to: -%% -%% for ( j = `J1' ; j <= `J2' ; j += 1 ) { glBegin( GL_LINE_STRIP ); for ( i = `I1' -%% ; i <= `I2' ; i += 1 ) glEvalCoord2( i.&Delta; u+u 1, j.&Delta; v+v 1 -%% ); glEnd(); } for ( i = `I1' ; i <= `I2' ; i += 1 ) { glBegin( GL_LINE_STRIP -%% ); for ( j = `J1' ; j <= `J1' ; j += 1 ) glEvalCoord2( i.&Delta; u+u 1, j. -%% &Delta; v+v 1 ); glEnd(); } -%% -%% And finally, if `Mode' is `?GL_POINT', then a call to ``gl:evalMesh2'' is -%% equivalent to: -%% -%% glBegin( GL_POINTS ); for ( j = `J1' ; j <= `J2' ; j += 1 ) for ( i = `I1' -%% ; i <= `I2' ; i += 1 ) glEvalCoord2( i.&Delta; u+u 1, j.&Delta; v+v 1 -%% ); glEnd(); -%% -%% In all three cases, the only absolute numeric requirements are that if i=n, then the -%% value computed from i.&Delta; u+u 1 is exactly u 2, and if j=m, then the value -%% computed from j.&Delta; v+v 1 is exactly v 2. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEvalMesh.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glEvalMesh.xml">external</a> documentation. -spec evalMesh1(Mode, I1, I2) -> 'ok' when Mode :: enum(),I1 :: integer(),I2 :: integer(). evalMesh1(Mode,I1,I2) -> cast(5302, <<Mode:?GLenum,I1:?GLint,I2:?GLint>>). @@ -7550,66 +3005,7 @@ evalMesh2(Mode,I1,I2,J1,J2) -> %% pixel blocks, but not buffer clear operations. To enable and disable fog, call {@link gl:enable/1} %% and {@link gl:enable/1} with argument `?GL_FOG'. %% -%% ``gl:fog'' assigns the value or values in `Params' to the fog parameter specified -%% by `Pname' . The following values are accepted for `Pname' : -%% -%% `?GL_FOG_MODE': `Params' is a single integer or floating-point value that specifies -%% the equation to be used to compute the fog blend factor, f. Three symbolic constants -%% are accepted: `?GL_LINEAR', `?GL_EXP', and `?GL_EXP2'. The equations corresponding -%% to these symbolic constants are defined below. The initial fog mode is `?GL_EXP'. -%% -%% `?GL_FOG_DENSITY': `Params' is a single integer or floating-point value that -%% specifies density, the fog density used in both exponential fog equations. Only nonnegative -%% densities are accepted. The initial fog density is 1. -%% -%% `?GL_FOG_START': `Params' is a single integer or floating-point value that specifies -%% start, the near distance used in the linear fog equation. The initial near distance -%% is 0. -%% -%% `?GL_FOG_END': `Params' is a single integer or floating-point value that specifies -%% end, the far distance used in the linear fog equation. The initial far distance is 1. -%% -%% `?GL_FOG_INDEX': `Params' is a single integer or floating-point value that specifies -%% i f, the fog color index. The initial fog index is 0. -%% -%% `?GL_FOG_COLOR': `Params' contains four integer or floating-point values that -%% specify C f, the fog color. Integer values are mapped linearly such that the most positive -%% representable value maps to 1.0, and the most negative representable value maps to -1.0. -%% Floating-point values are mapped directly. After conversion, all color components are -%% clamped to the range [0 1]. The initial fog color is (0, 0, 0, 0). -%% -%% `?GL_FOG_COORD_SRC': `Params' contains either of the following symbolic constants: -%% `?GL_FOG_COORD' or `?GL_FRAGMENT_DEPTH'. `?GL_FOG_COORD' specifies that -%% the current fog coordinate should be used as distance value in the fog color computation. -%% `?GL_FRAGMENT_DEPTH' specifies that the current fragment depth should be used as -%% distance value in the fog computation. -%% -%% Fog blends a fog color with each rasterized pixel fragment's post-texturing color using -%% a blending factor f. Factor f is computed in one of three ways, depending on the fog -%% mode. Let c be either the distance in eye coordinate from the origin (in the case that -%% the `?GL_FOG_COORD_SRC' is `?GL_FRAGMENT_DEPTH') or the current fog coordinate -%% (in the case that `?GL_FOG_COORD_SRC' is `?GL_FOG_COORD'). The equation for `?GL_LINEAR' -%% fog is f=(end-c)/(end-start) -%% -%% The equation for `?GL_EXP' fog is f=e(-(density. c)) -%% -%% The equation for `?GL_EXP2' fog is f=e(-(density. c)) 2 -%% -%% Regardless of the fog mode, f is clamped to the range [0 1] after it is computed. Then, -%% if the GL is in RGBA color mode, the fragment's red, green, and blue colors, represented -%% by C r, are replaced by -%% -%% (C r)"=f×C r+(1-f)×C f -%% -%% Fog does not affect a fragment's alpha component. -%% -%% In color index mode, the fragment's color index i r is replaced by -%% -%% (i r)"=i r+(1-f)×i f -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFog.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFog.xml">external</a> documentation. -spec fogf(Pname, Param) -> 'ok' when Pname :: enum(),Param :: float(). fogf(Pname,Param) -> cast(5304, <<Pname:?GLenum,Param:?GLfloat>>). @@ -7642,106 +3038,7 @@ fogiv(Pname,Params) -> %% about primitives that would have been rasterized is fed back to the application using %% the GL. %% -%% ``gl:feedbackBuffer'' has three arguments: `Buffer' is a pointer to an array of -%% floating-point values into which feedback information is placed. `Size' indicates -%% the size of the array. `Type' is a symbolic constant describing the information that -%% is fed back for each vertex. ``gl:feedbackBuffer'' must be issued before feedback mode -%% is enabled (by calling {@link gl:renderMode/1} with argument `?GL_FEEDBACK'). Setting -%% `?GL_FEEDBACK' without establishing the feedback buffer, or calling ``gl:feedbackBuffer'' -%% while the GL is in feedback mode, is an error. -%% -%% When {@link gl:renderMode/1} is called while in feedback mode, it returns the number of -%% entries placed in the feedback array and resets the feedback array pointer to the base -%% of the feedback buffer. The returned value never exceeds `Size' . If the feedback -%% data required more room than was available in `Buffer' , {@link gl:renderMode/1} returns -%% a negative value. To take the GL out of feedback mode, call {@link gl:renderMode/1} with -%% a parameter value other than `?GL_FEEDBACK'. -%% -%% While in feedback mode, each primitive, bitmap, or pixel rectangle that would be rasterized -%% generates a block of values that are copied into the feedback array. If doing so would -%% cause the number of entries to exceed the maximum, the block is partially written so as -%% to fill the array (if there is any room left at all), and an overflow flag is set. Each -%% block begins with a code indicating the primitive type, followed by values that describe -%% the primitive's vertices and associated data. Entries are also written for bitmaps and -%% pixel rectangles. Feedback occurs after polygon culling and {@link gl:polygonMode/2} interpretation -%% of polygons has taken place, so polygons that are culled are not returned in the feedback -%% buffer. It can also occur after polygons with more than three edges are broken up into -%% triangles, if the GL implementation renders polygons by performing this decomposition. -%% -%% The {@link gl:passThrough/1} command can be used to insert a marker into the feedback -%% buffer. See {@link gl:passThrough/1} . -%% -%% Following is the grammar for the blocks of values written into the feedback buffer. Each -%% primitive is indicated with a unique identifying value followed by some number of vertices. -%% Polygon entries include an integer value indicating how many vertices follow. A vertex -%% is fed back as some number of floating-point values, as determined by `Type' . Colors -%% are fed back as four values in RGBA mode and one value in color index mode. -%% -%% feedbackList ← feedbackItem feedbackList | feedbackItem -%% -%% feedbackItem ← point | lineSegment | polygon | bitmap | pixelRectangle | passThru -%% -%% point ←`?GL_POINT_TOKEN' vertex -%% -%% lineSegment ←`?GL_LINE_TOKEN' vertex vertex | `?GL_LINE_RESET_TOKEN' vertex -%% vertex -%% -%% polygon ←`?GL_POLYGON_TOKEN' n polySpec -%% -%% polySpec ← polySpec vertex | vertex vertex vertex -%% -%% bitmap ←`?GL_BITMAP_TOKEN' vertex -%% -%% pixelRectangle ←`?GL_DRAW_PIXEL_TOKEN' vertex | `?GL_COPY_PIXEL_TOKEN' vertex -%% -%% -%% passThru ←`?GL_PASS_THROUGH_TOKEN' value -%% -%% vertex ← 2d | 3d | 3dColor | 3dColorTexture | 4dColorTexture -%% -%% 2d ← value value -%% -%% 3d ← value value value -%% -%% 3dColor ← value value value color -%% -%% 3dColorTexture ← value value value color tex -%% -%% 4dColorTexture ← value value value value color tex -%% -%% color ← rgba | index -%% -%% rgba ← value value value value -%% -%% index ← value -%% -%% tex ← value value value value -%% -%% `value' is a floating-point number, and `n' is a floating-point integer giving -%% the number of vertices in the polygon. `?GL_POINT_TOKEN', `?GL_LINE_TOKEN', `?GL_LINE_RESET_TOKEN' -%% , `?GL_POLYGON_TOKEN', `?GL_BITMAP_TOKEN', `?GL_DRAW_PIXEL_TOKEN', `?GL_COPY_PIXEL_TOKEN' -%% and `?GL_PASS_THROUGH_TOKEN' are symbolic floating-point constants. `?GL_LINE_RESET_TOKEN' -%% is returned whenever the line stipple pattern is reset. The data returned as a vertex -%% depends on the feedback `Type' . -%% -%% The following table gives the correspondence between `Type' and the number of values -%% per vertex. `k' is 1 in color index mode and 4 in RGBA mode. -%% -%% <table><tbody><tr><td>` Type '</td><td>` Coordinates '</td><td>` Color '</td> -%% <td>` Texture '</td><td>` Total Number of Values '</td></tr></tbody><tbody><tr><td> -%% `?GL_2D'</td><td>`x', `y'</td><td></td><td></td><td> 2 </td></tr><tr><td>`?GL_3D' -%% </td><td>`x', `y', `z'</td><td></td><td></td><td> 3 </td></tr><tr><td>`?GL_3D_COLOR' -%% </td><td>`x', `y', `z'</td><td> k</td><td></td><td> 3+k</td></tr><tr><td>`?GL_3D_COLOR_TEXTURE' -%% </td><td>`x', `y', `z'</td><td> k</td><td> 4 </td><td> 7+k</td></tr><tr><td> -%% `?GL_4D_COLOR_TEXTURE'</td><td>`x', `y', `z', `w'</td><td> k</td> -%% <td> 4 </td><td> 8+k</td></tr></tbody></table> -%% -%% Feedback vertex coordinates are in window coordinates, except `w', which is in clip -%% coordinates. Feedback colors are lighted, if lighting is enabled. Feedback texture coordinates -%% are generated, if texture coordinate generation is enabled. They are always transformed -%% by the texture matrix. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFeedbackBuffer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFeedbackBuffer.xml">external</a> documentation. -spec feedbackBuffer(Size, Type, Buffer) -> 'ok' when Size :: integer(),Type :: enum(),Buffer :: mem(). feedbackBuffer(Size,Type,Buffer) -> send_bin(Buffer), @@ -7749,18 +3046,9 @@ feedbackBuffer(Size,Type,Buffer) -> %% @doc Place a marker in the feedback buffer %% -%% Feedback is a GL render mode. The mode is selected by calling {@link gl:renderMode/1} -%% with `?GL_FEEDBACK'. When the GL is in feedback mode, no pixels are produced by rasterization. -%% Instead, information about primitives that would have been rasterized is fed back to the -%% application using the GL. See the {@link gl:feedbackBuffer/3} reference page for a description -%% of the feedback buffer and the values in it. -%% -%% ``gl:passThrough'' inserts a user-defined marker in the feedback buffer when it is executed -%% in feedback mode. `Token' is returned as if it were a primitive; it is indicated -%% with its own unique identifying value: `?GL_PASS_THROUGH_TOKEN'. The order of ``gl:passThrough'' -%% commands with respect to the specification of graphics primitives is maintained. +%% %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPassThrough.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPassThrough.xml">external</a> documentation. -spec passThrough(Token) -> 'ok' when Token :: float(). passThrough(Token) -> cast(5309, <<Token:?GLfloat>>). @@ -7774,38 +3062,7 @@ passThrough(Token) -> %% must be issued before selection mode is enabled, and it must not be issued while the %% rendering mode is `?GL_SELECT'. %% -%% A programmer can use selection to determine which primitives are drawn into some region -%% of a window. The region is defined by the current modelview and perspective matrices. -%% -%% In selection mode, no pixel fragments are produced from rasterization. Instead, if a -%% primitive or a raster position intersects the clipping volume defined by the viewing frustum -%% and the user-defined clipping planes, this primitive causes a selection hit. (With polygons, -%% no hit occurs if the polygon is culled.) When a change is made to the name stack, or when -%% {@link gl:renderMode/1} is called, a hit record is copied to `Buffer' if any hits -%% have occurred since the last such event (name stack change or {@link gl:renderMode/1} call). -%% The hit record consists of the number of names in the name stack at the time of the event, -%% followed by the minimum and maximum depth values of all vertices that hit since the previous -%% event, followed by the name stack contents, bottom name first. -%% -%% Depth values (which are in the range [0,1]) are multiplied by 2 32-1, before being -%% placed in the hit record. -%% -%% An internal index into `Buffer' is reset to 0 whenever selection mode is entered. -%% Each time a hit record is copied into `Buffer' , the index is incremented to point -%% to the cell just past the end of the block of names(emthat is, to the next available cell -%% If the hit record is larger than the number of remaining locations in `Buffer' , as -%% much data as can fit is copied, and the overflow flag is set. If the name stack is empty -%% when a hit record is copied, that record consists of 0 followed by the minimum and maximum -%% depth values. -%% -%% To exit selection mode, call {@link gl:renderMode/1} with an argument other than `?GL_SELECT' -%% . Whenever {@link gl:renderMode/1} is called while the render mode is `?GL_SELECT', -%% it returns the number of hit records copied to `Buffer' , resets the overflow flag -%% and the selection buffer pointer, and initializes the name stack to be empty. If the overflow -%% bit was set when {@link gl:renderMode/1} was called, a negative hit record count is returned. -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSelectBuffer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glSelectBuffer.xml">external</a> documentation. -spec selectBuffer(Size, Buffer) -> 'ok' when Size :: integer(),Buffer :: mem(). selectBuffer(Size,Buffer) -> send_bin(Buffer), @@ -7817,10 +3074,7 @@ selectBuffer(Size,Buffer) -> %% uniquely identified. It consists of an ordered set of unsigned integers. ``gl:initNames'' %% causes the name stack to be initialized to its default empty state. %% -%% The name stack is always empty while the render mode is not `?GL_SELECT'. Calls to ``gl:initNames'' -%% while the render mode is not `?GL_SELECT' are ignored. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glInitNames.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glInitNames.xml">external</a> documentation. -spec initNames() -> 'ok'. initNames() -> cast(5311, <<>>). @@ -7831,12 +3085,7 @@ initNames() -> %% uniquely identified. It consists of an ordered set of unsigned integers and is initially %% empty. %% -%% ``gl:loadName'' causes `Name' to replace the value on the top of the name stack. -%% -%% The name stack is always empty while the render mode is not `?GL_SELECT'. Calls to ``gl:loadName'' -%% while the render mode is not `?GL_SELECT' are ignored. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadName.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLoadName.xml">external</a> documentation. -spec loadName(Name) -> 'ok' when Name :: integer(). loadName(Name) -> cast(5312, <<Name:?GLuint>>). @@ -7847,20 +3096,7 @@ loadName(Name) -> %% uniquely identified. It consists of an ordered set of unsigned integers and is initially %% empty. %% -%% ``gl:pushName'' causes `Name' to be pushed onto the name stack. {@link gl:pushName/1} -%% pops one name off the top of the stack. -%% -%% The maximum name stack depth is implementation-dependent; call `?GL_MAX_NAME_STACK_DEPTH' -%% to find out the value for a particular implementation. It is an error to push a name -%% onto a full stack or to pop a name off an empty stack. It is also an error to manipulate -%% the name stack between the execution of {@link gl:'begin'/1} and the corresponding execution -%% of {@link gl:'begin'/1} . In any of these cases, the error flag is set and no other change is -%% made to GL state. -%% -%% The name stack is always empty while the render mode is not `?GL_SELECT'. Calls to ``gl:pushName'' -%% or {@link gl:pushName/1} while the render mode is not `?GL_SELECT' are ignored. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPushName.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glPushName.xml">external</a> documentation. -spec pushName(Name) -> 'ok' when Name :: integer(). pushName(Name) -> cast(5313, <<Name:?GLuint>>). @@ -7878,7 +3114,7 @@ popName() -> %% for a complete description of the blending operations. Initially the `?GL_BLEND_COLOR' %% is set to (0, 0, 0, 0). %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendColor.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendColor.xhtml">external</a> documentation. -spec blendColor(Red, Green, Blue, Alpha) -> 'ok' when Red :: clamp(),Green :: clamp(),Blue :: clamp(),Alpha :: clamp(). blendColor(Red,Green,Blue,Alpha) -> cast(5315, <<Red:?GLclampf,Green:?GLclampf,Blue:?GLclampf,Alpha:?GLclampf>>). @@ -7891,35 +3127,7 @@ blendColor(Red,Green,Blue,Alpha) -> %% specifies the blend equation for a single draw buffer whereas ``gl:blendEquation'' %% sets the blend equation for all draw buffers. %% -%% These equations use the source and destination blend factors specified by either {@link gl:blendFunc/2} -%% or {@link gl:blendFuncSeparate/4} . See {@link gl:blendFunc/2} or {@link gl:blendFuncSeparate/4} -%% for a description of the various blend factors. -%% -%% In the equations that follow, source and destination color components are referred to -%% as (R s G s B s A s) and (R d G d B d A d), respectively. The result color is referred to as (R r G r B r A r). The source and destination -%% blend factors are denoted (s R s G s B s A) and (d R d G d B d A), respectively. For these equations all color components -%% are understood to have values in the range [0 1]. <table><tbody><tr><td>` Mode '</td><td> -%% ` RGB Components '</td><td>` Alpha Component '</td></tr></tbody><tbody><tr><td>`?GL_FUNC_ADD' -%% </td><td> Rr=R s s R+R d d R Gr=G s s G+G d d G Br=B s s B+B d d B</td><td> Ar=A s -%% s A+A d d A</td></tr><tr><td>`?GL_FUNC_SUBTRACT'</td><td> Rr=R s s R-R d d R Gr=G -%% s s G-G d d G Br=B s s B-B d d B</td><td> Ar=A s s A-A d d A</td></tr><tr><td>`?GL_FUNC_REVERSE_SUBTRACT' -%% </td><td> Rr=R d d R-R s s R Gr=G d d G-G s s G Br=B d d B-B s s B</td><td> Ar=A d -%% d A-A s s A</td></tr><tr><td>`?GL_MIN'</td><td> Rr=min(R s R d) Gr=min(G s G d) Br=min(B s B d)</td><td> Ar=min -%% (A s A d)</td></tr><tr><td>`?GL_MAX'</td><td> Rr=max(R s R d) Gr=max(G s G d) Br=max(B s B d)</td><td> Ar=max(A s A d)</td></tr></tbody> -%% </table> -%% -%% The results of these equations are clamped to the range [0 1]. -%% -%% The `?GL_MIN' and `?GL_MAX' equations are useful for applications that analyze -%% image data (image thresholding against a constant color, for example). The `?GL_FUNC_ADD' -%% equation is useful for antialiasing and transparency, among other things. -%% -%% Initially, both the RGB blend equation and the alpha blend equation are set to `?GL_FUNC_ADD' -%% . -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquation.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendEquation.xhtml">external</a> documentation. -spec blendEquation(Mode) -> 'ok' when Mode :: enum(). blendEquation(Mode) -> cast(5316, <<Mode:?GLenum>>). @@ -7931,24 +3139,7 @@ blendEquation(Mode) -> %% , with the additional constraint that all values in the arrays `Count' must lie between %% `Start' and `End' , inclusive. %% -%% Implementations denote recommended maximum amounts of vertex and index data, which may -%% be queried by calling {@link gl:getBooleanv/1} with argument `?GL_MAX_ELEMENTS_VERTICES' and `?GL_MAX_ELEMENTS_INDICES' -%% . If end-start+1 is greater than the value of `?GL_MAX_ELEMENTS_VERTICES', or if `Count' -%% is greater than the value of `?GL_MAX_ELEMENTS_INDICES', then the call may operate -%% at reduced performance. There is no requirement that all vertices in the range [start end] be referenced. -%% However, the implementation may partially process unused vertices, reducing performance -%% from what could be achieved with an optimal index set. -%% -%% When ``gl:drawRangeElements'' is called, it uses `Count' sequential elements from -%% an enabled array, starting at `Start' to construct a sequence of geometric primitives. -%% `Mode' specifies what kind of primitives are constructed, and how the array elements -%% construct these primitives. If more than one array is enabled, each is used. -%% -%% Vertex attributes that are modified by ``gl:drawRangeElements'' have an unspecified -%% value after ``gl:drawRangeElements'' returns. Attributes that aren't modified maintain -%% their previous values. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawRangeElements.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawRangeElements.xhtml">external</a> documentation. -spec drawRangeElements(Mode, Start, End, Count, Type, Indices) -> 'ok' when Mode :: enum(),Start :: integer(),End :: integer(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(). drawRangeElements(Mode,Start,End,Count,Type,Indices) when is_integer(Indices) -> cast(5317, <<Mode:?GLenum,Start:?GLuint,End:?GLuint,Count:?GLsizei,Type:?GLenum,Indices:?GLuint>>); @@ -7962,101 +3153,7 @@ drawRangeElements(Mode,Start,End,Count,Type,Indices) -> %% which texturing is enabled. To enable and disable three-dimensional texturing, call {@link gl:enable/1} %% and {@link gl:enable/1} with argument `?GL_TEXTURE_3D'. %% -%% To define texture images, call ``gl:texImage3D''. The arguments describe the parameters -%% of the texture image, such as height, width, depth, width of the border, level-of-detail -%% number (see {@link gl:texParameterf/3} ), and number of color components provided. The last -%% three arguments describe how the image is represented in memory. -%% -%% If `Target' is `?GL_PROXY_TEXTURE_3D', no data is read from `Data' , but -%% all of the texture image state is recalculated, checked for consistency, and checked against -%% the implementation's capabilities. If the implementation cannot handle a texture of the -%% requested texture size, it sets all of the image state to 0, but does not generate an -%% error (see {@link gl:getError/0} ). To query for an entire mipmap array, use an image array -%% level greater than or equal to 1. -%% -%% If `Target' is `?GL_TEXTURE_3D', data is read from `Data' as a sequence -%% of signed or unsigned bytes, shorts, or longs, or single-precision floating-point values, -%% depending on `Type' . These values are grouped into sets of one, two, three, or four -%% values, depending on `Format' , to form elements. Each data byte is treated as eight -%% 1-bit elements, with bit ordering determined by `?GL_UNPACK_LSB_FIRST' (see {@link gl:pixelStoref/2} -%% ). -%% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated -%% as a byte offset into the buffer object's data store. -%% -%% The first element corresponds to the lower left corner of the texture image. Subsequent -%% elements progress left-to-right through the remaining texels in the lowest row of the -%% texture image, and then in successively higher rows of the texture image. The final element -%% corresponds to the upper right corner of the texture image. -%% -%% `Format' determines the composition of each element in `Data' . It can assume -%% one of these symbolic values: -%% -%% `?GL_RED': Each element is a single red component. The GL converts it to floating -%% point and assembles it into an RGBA element by attaching 0 for green and blue, and 1 for -%% alpha. Each component is then multiplied by the signed scale factor `?GL_c_SCALE', -%% added to the signed bias `?GL_c_BIAS', and clamped to the range [0,1]. -%% -%% `?GL_RG': Each element is a red and green pair. The GL converts each to floating -%% point and assembles it into an RGBA element by attaching 0 for blue, and 1 for alpha. -%% Each component is then multiplied by the signed scale factor `?GL_c_SCALE', added -%% to the signed bias `?GL_c_BIAS', and clamped to the range [0,1]. -%% -%% `?GL_RGB' -%% -%% `?GL_BGR': Each element is an RGB triple. The GL converts it to floating point and -%% assembles it into an RGBA element by attaching 1 for alpha. Each component is then multiplied -%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS', -%% and clamped to the range [0,1]. -%% -%% `?GL_RGBA' -%% -%% `?GL_BGRA': Each element contains all four components. Each component is multiplied -%% by the signed scale factor `?GL_c_SCALE', added to the signed bias `?GL_c_BIAS', -%% and clamped to the range [0,1]. -%% -%% If an application wants to store the texture at a certain resolution or in a certain -%% format, it can request the resolution and format with `InternalFormat' . The GL will -%% choose an internal representation that closely approximates that requested by `InternalFormat' -%% , but it may not match exactly. (The representations specified by `?GL_RED', `?GL_RG' -%% , `?GL_RGB', and `?GL_RGBA' must match exactly.) -%% -%% `InternalFormat' may be one of the base internal formats shown in Table 1, below -%% -%% `InternalFormat' may also be one of the sized internal formats shown in Table 2, -%% below -%% -%% Finally, `InternalFormat' may also be one of the generic or compressed compressed -%% texture formats shown in Table 3 below -%% -%% If the `InternalFormat' parameter is one of the generic compressed formats, `?GL_COMPRESSED_RED' -%% , `?GL_COMPRESSED_RG', `?GL_COMPRESSED_RGB', or `?GL_COMPRESSED_RGBA', -%% the GL will replace the internal format with the symbolic constant for a specific internal -%% format and compress the texture before storage. If no corresponding internal format is -%% available, or the GL can not compress that image for any reason, the internal format is -%% instead replaced with a corresponding base internal format. -%% -%% If the `InternalFormat' parameter is `?GL_SRGB', `?GL_SRGB8', `?GL_SRGB_ALPHA' -%% , or `?GL_SRGB8_ALPHA8', the texture is treated as if the red, green, blue, or -%% luminance components are encoded in the sRGB color space. Any alpha component is left -%% unchanged. The conversion from the sRGB encoded component c s to a linear component -%% c l is: -%% -%% c l={ c s/12.92if c s&le; 0.04045( c s+0.055/1.055) 2.4if c s> 0.04045 -%% -%% Assume c s is the sRGB component in the range [0,1]. -%% -%% Use the `?GL_PROXY_TEXTURE_3D' target to try out a resolution and format. The implementation -%% will update and recompute its best match for the requested storage resolution and format. -%% To then query this state, call {@link gl:getTexLevelParameterfv/3} . If the texture cannot -%% be accommodated, texture state is set to 0. -%% -%% A one-component texture image uses only the red component of the RGBA color extracted -%% from `Data' . A two-component image uses the R and A values. A three-component image -%% uses the R, G, and B values. A four-component image uses all of the RGBA components. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage3D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage3D.xhtml">external</a> documentation. -spec texImage3D(Target, Level, InternalFormat, Width, Height, Depth, Border, Format, Type, Pixels) -> 'ok' when Target :: enum(),Level :: integer(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Border :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem(). texImage3D(Target,Level,InternalFormat,Width,Height,Depth,Border,Format,Type,Pixels) when is_integer(Pixels) -> cast(5319, <<Target:?GLenum,Level:?GLint,InternalFormat:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Border:?GLint,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>); @@ -8066,7 +3163,7 @@ texImage3D(Target,Level,InternalFormat,Width,Height,Depth,Border,Format,Type,Pix %% @doc glTexSubImage %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexSubImage.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec texSubImage3D(Target, Level, Xoffset, Yoffset, Zoffset, Width, Height, Depth, Format, Type, Pixels) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),Zoffset :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Format :: enum(),Type :: enum(),Pixels :: offset()|mem(). texSubImage3D(Target,Level,Xoffset,Yoffset,Zoffset,Width,Height,Depth,Format,Type,Pixels) when is_integer(Pixels) -> cast(5321, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Zoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Format:?GLenum,Type:?GLenum,Pixels:?GLuint>>); @@ -8080,30 +3177,7 @@ texSubImage3D(Target,Level,Xoffset,Yoffset,Zoffset,Width,Height,Depth,Format,Typ %% image with pixels from the current `?GL_READ_BUFFER' (rather than from main memory, %% as is the case for {@link gl:texSubImage1D/7} ). %% -%% The screen-aligned pixel rectangle with lower left corner at ( `X' , `Y' ) and -%% with width `Width' and height `Height' replaces the portion of the texture array -%% with x indices `Xoffset' through xoffset+width-1, inclusive, and y indices `Yoffset' -%% through yoffset+height-1, inclusive, at z index `Zoffset' and at the mipmap level -%% specified by `Level' . -%% -%% The pixels in the rectangle are processed exactly as if {@link gl:readPixels/7} had been -%% called, but the process stops just before final conversion. At this point, all pixel component -%% values are clamped to the range [0 1] and then converted to the texture's internal format -%% for storage in the texel array. -%% -%% The destination rectangle in the texture array may not include any texels outside the -%% texture array as it was originally specified. It is not an error to specify a subtexture -%% with zero width or height, but such a specification has no effect. -%% -%% If any of the pixels within the specified rectangle of the current `?GL_READ_BUFFER' -%% are outside the read window associated with the current rendering context, then the values -%% obtained for those pixels are undefined. -%% -%% No change is made to the `internalformat', `width', `height', `depth', -%% or `border' parameters of the specified texture array or to texel values outside -%% the specified subregion. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyTexSubImage3D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCopyTexSubImage3D.xhtml">external</a> documentation. -spec copyTexSubImage3D(Target, Level, Xoffset, Yoffset, Zoffset, X, Y, Width, Height) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),Zoffset :: integer(),X :: integer(),Y :: integer(),Width :: integer(),Height :: integer(). copyTexSubImage3D(Target,Level,Xoffset,Yoffset,Zoffset,X,Y,Width,Height) -> cast(5323, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Zoffset:?GLint,X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>). @@ -8115,95 +3189,7 @@ copyTexSubImage3D(Target,Level,Xoffset,Yoffset,Zoffset,X,Y,Width,Height) -> %% lookup table. Use the targets `?GL_PROXY_*' for the first case and the other targets %% for the second case. %% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a color table is specified, `Data' is treated -%% as a byte offset into the buffer object's data store. -%% -%% If `Target' is `?GL_COLOR_TABLE', `?GL_POST_CONVOLUTION_COLOR_TABLE', or `?GL_POST_COLOR_MATRIX_COLOR_TABLE' -%% , ``gl:colorTable'' builds a color lookup table from an array of pixels. The pixel array -%% specified by `Width' , `Format' , `Type' , and `Data' is extracted from -%% memory and processed just as if {@link gl:drawPixels/5} were called, but processing stops -%% after the final expansion to RGBA is completed. -%% -%% The four scale parameters and the four bias parameters that are defined for the table -%% are then used to scale and bias the R, G, B, and A components of each pixel. (Use ``gl:colorTableParameter'' -%% to set these scale and bias parameters.) -%% -%% Next, the R, G, B, and A values are clamped to the range [0 1]. Each pixel is then converted -%% to the internal format specified by `Internalformat' . This conversion simply maps -%% the component values of the pixel (R, G, B, and A) to the values included in the internal -%% format (red, green, blue, alpha, luminance, and intensity). The mapping is as follows: -%% -%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td> -%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity ' -%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td> -%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td> -%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td> -%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td> -%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td> -%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td> -%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table> -%% -%% Finally, the red, green, blue, alpha, luminance, and/or intensity components of the resulting -%% pixels are stored in the color table. They form a one-dimensional table with indices in -%% the range [0 width-1]. -%% -%% If `Target' is `?GL_PROXY_*', ``gl:colorTable'' recomputes and stores the -%% values of the proxy color table's state variables `?GL_COLOR_TABLE_FORMAT', `?GL_COLOR_TABLE_WIDTH' -%% , `?GL_COLOR_TABLE_RED_SIZE', `?GL_COLOR_TABLE_GREEN_SIZE', `?GL_COLOR_TABLE_BLUE_SIZE' -%% , `?GL_COLOR_TABLE_ALPHA_SIZE', `?GL_COLOR_TABLE_LUMINANCE_SIZE', and `?GL_COLOR_TABLE_INTENSITY_SIZE' -%% . There is no effect on the image or state of any actual color table. If the specified -%% color table is too large to be supported, then all the proxy state variables listed above -%% are set to zero. Otherwise, the color table could be supported by ``gl:colorTable'' -%% using the corresponding non-proxy target, and the proxy state variables are set as if -%% that target were being defined. -%% -%% The proxy state variables can be retrieved by calling {@link gl:getColorTableParameterfv/2} -%% with a target of `?GL_PROXY_*'. This allows the application to decide if a particular -%% ``gl:colorTable'' command would succeed, and to determine what the resulting color table -%% attributes would be. -%% -%% If a color table is enabled, and its width is non-zero, then its contents are used to -%% replace a subset of the components of each RGBA pixel group, based on the internal format -%% of the table. -%% -%% Each pixel group has color components (R, G, B, A) that are in the range [0.0 1.0]. The color -%% components are rescaled to the size of the color lookup table to form an index. Then a -%% subset of the components based on the internal format of the table are replaced by the -%% table entry selected by that index. If the color components and contents of the table -%% are represented as follows: -%% -%% <table><tbody><tr><td>` Representation '</td><td>` Meaning '</td></tr></tbody><tbody> -%% <tr><td>r</td><td> Table index computed from R</td></tr><tr><td>g</td><td> Table index -%% computed from G</td></tr><tr><td>b</td><td> Table index computed from B</td></tr><tr><td>a -%% </td><td> Table index computed from A</td></tr><tr><td>L[i]</td><td> Luminance value at -%% table index i</td></tr><tr><td>I[i]</td><td> Intensity value at table index i</td></tr><tr> -%% <td>R[i]</td><td> Red value at table index i</td></tr><tr><td>G[i]</td><td> Green value -%% at table index i</td></tr><tr><td>B[i]</td><td> Blue value at table index i</td></tr><tr><td> -%% A[i]</td><td> Alpha value at table index i</td></tr></tbody></table> -%% -%% then the result of color table lookup is as follows: -%% -%% <table><tbody><tr><td></td><td>` Resulting Texture Components '</td></tr><tr><td>` Table Internal Format ' -%% </td><td>` R '</td><td>` G '</td><td>` B '</td><td>` A '</td></tr></tbody> -%% <tbody><tr><td>`?GL_ALPHA'</td><td>R</td><td>G</td><td>B</td><td>A[a]</td></tr><tr><td> -%% `?GL_LUMINANCE'</td><td>L[r]</td><td>L[g]</td><td>L[b]</td><td>At</td></tr><tr><td>`?GL_LUMINANCE_ALPHA' -%% </td><td>L[r]</td><td>L[g]</td><td>L[b]</td><td>A[a]</td></tr><tr><td>`?GL_INTENSITY'</td> -%% <td>I[r]</td><td>I[g]</td><td>I[b]</td><td>I[a]</td></tr><tr><td>`?GL_RGB'</td><td>R[r] -%% </td><td>G[g]</td><td>B[b]</td><td>A</td></tr><tr><td>`?GL_RGBA'</td><td>R[r]</td><td> -%% G[g]</td><td>B[b]</td><td>A[a]</td></tr></tbody></table> -%% -%% When `?GL_COLOR_TABLE' is enabled, the colors resulting from the pixel map operation -%% (if it is enabled) are mapped by the color lookup table before being passed to the convolution -%% operation. The colors resulting from the convolution operation are modified by the post -%% convolution color lookup table when `?GL_POST_CONVOLUTION_COLOR_TABLE' is enabled. -%% These modified colors are then sent to the color matrix operation. Finally, if `?GL_POST_COLOR_MATRIX_COLOR_TABLE' -%% is enabled, the colors resulting from the color matrix operation are mapped by the post -%% color matrix color lookup table before being used by the histogram operation. -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorTable.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glColorTable.xml">external</a> documentation. -spec colorTable(Target, Internalformat, Width, Format, Type, Table) -> 'ok' when Target :: enum(),Internalformat :: enum(),Width :: integer(),Format :: enum(),Type :: enum(),Table :: offset()|mem(). colorTable(Target,Internalformat,Width,Format,Type,Table) when is_integer(Table) -> cast(5324, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Format:?GLenum,Type:?GLenum,Table:?GLuint>>); @@ -8218,17 +3204,7 @@ colorTable(Target,Internalformat,Width,Format,Type,Table) -> %% color table the scale and bias terms apply to; it must be set to `?GL_COLOR_TABLE', `?GL_POST_CONVOLUTION_COLOR_TABLE' %% , or `?GL_POST_COLOR_MATRIX_COLOR_TABLE'. %% -%% `Pname' must be `?GL_COLOR_TABLE_SCALE' to set the scale factors. In this case, -%% `Params' points to an array of four values, which are the scale factors for red, -%% green, blue, and alpha, in that order. -%% -%% `Pname' must be `?GL_COLOR_TABLE_BIAS' to set the bias terms. In this case, `Params' -%% points to an array of four values, which are the bias terms for red, green, blue, and -%% alpha, in that order. -%% -%% The color tables themselves are specified by calling {@link gl:colorTable/6} . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorTableParameter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glColorTableParameter.xml">external</a> documentation. -spec colorTableParameterfv(Target, Pname, Params) -> 'ok' when Target :: enum(),Pname :: enum(),Params :: {float(),float(),float(),float()}. colorTableParameterfv(Target,Pname,{P1,P2,P3,P4}) -> cast(5326, <<Target:?GLenum,Pname:?GLenum,P1:?GLfloat,P2:?GLfloat,P3:?GLfloat,P4:?GLfloat>>). @@ -8244,41 +3220,7 @@ colorTableParameteriv(Target,Pname,{P1,P2,P3,P4}) -> %% ``gl:copyColorTable'' loads a color table with pixels from the current `?GL_READ_BUFFER' %% (rather than from main memory, as is the case for {@link gl:colorTable/6} ). %% -%% The screen-aligned pixel rectangle with lower-left corner at ( `X' , `Y' ) having -%% width `Width' and height 1 is loaded into the color table. If any pixels within this -%% region are outside the window that is associated with the GL context, the values obtained -%% for those pixels are undefined. -%% -%% The pixels in the rectangle are processed just as if {@link gl:readPixels/7} were called, -%% with `Internalformat' set to RGBA, but processing stops after the final conversion -%% to RGBA. -%% -%% The four scale parameters and the four bias parameters that are defined for the table -%% are then used to scale and bias the R, G, B, and A components of each pixel. The scale -%% and bias parameters are set by calling {@link gl:colorTableParameterfv/3} . -%% -%% Next, the R, G, B, and A values are clamped to the range [0 1]. Each pixel is then converted -%% to the internal format specified by `Internalformat' . This conversion simply maps -%% the component values of the pixel (R, G, B, and A) to the values included in the internal -%% format (red, green, blue, alpha, luminance, and intensity). The mapping is as follows: -%% -%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td> -%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity ' -%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td> -%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td> -%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td> -%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td> -%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td> -%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td> -%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table> -%% -%% Finally, the red, green, blue, alpha, luminance, and/or intensity components of the resulting -%% pixels are stored in the color table. They form a one-dimensional table with indices in -%% the range [0 width-1]. -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyColorTable.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glCopyColorTable.xml">external</a> documentation. -spec copyColorTable(Target, Internalformat, X, Y, Width) -> 'ok' when Target :: enum(),Internalformat :: enum(),X :: integer(),Y :: integer(),Width :: integer(). copyColorTable(Target,Internalformat,X,Y,Width) -> cast(5328, <<Target:?GLenum,Internalformat:?GLenum,X:?GLint,Y:?GLint,Width:?GLsizei>>). @@ -8289,21 +3231,7 @@ copyColorTable(Target,Internalformat,X,Y,Width) -> %% by `Target' . No pixel transfer operations are performed, but pixel storage modes %% that are applicable to {@link gl:readPixels/7} are performed. %% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a histogram table is requested, `Table' is treated -%% as a byte offset into the buffer object's data store. -%% -%% Color components that are requested in the specified `Format' , but which are not -%% included in the internal format of the color lookup table, are returned as zero. The assignments -%% of internal color components to the components requested by `Format' are <table><tbody> -%% <tr><td>` Internal Component '</td><td>` Resulting Component '</td></tr></tbody> -%% <tbody><tr><td> Red </td><td> Red </td></tr><tr><td> Green </td><td> Green </td></tr><tr><td> -%% Blue </td><td> Blue </td></tr><tr><td> Alpha </td><td> Alpha </td></tr><tr><td> Luminance -%% </td><td> Red </td></tr><tr><td> Intensity </td><td> Red </td></tr></tbody></table> -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetColorTable.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetColorTable.xml">external</a> documentation. -spec getColorTable(Target, Format, Type, Table) -> 'ok' when Target :: enum(),Format :: enum(),Type :: enum(),Table :: mem(). getColorTable(Target,Format,Type,Table) -> send_bin(Table), @@ -8313,36 +3241,7 @@ getColorTable(Target,Format,Type,Table) -> %% %% Returns parameters specific to color table `Target' . %% -%% When `Pname' is set to `?GL_COLOR_TABLE_SCALE' or `?GL_COLOR_TABLE_BIAS', -%% ``gl:getColorTableParameter'' returns the color table scale or bias parameters for the -%% table specified by `Target' . For these queries, `Target' must be set to `?GL_COLOR_TABLE' -%% , `?GL_POST_CONVOLUTION_COLOR_TABLE', or `?GL_POST_COLOR_MATRIX_COLOR_TABLE' -%% and `Params' points to an array of four elements, which receive the scale or bias -%% factors for red, green, blue, and alpha, in that order. -%% -%% ``gl:getColorTableParameter'' can also be used to retrieve the format and size parameters -%% for a color table. For these queries, set `Target' to either the color table target -%% or the proxy color table target. The format and size parameters are set by {@link gl:colorTable/6} -%% . -%% -%% The following table lists the format and size parameters that may be queried. For each -%% symbolic constant listed below for `Pname' , `Params' must point to an array -%% of the given length and receive the values indicated. -%% -%% <table><tbody><tr><td>` Parameter '</td><td>` N '</td><td>` Meaning '</td></tr> -%% </tbody><tbody><tr><td>`?GL_COLOR_TABLE_FORMAT'</td><td> 1 </td><td> Internal format -%% (e.g., `?GL_RGBA') </td></tr><tr><td>`?GL_COLOR_TABLE_WIDTH'</td><td> 1 </td><td> -%% Number of elements in table </td></tr><tr><td>`?GL_COLOR_TABLE_RED_SIZE'</td><td> -%% 1 </td><td> Size of red component, in bits </td></tr><tr><td>`?GL_COLOR_TABLE_GREEN_SIZE' -%% </td><td> 1 </td><td> Size of green component </td></tr><tr><td>`?GL_COLOR_TABLE_BLUE_SIZE' -%% </td><td> 1 </td><td> Size of blue component </td></tr><tr><td>`?GL_COLOR_TABLE_ALPHA_SIZE' -%% </td><td> 1 </td><td> Size of alpha component </td></tr><tr><td>`?GL_COLOR_TABLE_LUMINANCE_SIZE' -%% </td><td> 1 </td><td> Size of luminance component </td></tr><tr><td>`?GL_COLOR_TABLE_INTENSITY_SIZE' -%% </td><td> 1 </td><td> Size of intensity component </td></tr></tbody></table> -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetColorTableParameter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetColorTableParameter.xml">external</a> documentation. -spec getColorTableParameterfv(Target, Pname) -> {float(),float(),float(),float()} when Target :: enum(),Pname :: enum(). getColorTableParameterfv(Target,Pname) -> call(5330, <<Target:?GLenum,Pname:?GLenum>>). @@ -8362,11 +3261,7 @@ getColorTableParameteriv(Target,Pname) -> %% originally specified. It is not an error to specify a subtexture with width of 0, but %% such a specification has no effect. %% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a portion of a color table is respecified, `Data' -%% is treated as a byte offset into the buffer object's data store. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorSubTable.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glColorSubTable.xml">external</a> documentation. -spec colorSubTable(Target, Start, Count, Format, Type, Data) -> 'ok' when Target :: enum(),Start :: integer(),Count :: integer(),Format :: enum(),Type :: enum(),Data :: offset()|mem(). colorSubTable(Target,Start,Count,Format,Type,Data) when is_integer(Data) -> cast(5332, <<Target:?GLenum,Start:?GLsizei,Count:?GLsizei,Format:?GLenum,Type:?GLenum,Data:?GLuint>>); @@ -8383,7 +3278,7 @@ colorSubTable(Target,Start,Count,Format,Type,Data) -> %% specified. It is not an error to specify a subtexture with width of 0, but such a specification %% has no effect. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyColorSubTable.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glCopyColorSubTable.xml">external</a> documentation. -spec copyColorSubTable(Target, Start, X, Y, Width) -> 'ok' when Target :: enum(),Start :: integer(),X :: integer(),Y :: integer(),Width :: integer(). copyColorSubTable(Target,Start,X,Y,Width) -> cast(5334, <<Target:?GLenum,Start:?GLsizei,X:?GLint,Y:?GLint,Width:?GLsizei>>). @@ -8393,50 +3288,7 @@ copyColorSubTable(Target,Start,X,Y,Width) -> %% ``gl:convolutionFilter1D'' builds a one-dimensional convolution filter kernel from an %% array of pixels. %% -%% The pixel array specified by `Width' , `Format' , `Type' , and `Data' -%% is extracted from memory and processed just as if {@link gl:drawPixels/5} were called, -%% but processing stops after the final expansion to RGBA is completed. -%% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a convolution filter is specified, `Data' is -%% treated as a byte offset into the buffer object's data store. -%% -%% The R, G, B, and A components of each pixel are next scaled by the four 1D `?GL_CONVOLUTION_FILTER_SCALE' -%% parameters and biased by the four 1D `?GL_CONVOLUTION_FILTER_BIAS' parameters. (The -%% scale and bias parameters are set by {@link gl:convolutionParameterf/3} using the `?GL_CONVOLUTION_1D' -%% target and the names `?GL_CONVOLUTION_FILTER_SCALE' and `?GL_CONVOLUTION_FILTER_BIAS' -%% . The parameters themselves are vectors of four values that are applied to red, green, -%% blue, and alpha, in that order.) The R, G, B, and A values are not clamped to [0,1] at -%% any time during this process. -%% -%% Each pixel is then converted to the internal format specified by `Internalformat' . -%% This conversion simply maps the component values of the pixel (R, G, B, and A) to the -%% values included in the internal format (red, green, blue, alpha, luminance, and intensity). -%% The mapping is as follows: -%% -%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td> -%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity ' -%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td> -%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td> -%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td> -%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td> -%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td> -%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td> -%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table> -%% -%% The red, green, blue, alpha, luminance, and/or intensity components of the resulting -%% pixels are stored in floating-point rather than integer format. They form a one-dimensional -%% filter kernel image indexed with coordinate `i' such that `i' starts at 0 and -%% increases from left to right. Kernel location `i' is derived from the `i'th -%% pixel, counting from 0. -%% -%% Note that after a convolution is performed, the resulting color components are also scaled -%% by their corresponding `?GL_POST_CONVOLUTION_c_SCALE' parameters and biased by their -%% corresponding `?GL_POST_CONVOLUTION_c_BIAS' parameters (where `c' takes on the -%% values `RED', `GREEN', `BLUE', and `ALPHA'). These parameters are -%% set by {@link gl:pixelTransferf/2} . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionFilter1D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glConvolutionFilter1D.xml">external</a> documentation. -spec convolutionFilter1D(Target, Internalformat, Width, Format, Type, Image) -> 'ok' when Target :: enum(),Internalformat :: enum(),Width :: integer(),Format :: enum(),Type :: enum(),Image :: offset()|mem(). convolutionFilter1D(Target,Internalformat,Width,Format,Type,Image) when is_integer(Image) -> cast(5335, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Format:?GLenum,Type:?GLenum,Image:?GLuint>>); @@ -8449,51 +3301,7 @@ convolutionFilter1D(Target,Internalformat,Width,Format,Type,Image) -> %% ``gl:convolutionFilter2D'' builds a two-dimensional convolution filter kernel from an %% array of pixels. %% -%% The pixel array specified by `Width' , `Height' , `Format' , `Type' , -%% and `Data' is extracted from memory and processed just as if {@link gl:drawPixels/5} -%% were called, but processing stops after the final expansion to RGBA is completed. -%% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a convolution filter is specified, `Data' is -%% treated as a byte offset into the buffer object's data store. -%% -%% The R, G, B, and A components of each pixel are next scaled by the four 2D `?GL_CONVOLUTION_FILTER_SCALE' -%% parameters and biased by the four 2D `?GL_CONVOLUTION_FILTER_BIAS' parameters. (The -%% scale and bias parameters are set by {@link gl:convolutionParameterf/3} using the `?GL_CONVOLUTION_2D' -%% target and the names `?GL_CONVOLUTION_FILTER_SCALE' and `?GL_CONVOLUTION_FILTER_BIAS' -%% . The parameters themselves are vectors of four values that are applied to red, green, -%% blue, and alpha, in that order.) The R, G, B, and A values are not clamped to [0,1] at -%% any time during this process. -%% -%% Each pixel is then converted to the internal format specified by `Internalformat' . -%% This conversion simply maps the component values of the pixel (R, G, B, and A) to the -%% values included in the internal format (red, green, blue, alpha, luminance, and intensity). -%% The mapping is as follows: -%% -%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td> -%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity ' -%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td> -%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td> -%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td> -%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td> -%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td> -%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td> -%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table> -%% -%% The red, green, blue, alpha, luminance, and/or intensity components of the resulting -%% pixels are stored in floating-point rather than integer format. They form a two-dimensional -%% filter kernel image indexed with coordinates `i' and `j' such that `i' -%% starts at zero and increases from left to right, and `j' starts at zero and increases -%% from bottom to top. Kernel location `i,j' is derived from the `N'th pixel, where -%% `N' is `i'+`j'* `Width' . -%% -%% Note that after a convolution is performed, the resulting color components are also scaled -%% by their corresponding `?GL_POST_CONVOLUTION_c_SCALE' parameters and biased by their -%% corresponding `?GL_POST_CONVOLUTION_c_BIAS' parameters (where `c' takes on the -%% values `RED', `GREEN', `BLUE', and `ALPHA'). These parameters are -%% set by {@link gl:pixelTransferf/2} . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionFilter2D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glConvolutionFilter2D.xml">external</a> documentation. -spec convolutionFilter2D(Target, Internalformat, Width, Height, Format, Type, Image) -> 'ok' when Target :: enum(),Internalformat :: enum(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Image :: offset()|mem(). convolutionFilter2D(Target,Internalformat,Width,Height,Format,Type,Image) when is_integer(Image) -> cast(5337, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum,Image:?GLuint>>); @@ -8505,36 +3313,7 @@ convolutionFilter2D(Target,Internalformat,Width,Height,Format,Type,Image) -> %% %% ``gl:convolutionParameter'' sets the value of a convolution parameter. %% -%% `Target' selects the convolution filter to be affected: `?GL_CONVOLUTION_1D', `?GL_CONVOLUTION_2D' -%% , or `?GL_SEPARABLE_2D' for the 1D, 2D, or separable 2D filter, respectively. -%% -%% `Pname' selects the parameter to be changed. `?GL_CONVOLUTION_FILTER_SCALE' -%% and `?GL_CONVOLUTION_FILTER_BIAS' affect the definition of the convolution filter -%% kernel; see {@link gl:convolutionFilter1D/6} , {@link gl:convolutionFilter2D/7} , and {@link gl:separableFilter2D/8} -%% for details. In these cases, `Params' v is an array of four values to be applied -%% to red, green, blue, and alpha values, respectively. The initial value for `?GL_CONVOLUTION_FILTER_SCALE' -%% is (1, 1, 1, 1), and the initial value for `?GL_CONVOLUTION_FILTER_BIAS' is (0, -%% 0, 0, 0). -%% -%% A `Pname' value of `?GL_CONVOLUTION_BORDER_MODE' controls the convolution border -%% mode. The accepted modes are: -%% -%% `?GL_REDUCE': The image resulting from convolution is smaller than the source image. -%% If the filter width is Wf and height is Hf, and the source image width is Ws and -%% height is Hs, then the convolved image width will be Ws-Wf+1 and height will be Hs-Hf -%% +1. (If this reduction would generate an image with zero or negative width and/or height, -%% the output is simply null, with no error generated.) The coordinates of the image resulting -%% from convolution are zero through Ws-Wf in width and zero through Hs-Hf in height. -%% -%% `?GL_CONSTANT_BORDER': The image resulting from convolution is the same size as -%% the source image, and processed as if the source image were surrounded by pixels with -%% their color specified by the `?GL_CONVOLUTION_BORDER_COLOR'. -%% -%% `?GL_REPLICATE_BORDER': The image resulting from convolution is the same size as -%% the source image, and processed as if the outermost pixel on the border of the source -%% image were replicated. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glConvolutionParameter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glConvolutionParameter.xml">external</a> documentation. -spec convolutionParameterf(Target, Pname, Params) -> 'ok' when Target :: enum(),Pname :: enum(),Params :: tuple(). convolutionParameterf(Target,Pname,Params) -> cast(5339, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint, @@ -8561,49 +3340,7 @@ convolutionParameteriv(Target,Pname,{Params}) -> convolutionParameteri(Target,P %% pixels from the current `?GL_READ_BUFFER' (rather than from main memory, as is the %% case for {@link gl:convolutionFilter1D/6} ). %% -%% The screen-aligned pixel rectangle with lower-left corner at ( `X' , `Y' ), width -%% `Width' and height 1 is used to define the convolution filter. If any pixels within -%% this region are outside the window that is associated with the GL context, the values -%% obtained for those pixels are undefined. -%% -%% The pixels in the rectangle are processed exactly as if {@link gl:readPixels/7} had been -%% called with `format' set to RGBA, but the process stops just before final conversion. -%% The R, G, B, and A components of each pixel are next scaled by the four 1D `?GL_CONVOLUTION_FILTER_SCALE' -%% parameters and biased by the four 1D `?GL_CONVOLUTION_FILTER_BIAS' parameters. (The -%% scale and bias parameters are set by {@link gl:convolutionParameterf/3} using the `?GL_CONVOLUTION_1D' -%% target and the names `?GL_CONVOLUTION_FILTER_SCALE' and `?GL_CONVOLUTION_FILTER_BIAS' -%% . The parameters themselves are vectors of four values that are applied to red, green, -%% blue, and alpha, in that order.) The R, G, B, and A values are not clamped to [0,1] at -%% any time during this process. -%% -%% Each pixel is then converted to the internal format specified by `Internalformat' . -%% This conversion simply maps the component values of the pixel (R, G, B, and A) to the -%% values included in the internal format (red, green, blue, alpha, luminance, and intensity). -%% The mapping is as follows: -%% -%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td> -%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity ' -%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td> -%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td> -%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td> -%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td> -%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td> -%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td> -%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table> -%% -%% The red, green, blue, alpha, luminance, and/or intensity components of the resulting -%% pixels are stored in floating-point rather than integer format. -%% -%% Pixel ordering is such that lower x screen coordinates correspond to lower `i' filter -%% image coordinates. -%% -%% Note that after a convolution is performed, the resulting color components are also scaled -%% by their corresponding `?GL_POST_CONVOLUTION_c_SCALE' parameters and biased by their -%% corresponding `?GL_POST_CONVOLUTION_c_BIAS' parameters (where `c' takes on the -%% values `RED', `GREEN', `BLUE', and `ALPHA'). These parameters are -%% set by {@link gl:pixelTransferf/2} . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyConvolutionFilter1D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glCopyConvolutionFilter1D.xml">external</a> documentation. -spec copyConvolutionFilter1D(Target, Internalformat, X, Y, Width) -> 'ok' when Target :: enum(),Internalformat :: enum(),X :: integer(),Y :: integer(),Width :: integer(). copyConvolutionFilter1D(Target,Internalformat,X,Y,Width) -> cast(5341, <<Target:?GLenum,Internalformat:?GLenum,X:?GLint,Y:?GLint,Width:?GLsizei>>). @@ -8614,50 +3351,7 @@ copyConvolutionFilter1D(Target,Internalformat,X,Y,Width) -> %% pixels from the current `?GL_READ_BUFFER' (rather than from main memory, as is the %% case for {@link gl:convolutionFilter2D/7} ). %% -%% The screen-aligned pixel rectangle with lower-left corner at ( `X' , `Y' ), width -%% `Width' and height `Height' is used to define the convolution filter. If any -%% pixels within this region are outside the window that is associated with the GL context, -%% the values obtained for those pixels are undefined. -%% -%% The pixels in the rectangle are processed exactly as if {@link gl:readPixels/7} had been -%% called with `format' set to RGBA, but the process stops just before final conversion. -%% The R, G, B, and A components of each pixel are next scaled by the four 2D `?GL_CONVOLUTION_FILTER_SCALE' -%% parameters and biased by the four 2D `?GL_CONVOLUTION_FILTER_BIAS' parameters. (The -%% scale and bias parameters are set by {@link gl:convolutionParameterf/3} using the `?GL_CONVOLUTION_2D' -%% target and the names `?GL_CONVOLUTION_FILTER_SCALE' and `?GL_CONVOLUTION_FILTER_BIAS' -%% . The parameters themselves are vectors of four values that are applied to red, green, -%% blue, and alpha, in that order.) The R, G, B, and A values are not clamped to [0,1] at -%% any time during this process. -%% -%% Each pixel is then converted to the internal format specified by `Internalformat' . -%% This conversion simply maps the component values of the pixel (R, G, B, and A) to the -%% values included in the internal format (red, green, blue, alpha, luminance, and intensity). -%% The mapping is as follows: -%% -%% <table><tbody><tr><td>` Internal Format '</td><td>` Red '</td><td>` Green '</td> -%% <td>` Blue '</td><td>` Alpha '</td><td>` Luminance '</td><td>` Intensity ' -%% </td></tr></tbody><tbody><tr><td>`?GL_ALPHA'</td><td></td><td></td><td></td><td> A </td> -%% <td></td><td></td></tr><tr><td>`?GL_LUMINANCE'</td><td></td><td></td><td></td><td></td> -%% <td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td><td></td><td></td><td></td> -%% <td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY'</td><td></td><td></td><td> -%% </td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td><td> R </td><td> G </td> -%% <td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA'</td><td> R </td><td> -%% G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table> -%% -%% The red, green, blue, alpha, luminance, and/or intensity components of the resulting -%% pixels are stored in floating-point rather than integer format. -%% -%% Pixel ordering is such that lower x screen coordinates correspond to lower `i' filter -%% image coordinates, and lower y screen coordinates correspond to lower `j' filter -%% image coordinates. -%% -%% Note that after a convolution is performed, the resulting color components are also scaled -%% by their corresponding `?GL_POST_CONVOLUTION_c_SCALE' parameters and biased by their -%% corresponding `?GL_POST_CONVOLUTION_c_BIAS' parameters (where `c' takes on the -%% values `RED', `GREEN', `BLUE', and `ALPHA'). These parameters are -%% set by {@link gl:pixelTransferf/2} . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyConvolutionFilter2D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glCopyConvolutionFilter2D.xml">external</a> documentation. -spec copyConvolutionFilter2D(Target, Internalformat, X, Y, Width, Height) -> 'ok' when Target :: enum(),Internalformat :: enum(),X :: integer(),Y :: integer(),Width :: integer(),Height :: integer(). copyConvolutionFilter2D(Target,Internalformat,X,Y,Width,Height) -> cast(5342, <<Target:?GLenum,Internalformat:?GLenum,X:?GLint,Y:?GLint,Width:?GLsizei,Height:?GLsizei>>). @@ -8669,21 +3363,7 @@ copyConvolutionFilter2D(Target,Internalformat,X,Y,Width,Height) -> %% specifications in `Format' and `Type' . No pixel transfer operations are performed %% on this image, but the relevant pixel storage modes are applied. %% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a convolution filter is requested, `Image' is -%% treated as a byte offset into the buffer object's data store. -%% -%% Color components that are present in `Format' but not included in the internal format -%% of the filter are returned as zero. The assignments of internal color components to the -%% components of `Format' are as follows. <table><tbody><tr><td>` Internal Component ' -%% </td><td>` Resulting Component '</td></tr></tbody><tbody><tr><td> Red </td><td> Red </td> -%% </tr><tr><td> Green </td><td> Green </td></tr><tr><td> Blue </td><td> Blue </td></tr><tr><td> -%% Alpha </td><td> Alpha </td></tr><tr><td> Luminance </td><td> Red </td></tr><tr><td> Intensity -%% </td><td> Red </td></tr></tbody></table> -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetConvolutionFilter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetConvolutionFilter.xml">external</a> documentation. -spec getConvolutionFilter(Target, Format, Type, Image) -> 'ok' when Target :: enum(),Format :: enum(),Type :: enum(),Image :: mem(). getConvolutionFilter(Target,Format,Type,Image) -> send_bin(Image), @@ -8695,34 +3375,7 @@ getConvolutionFilter(Target,Format,Type,Image) -> %% which convolution filter is queried. `Pname' determines which parameter is returned: %% %% -%% `?GL_CONVOLUTION_BORDER_MODE': The convolution border mode. See {@link gl:convolutionParameterf/3} -%% for a list of border modes. -%% -%% `?GL_CONVOLUTION_BORDER_COLOR': The current convolution border color. `Params' -%% must be a pointer to an array of four elements, which will receive the red, green, blue, -%% and alpha border colors. -%% -%% `?GL_CONVOLUTION_FILTER_SCALE': The current filter scale factors. `Params' -%% must be a pointer to an array of four elements, which will receive the red, green, blue, -%% and alpha filter scale factors in that order. -%% -%% `?GL_CONVOLUTION_FILTER_BIAS': The current filter bias factors. `Params' must -%% be a pointer to an array of four elements, which will receive the red, green, blue, and -%% alpha filter bias terms in that order. -%% -%% `?GL_CONVOLUTION_FORMAT': The current internal format. See {@link gl:convolutionFilter1D/6} -%% , {@link gl:convolutionFilter2D/7} , and {@link gl:separableFilter2D/8} for lists of allowable -%% formats. -%% -%% `?GL_CONVOLUTION_WIDTH': The current filter image width. -%% -%% `?GL_CONVOLUTION_HEIGHT': The current filter image height. -%% -%% `?GL_MAX_CONVOLUTION_WIDTH': The maximum acceptable filter image width. -%% -%% `?GL_MAX_CONVOLUTION_HEIGHT': The maximum acceptable filter image height. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetConvolutionParameter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetConvolutionParameter.xml">external</a> documentation. -spec getConvolutionParameterfv(Target, Pname) -> {float(),float(),float(),float()} when Target :: enum(),Pname :: enum(). getConvolutionParameterfv(Target,Pname) -> call(5344, <<Target:?GLenum,Pname:?GLenum>>). @@ -8738,52 +3391,7 @@ getConvolutionParameteriv(Target,Pname) -> %% ``gl:separableFilter2D'' builds a two-dimensional separable convolution filter kernel %% from two arrays of pixels. %% -%% The pixel arrays specified by ( `Width' , `Format' , `Type' , `Row' ) -%% and ( `Height' , `Format' , `Type' , `Column' ) are processed just as if -%% they had been passed to {@link gl:drawPixels/5} , but processing stops after the final expansion -%% to RGBA is completed. -%% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a convolution filter is specified, `Row' and `Column' -%% are treated as byte offsets into the buffer object's data store. -%% -%% Next, the R, G, B, and A components of all pixels in both arrays are scaled by the four -%% separable 2D `?GL_CONVOLUTION_FILTER_SCALE' parameters and biased by the four separable -%% 2D `?GL_CONVOLUTION_FILTER_BIAS' parameters. (The scale and bias parameters are set -%% by {@link gl:convolutionParameterf/3} using the `?GL_SEPARABLE_2D' target and the names -%% `?GL_CONVOLUTION_FILTER_SCALE' and `?GL_CONVOLUTION_FILTER_BIAS'. The parameters -%% themselves are vectors of four values that are applied to red, green, blue, and alpha, -%% in that order.) The R, G, B, and A values are not clamped to [0,1] at any time during -%% this process. -%% -%% Each pixel is then converted to the internal format specified by `Internalformat' . -%% This conversion simply maps the component values of the pixel (R, G, B, and A) to the -%% values included in the internal format (red, green, blue, alpha, luminance, and intensity). -%% The mapping is as follows: <table><tbody><tr><td>` Internal Format '</td><td>` Red ' -%% </td><td>` Green '</td><td>` Blue '</td><td>` Alpha '</td><td>` Luminance ' -%% </td><td>` Intensity '</td></tr></tbody><tbody><tr><td>`?GL_LUMINANCE'</td><td></td> -%% <td></td><td></td><td></td><td> R </td><td></td></tr><tr><td>`?GL_LUMINANCE_ALPHA'</td> -%% <td></td><td></td><td></td><td> A </td><td> R </td><td></td></tr><tr><td>`?GL_INTENSITY' -%% </td><td></td><td></td><td></td><td></td><td></td><td> R </td></tr><tr><td>`?GL_RGB'</td> -%% <td> R </td><td> G </td><td> B </td><td></td><td></td><td></td></tr><tr><td>`?GL_RGBA' -%% </td><td> R </td><td> G </td><td> B </td><td> A </td><td></td><td></td></tr></tbody></table> -%% -%% -%% The red, green, blue, alpha, luminance, and/or intensity components of the resulting -%% pixels are stored in floating-point rather than integer format. They form two one-dimensional -%% filter kernel images. The row image is indexed by coordinate `i' starting at zero -%% and increasing from left to right. Each location in the row image is derived from element -%% `i' of `Row' . The column image is indexed by coordinate `j' starting at -%% zero and increasing from bottom to top. Each location in the column image is derived from -%% element `j' of `Column' . -%% -%% Note that after a convolution is performed, the resulting color components are also scaled -%% by their corresponding `?GL_POST_CONVOLUTION_c_SCALE' parameters and biased by their -%% corresponding `?GL_POST_CONVOLUTION_c_BIAS' parameters (where `c' takes on the -%% values `RED', `GREEN', `BLUE', and `ALPHA'). These parameters are -%% set by {@link gl:pixelTransferf/2} . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSeparableFilter2D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glSeparableFilter2D.xml">external</a> documentation. -spec separableFilter2D(Target, Internalformat, Width, Height, Format, Type, Row, Column) -> 'ok' when Target :: enum(),Internalformat :: enum(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Row :: offset()|mem(),Column :: offset()|mem(). separableFilter2D(Target,Internalformat,Width,Height,Format,Type,Row,Column) when is_integer(Row), is_integer(Column) -> cast(5346, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,Type:?GLenum,Row:?GLuint,Column:?GLuint>>); @@ -8798,21 +3406,7 @@ separableFilter2D(Target,Internalformat,Width,Height,Format,Type,Row,Column) -> %% the same width as the histogram. No pixel transfer operations are performed on this image, %% but pixel storage modes that are applicable to 1D images are honored. %% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a histogram table is requested, `Values' is treated -%% as a byte offset into the buffer object's data store. -%% -%% Color components that are requested in the specified `Format' , but which are not -%% included in the internal format of the histogram, are returned as zero. The assignments -%% of internal color components to the components requested by `Format' are: <table><tbody> -%% <tr><td>` Internal Component '</td><td>` Resulting Component '</td></tr></tbody> -%% <tbody><tr><td> Red </td><td> Red </td></tr><tr><td> Green </td><td> Green </td></tr><tr><td> -%% Blue </td><td> Blue </td></tr><tr><td> Alpha </td><td> Alpha </td></tr><tr><td> Luminance -%% </td><td> Red </td></tr></tbody></table> -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetHistogram.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetHistogram.xml">external</a> documentation. -spec getHistogram(Target, Reset, Format, Type, Values) -> 'ok' when Target :: enum(),Reset :: 0|1,Format :: enum(),Type :: enum(),Values :: mem(). getHistogram(Target,Reset,Format,Type,Values) -> send_bin(Values), @@ -8826,19 +3420,7 @@ getHistogram(Target,Reset,Format,Type,Values) -> %% table) or `?GL_PROXY_HISTOGRAM' (to obtain information from the most recent proxy %% request) and one of the following values for the `Pname' argument: %% -%% <table><tbody><tr><td>` Parameter '</td><td>` Description '</td></tr></tbody><tbody> -%% <tr><td>`?GL_HISTOGRAM_WIDTH'</td><td> Histogram table width </td></tr><tr><td>`?GL_HISTOGRAM_FORMAT' -%% </td><td> Internal format </td></tr><tr><td>`?GL_HISTOGRAM_RED_SIZE'</td><td> Red -%% component counter size, in bits </td></tr><tr><td>`?GL_HISTOGRAM_GREEN_SIZE'</td><td> -%% Green component counter size, in bits </td></tr><tr><td>`?GL_HISTOGRAM_BLUE_SIZE'</td> -%% <td> Blue component counter size, in bits </td></tr><tr><td>`?GL_HISTOGRAM_ALPHA_SIZE' -%% </td><td> Alpha component counter size, in bits </td></tr><tr><td>`?GL_HISTOGRAM_LUMINANCE_SIZE' -%% </td><td> Luminance component counter size, in bits </td></tr><tr><td>`?GL_HISTOGRAM_SINK' -%% </td><td> Value of the `sink' parameter </td></tr></tbody></table> -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetHistogramParameter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetHistogramParameter.xml">external</a> documentation. -spec getHistogramParameterfv(Target, Pname) -> {float()} when Target :: enum(),Pname :: enum(). getHistogramParameterfv(Target,Pname) -> call(5349, <<Target:?GLenum,Pname:?GLenum>>). @@ -8857,26 +3439,7 @@ getHistogramParameteriv(Target,Pname) -> %% of the return values is determined by `Format' , and their type is determined by `Types' %% . %% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while minimum and maximum pixel values are requested, `Values' -%% is treated as a byte offset into the buffer object's data store. -%% -%% No pixel transfer operations are performed on the return values, but pixel storage modes -%% that are applicable to one-dimensional images are performed. Color components that are -%% requested in the specified `Format' , but that are not included in the internal format -%% of the minmax table, are returned as zero. The assignment of internal color components -%% to the components requested by `Format' are as follows: -%% -%% <table><tbody><tr><td>` Internal Component '</td><td>` Resulting Component '</td> -%% </tr></tbody><tbody><tr><td> Red </td><td> Red </td></tr><tr><td> Green </td><td> Green </td> -%% </tr><tr><td> Blue </td><td> Blue </td></tr><tr><td> Alpha </td><td> Alpha </td></tr><tr><td> -%% Luminance </td><td> Red </td></tr></tbody></table> -%% -%% If `Reset' is `?GL_TRUE', the minmax table entries corresponding to the return -%% values are reset to their initial values. Minimum and maximum values that are not returned -%% are not modified, even if `Reset' is `?GL_TRUE'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMinmax.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetMinmax.xml">external</a> documentation. -spec getMinmax(Target, Reset, Format, Types, Values) -> 'ok' when Target :: enum(),Reset :: 0|1,Format :: enum(),Types :: enum(),Values :: mem(). getMinmax(Target,Reset,Format,Types,Values) -> send_bin(Values), @@ -8887,14 +3450,7 @@ getMinmax(Target,Reset,Format,Types,Values) -> %% ``gl:getMinmaxParameter'' retrieves parameters for the current minmax table by setting `Pname' %% to one of the following values: %% -%% <table><tbody><tr><td>` Parameter '</td><td>` Description '</td></tr></tbody><tbody> -%% <tr><td>`?GL_MINMAX_FORMAT'</td><td> Internal format of minmax table </td></tr><tr><td> -%% `?GL_MINMAX_SINK'</td><td> Value of the `sink' parameter </td></tr></tbody></table> -%% -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMinmaxParameter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetMinmaxParameter.xml">external</a> documentation. -spec getMinmaxParameterfv(Target, Pname) -> {float()} when Target :: enum(),Pname :: enum(). getMinmaxParameterfv(Target,Pname) -> call(5352, <<Target:?GLenum,Pname:?GLenum>>). @@ -8915,26 +3471,7 @@ getMinmaxParameteriv(Target,Pname) -> %% to be incremented.) If a histogram table entry is incremented beyond its maximum value, %% then its value becomes undefined. (This is not an error.) %% -%% Histogramming is performed only for RGBA pixels (though these may be specified originally -%% as color indices and converted to RGBA by index table lookup). Histogramming is enabled -%% with {@link gl:enable/1} and disabled with {@link gl:enable/1} . -%% -%% When `Target' is `?GL_HISTOGRAM', ``gl:histogram'' redefines the current -%% histogram table to have `Width' entries of the format specified by `Internalformat' -%% . The entries are indexed 0 through width-1, and all entries are initialized to zero. -%% The values in the previous histogram table, if any, are lost. If `Sink' is `?GL_TRUE' -%% , then pixels are discarded after histogramming; no further processing of the pixels takes -%% place, and no drawing, texture loading, or pixel readback will result. -%% -%% When `Target' is `?GL_PROXY_HISTOGRAM', ``gl:histogram'' computes all state -%% information as if the histogram table were to be redefined, but does not actually define -%% the new table. If the requested histogram table is too large to be supported, then the -%% state information will be set to zero. This provides a way to determine if a histogram -%% table with the given parameters can be supported. -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glHistogram.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glHistogram.xml">external</a> documentation. -spec histogram(Target, Width, Internalformat, Sink) -> 'ok' when Target :: enum(),Width :: integer(),Internalformat :: enum(),Sink :: 0|1. histogram(Target,Width,Internalformat,Sink) -> cast(5354, <<Target:?GLenum,Width:?GLsizei,Internalformat:?GLenum,Sink:?GLboolean>>). @@ -8954,16 +3491,7 @@ histogram(Target,Width,Internalformat,Sink) -> %% calling {@link gl:enable/1} or {@link gl:enable/1} , respectively, with an argument of `?GL_MINMAX' %% . %% -%% ``gl:minmax'' redefines the current minmax table to have entries of the format specified -%% by `Internalformat' . The maximum element is initialized with the smallest possible -%% component values, and the minimum element is initialized with the largest possible component -%% values. The values in the previous minmax table, if any, are lost. If `Sink' is `?GL_TRUE' -%% , then pixels are discarded after minmax; no further processing of the pixels takes place, -%% and no drawing, texture loading, or pixel readback will result. -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMinmax.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glMinmax.xml">external</a> documentation. -spec minmax(Target, Internalformat, Sink) -> 'ok' when Target :: enum(),Internalformat :: enum(),Sink :: 0|1. minmax(Target,Internalformat,Sink) -> cast(5355, <<Target:?GLenum,Internalformat:?GLenum,Sink:?GLboolean>>). @@ -8972,7 +3500,7 @@ minmax(Target,Internalformat,Sink) -> %% %% ``gl:resetHistogram'' resets all the elements of the current histogram table to zero. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glResetHistogram.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glResetHistogram.xml">external</a> documentation. -spec resetHistogram(Target) -> 'ok' when Target :: enum(). resetHistogram(Target) -> cast(5356, <<Target:?GLenum>>). @@ -8983,7 +3511,7 @@ resetHistogram(Target) -> %% values: the ``maximum'' element receives the minimum possible component values, and the %% ``minimum'' element receives the maximum possible component values. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glResetMinmax.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glResetMinmax.xml">external</a> documentation. -spec resetMinmax(Target) -> 'ok' when Target :: enum(). resetMinmax(Target) -> cast(5357, <<Target:?GLenum>>). @@ -8994,7 +3522,7 @@ resetMinmax(Target) -> %% affect. The number of texture units an implementation supports is implementation dependent, %% but must be at least 80. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glActiveTexture.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glActiveTexture.xhtml">external</a> documentation. -spec activeTexture(Texture) -> 'ok' when Texture :: enum(). activeTexture(Texture) -> cast(5358, <<Texture:?GLenum>>). @@ -9005,22 +3533,7 @@ activeTexture(Texture) -> %% locations to generate antialiasing effects. Multisampling transparently antialiases points, %% lines, polygons, and images if it is enabled. %% -%% `Value' is used in constructing a temporary mask used in determining which samples -%% will be used in resolving the final fragment color. This mask is bitwise-anded with the -%% coverage mask generated from the multisampling computation. If the `Invert' flag -%% is set, the temporary mask is inverted (all bits flipped) and then the bitwise-and is -%% computed. -%% -%% If an implementation does not have any multisample buffers available, or multisampling -%% is disabled, rasterization occurs with only a single sample computing a pixel's final -%% RGB color. -%% -%% Provided an implementation supports multisample buffers, and multisampling is enabled, -%% then a pixel's final color is generated by combining several samples per pixel. Each sample -%% contains color, depth, and stencil information, allowing those operations to be performed -%% on each sample. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSampleCoverage.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glSampleCoverage.xhtml">external</a> documentation. -spec sampleCoverage(Value, Invert) -> 'ok' when Value :: clamp(),Invert :: 0|1. sampleCoverage(Value,Invert) -> cast(5359, <<Value:?GLclampf,Invert:?GLboolean>>). @@ -9029,56 +3542,7 @@ sampleCoverage(Value,Invert) -> %% %% Texturing allows elements of an image array to be read by shaders. %% -%% ``gl:compressedTexImage3D'' loads a previously defined, and retrieved, compressed three-dimensional -%% texture image if `Target' is `?GL_TEXTURE_3D' (see {@link gl:texImage3D/10} ). -%% -%% If `Target' is `?GL_TEXTURE_2D_ARRAY', `Data' is treated as an array of -%% compressed 2D textures. -%% -%% If `Target' is `?GL_PROXY_TEXTURE_3D' or `?GL_PROXY_TEXTURE_2D_ARRAY', -%% no data is read from `Data' , but all of the texture image state is recalculated, -%% checked for consistency, and checked against the implementation's capabilities. If the -%% implementation cannot handle a texture of the requested texture size, it sets all of the -%% image state to 0, but does not generate an error (see {@link gl:getError/0} ). To query -%% for an entire mipmap array, use an image array level greater than or equal to 1. -%% -%% `Internalformat' must be a known compressed image format (such as `?GL_RGTC') -%% or an extension-specified compressed-texture format. When a texture is loaded with {@link gl:texImage2D/9} -%% using a generic compressed texture format (e.g., `?GL_COMPRESSED_RGB'), the GL selects -%% from one of its extensions supporting compressed textures. In order to load the compressed -%% texture image using ``gl:compressedTexImage3D'', query the compressed texture image's -%% size and format using {@link gl:getTexLevelParameterfv/3} . -%% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated -%% as a byte offset into the buffer object's data store. -%% -%% If the compressed data are arranged into fixed-size blocks of texels, the pixel storage -%% modes can be used to select a sub-rectangle from a larger containing rectangle. These -%% pixel storage modes operate in the same way as they do for {@link gl:texImage1D/8} . In -%% the following description, denote by b s, b w, b h, and b d, the values of pixel storage -%% modes `?GL_UNPACK_COMPRESSED_BLOCK_SIZE', `?GL_UNPACK_COMPRESSED_BLOCK_WIDTH', `?GL_UNPACK_COMPRESSED_BLOCK_HEIGHT' -%% , and `?GL_UNPACK_COMPRESSED_BLOCK_DEPTH', respectively. b s is the compressed block -%% size in bytes; b w, b h, and b d are the compressed block width, height, and depth -%% in pixels. -%% -%% By default the pixel storage modes `?GL_UNPACK_ROW_LENGTH', `?GL_UNPACK_SKIP_ROWS' -%% , `?GL_UNPACK_SKIP_PIXELS', `?GL_UNPACK_IMAGE_HEIGHT' and `?GL_UNPACK_SKIP_IMAGES' -%% are ignored for compressed images. To enable `?GL_UNPACK_SKIP_PIXELS' and `?GL_UNPACK_ROW_LENGTH' -%% , b s and b w must both be non-zero. To also enable `?GL_UNPACK_SKIP_ROWS' and `?GL_UNPACK_IMAGE_HEIGHT' -%% , b h must be non-zero. To also enable `?GL_UNPACK_SKIP_IMAGES', b d must be non-zero. -%% All parameters must be consistent with the compressed format to produce the desired results. -%% -%% -%% When selecting a sub-rectangle from a compressed image: the value of `?GL_UNPACK_SKIP_PIXELS' -%% must be a multiple of b w;the value of `?GL_UNPACK_SKIP_ROWS' must be a multiple -%% of b w;the value of `?GL_UNPACK_SKIP_IMAGES' must be a multiple of b w. -%% -%% `ImageSize' must be equal to: -%% -%% b s×|width b/w|×|height b/h|×|depth b/d| -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage3D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCompressedTexImage3D.xhtml">external</a> documentation. -spec compressedTexImage3D(Target, Level, Internalformat, Width, Height, Depth, Border, ImageSize, Data) -> 'ok' when Target :: enum(),Level :: integer(),Internalformat :: enum(),Width :: integer(),Height :: integer(),Depth :: integer(),Border :: integer(),ImageSize :: integer(),Data :: offset()|mem(). compressedTexImage3D(Target,Level,Internalformat,Width,Height,Depth,Border,ImageSize,Data) when is_integer(Data) -> cast(5360, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Border:?GLint,ImageSize:?GLsizei,Data:?GLuint>>); @@ -9090,57 +3554,7 @@ compressedTexImage3D(Target,Level,Internalformat,Width,Height,Depth,Border,Image %% %% Texturing allows elements of an image array to be read by shaders. %% -%% ``gl:compressedTexImage2D'' loads a previously defined, and retrieved, compressed two-dimensional -%% texture image if `Target' is `?GL_TEXTURE_2D', or one of the cube map faces -%% such as `?GL_TEXTURE_CUBE_MAP_POSITIVE_X'. (see {@link gl:texImage2D/9} ). -%% -%% If `Target' is `?GL_TEXTURE_1D_ARRAY', `Data' is treated as an array of -%% compressed 1D textures. -%% -%% If `Target' is `?GL_PROXY_TEXTURE_2D', `?GL_PROXY_TEXTURE_1D_ARRAY' or `?GL_PROXY_CUBE_MAP' -%% , no data is read from `Data' , but all of the texture image state is recalculated, -%% checked for consistency, and checked against the implementation's capabilities. If the -%% implementation cannot handle a texture of the requested texture size, it sets all of the -%% image state to 0, but does not generate an error (see {@link gl:getError/0} ). To query -%% for an entire mipmap array, use an image array level greater than or equal to 1. -%% -%% `Internalformat' must be a known compressed image format (such as `?GL_RGTC') -%% or an extension-specified compressed-texture format. When a texture is loaded with {@link gl:texImage2D/9} -%% using a generic compressed texture format (e.g., `?GL_COMPRESSED_RGB'), the GL selects -%% from one of its extensions supporting compressed textures. In order to load the compressed -%% texture image using ``gl:compressedTexImage2D'', query the compressed texture image's -%% size and format using {@link gl:getTexLevelParameterfv/3} . -%% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated -%% as a byte offset into the buffer object's data store. -%% -%% If the compressed data are arranged into fixed-size blocks of texels, the pixel storage -%% modes can be used to select a sub-rectangle from a larger containing rectangle. These -%% pixel storage modes operate in the same way as they do for {@link gl:texImage2D/9} . In -%% the following description, denote by b s, b w, b h, and b d, the values of pixel storage -%% modes `?GL_UNPACK_COMPRESSED_BLOCK_SIZE', `?GL_UNPACK_COMPRESSED_BLOCK_WIDTH', `?GL_UNPACK_COMPRESSED_BLOCK_HEIGHT' -%% , and `?GL_UNPACK_COMPRESSED_BLOCK_DEPTH', respectively. b s is the compressed block -%% size in bytes; b w, b h, and b d are the compressed block width, height, and depth -%% in pixels. -%% -%% By default the pixel storage modes `?GL_UNPACK_ROW_LENGTH', `?GL_UNPACK_SKIP_ROWS' -%% , `?GL_UNPACK_SKIP_PIXELS', `?GL_UNPACK_IMAGE_HEIGHT' and `?GL_UNPACK_SKIP_IMAGES' -%% are ignored for compressed images. To enable `?GL_UNPACK_SKIP_PIXELS' and `?GL_UNPACK_ROW_LENGTH' -%% , b s and b w must both be non-zero. To also enable `?GL_UNPACK_SKIP_ROWS' and `?GL_UNPACK_IMAGE_HEIGHT' -%% , b h must be non-zero. To also enable `?GL_UNPACK_SKIP_IMAGES', b d must be non-zero. -%% All parameters must be consistent with the compressed format to produce the desired results. -%% -%% -%% When selecting a sub-rectangle from a compressed image: the value of `?GL_UNPACK_SKIP_PIXELS' -%% must be a multiple of b w;the value of `?GL_UNPACK_SKIP_ROWS' must be a multiple -%% of b w. -%% -%% `ImageSize' must be equal to: -%% -%% b s×|width b/w|×|height b/h| -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage2D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCompressedTexImage2D.xhtml">external</a> documentation. -spec compressedTexImage2D(Target, Level, Internalformat, Width, Height, Border, ImageSize, Data) -> 'ok' when Target :: enum(),Level :: integer(),Internalformat :: enum(),Width :: integer(),Height :: integer(),Border :: integer(),ImageSize :: integer(),Data :: offset()|mem(). compressedTexImage2D(Target,Level,Internalformat,Width,Height,Border,ImageSize,Data) when is_integer(Data) -> cast(5362, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Border:?GLint,ImageSize:?GLsizei,Data:?GLuint>>); @@ -9152,52 +3566,7 @@ compressedTexImage2D(Target,Level,Internalformat,Width,Height,Border,ImageSize,D %% %% Texturing allows elements of an image array to be read by shaders. %% -%% ``gl:compressedTexImage1D'' loads a previously defined, and retrieved, compressed one-dimensional -%% texture image if `Target' is `?GL_TEXTURE_1D' (see {@link gl:texImage1D/8} ). -%% -%% If `Target' is `?GL_PROXY_TEXTURE_1D', no data is read from `Data' , but -%% all of the texture image state is recalculated, checked for consistency, and checked against -%% the implementation's capabilities. If the implementation cannot handle a texture of the -%% requested texture size, it sets all of the image state to 0, but does not generate an -%% error (see {@link gl:getError/0} ). To query for an entire mipmap array, use an image array -%% level greater than or equal to 1. -%% -%% `Internalformat' must be an extension-specified compressed-texture format. When a -%% texture is loaded with {@link gl:texImage1D/8} using a generic compressed texture format -%% (e.g., `?GL_COMPRESSED_RGB') the GL selects from one of its extensions supporting -%% compressed textures. In order to load the compressed texture image using ``gl:compressedTexImage1D'' -%% , query the compressed texture image's size and format using {@link gl:getTexLevelParameterfv/3} -%% . -%% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated -%% as a byte offset into the buffer object's data store. -%% -%% If the compressed data are arranged into fixed-size blocks of texels, the pixel storage -%% modes can be used to select a sub-rectangle from a larger containing rectangle. These -%% pixel storage modes operate in the same way as they do for {@link gl:texImage1D/8} . In -%% the following description, denote by b s, b w, b h, and b d, the values of pixel storage -%% modes `?GL_UNPACK_COMPRESSED_BLOCK_SIZE', `?GL_UNPACK_COMPRESSED_BLOCK_WIDTH', `?GL_UNPACK_COMPRESSED_BLOCK_HEIGHT' -%% , and `?GL_UNPACK_COMPRESSED_BLOCK_DEPTH', respectively. b s is the compressed block -%% size in bytes; b w, b h, and b d are the compressed block width, height, and depth -%% in pixels. -%% -%% By default the pixel storage modes `?GL_UNPACK_ROW_LENGTH', `?GL_UNPACK_SKIP_ROWS' -%% , `?GL_UNPACK_SKIP_PIXELS', `?GL_UNPACK_IMAGE_HEIGHT' and `?GL_UNPACK_SKIP_IMAGES' -%% are ignored for compressed images. To enable `?GL_UNPACK_SKIP_PIXELS' and `?GL_UNPACK_ROW_LENGTH' -%% , b s and b w must both be non-zero. To also enable `?GL_UNPACK_SKIP_ROWS' and `?GL_UNPACK_IMAGE_HEIGHT' -%% , b h must be non-zero. To also enable `?GL_UNPACK_SKIP_IMAGES', b d must be non-zero. -%% All parameters must be consistent with the compressed format to produce the desired results. -%% -%% -%% When selecting a sub-rectangle from a compressed image: the value of `?GL_UNPACK_SKIP_PIXELS' -%% must be a multiple of b w; -%% -%% `ImageSize' must be equal to: -%% -%% b s×|width b/w| -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexImage1D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCompressedTexImage1D.xhtml">external</a> documentation. -spec compressedTexImage1D(Target, Level, Internalformat, Width, Border, ImageSize, Data) -> 'ok' when Target :: enum(),Level :: integer(),Internalformat :: enum(),Width :: integer(),Border :: integer(),ImageSize :: integer(),Data :: offset()|mem(). compressedTexImage1D(Target,Level,Internalformat,Width,Border,ImageSize,Data) when is_integer(Data) -> cast(5364, <<Target:?GLenum,Level:?GLint,Internalformat:?GLenum,Width:?GLsizei,Border:?GLint,ImageSize:?GLsizei,Data:?GLuint>>); @@ -9209,25 +3578,7 @@ compressedTexImage1D(Target,Level,Internalformat,Width,Border,ImageSize,Data) -> %% %% Texturing allows elements of an image array to be read by shaders. %% -%% ``gl:compressedTexSubImage3D'' redefines a contiguous subregion of an existing three-dimensional -%% texture image. The texels referenced by `Data' replace the portion of the existing -%% texture array with x indices `Xoffset' and xoffset+width-1, and the y indices `Yoffset' -%% and yoffset+height-1, and the z indices `Zoffset' and zoffset+depth-1, inclusive. -%% This region may not include any texels outside the range of the texture array as it was -%% originally specified. It is not an error to specify a subtexture with width of 0, but -%% such a specification has no effect. -%% -%% `Internalformat' must be a known compressed image format (such as `?GL_RGTC') -%% or an extension-specified compressed-texture format. The `Format' of the compressed -%% texture image is selected by the GL implementation that compressed it (see {@link gl:texImage3D/10} -%% ) and should be queried at the time the texture was compressed with {@link gl:getTexLevelParameterfv/3} -%% . -%% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated -%% as a byte offset into the buffer object's data store. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage3D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCompressedTexSubImage3D.xhtml">external</a> documentation. -spec compressedTexSubImage3D(Target, Level, Xoffset, Yoffset, Zoffset, Width, Height, Depth, Format, ImageSize, Data) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),Zoffset :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Format :: enum(),ImageSize :: integer(),Data :: offset()|mem(). compressedTexSubImage3D(Target,Level,Xoffset,Yoffset,Zoffset,Width,Height,Depth,Format,ImageSize,Data) when is_integer(Data) -> cast(5366, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Zoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Format:?GLenum,ImageSize:?GLsizei,Data:?GLuint>>); @@ -9239,24 +3590,7 @@ compressedTexSubImage3D(Target,Level,Xoffset,Yoffset,Zoffset,Width,Height,Depth, %% %% Texturing allows elements of an image array to be read by shaders. %% -%% ``gl:compressedTexSubImage2D'' redefines a contiguous subregion of an existing two-dimensional -%% texture image. The texels referenced by `Data' replace the portion of the existing -%% texture array with x indices `Xoffset' and xoffset+width-1, and the y indices `Yoffset' -%% and yoffset+height-1, inclusive. This region may not include any texels outside the -%% range of the texture array as it was originally specified. It is not an error to specify -%% a subtexture with width of 0, but such a specification has no effect. -%% -%% `Internalformat' must be a known compressed image format (such as `?GL_RGTC') -%% or an extension-specified compressed-texture format. The `Format' of the compressed -%% texture image is selected by the GL implementation that compressed it (see {@link gl:texImage2D/9} -%% ) and should be queried at the time the texture was compressed with {@link gl:getTexLevelParameterfv/3} -%% . -%% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated -%% as a byte offset into the buffer object's data store. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage2D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCompressedTexSubImage2D.xhtml">external</a> documentation. -spec compressedTexSubImage2D(Target, Level, Xoffset, Yoffset, Width, Height, Format, ImageSize, Data) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),Yoffset :: integer(),Width :: integer(),Height :: integer(),Format :: enum(),ImageSize :: integer(),Data :: offset()|mem(). compressedTexSubImage2D(Target,Level,Xoffset,Yoffset,Width,Height,Format,ImageSize,Data) when is_integer(Data) -> cast(5368, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Yoffset:?GLint,Width:?GLsizei,Height:?GLsizei,Format:?GLenum,ImageSize:?GLsizei,Data:?GLuint>>); @@ -9268,24 +3602,7 @@ compressedTexSubImage2D(Target,Level,Xoffset,Yoffset,Width,Height,Format,ImageSi %% %% Texturing allows elements of an image array to be read by shaders. %% -%% ``gl:compressedTexSubImage1D'' redefines a contiguous subregion of an existing one-dimensional -%% texture image. The texels referenced by `Data' replace the portion of the existing -%% texture array with x indices `Xoffset' and xoffset+width-1, inclusive. This region -%% may not include any texels outside the range of the texture array as it was originally -%% specified. It is not an error to specify a subtexture with width of 0, but such a specification -%% has no effect. -%% -%% `Internalformat' must be a known compressed image format (such as `?GL_RGTC') -%% or an extension-specified compressed-texture format. The `Format' of the compressed -%% texture image is selected by the GL implementation that compressed it (see {@link gl:texImage1D/8} -%% ), and should be queried at the time the texture was compressed with {@link gl:getTexLevelParameterfv/3} -%% . -%% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a texture image is specified, `Data' is treated -%% as a byte offset into the buffer object's data store. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompressedTexSubImage1D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCompressedTexSubImage1D.xhtml">external</a> documentation. -spec compressedTexSubImage1D(Target, Level, Xoffset, Width, Format, ImageSize, Data) -> 'ok' when Target :: enum(),Level :: integer(),Xoffset :: integer(),Width :: integer(),Format :: enum(),ImageSize :: integer(),Data :: offset()|mem(). compressedTexSubImage1D(Target,Level,Xoffset,Width,Format,ImageSize,Data) when is_integer(Data) -> cast(5370, <<Target:?GLenum,Level:?GLint,Xoffset:?GLint,Width:?GLsizei,Format:?GLenum,ImageSize:?GLsizei,Data:?GLuint>>); @@ -9302,20 +3619,7 @@ compressedTexSubImage1D(Target,Level,Xoffset,Width,Format,ImageSize,Data) -> %% ), or {@link gl:texImage3D/10} (`?GL_TEXTURE_3D'). `Lod' specifies the level-of-detail %% number of the desired image. %% -%% If a non-zero named buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target -%% (see {@link gl:bindBuffer/2} ) while a texture image is requested, `Img' is treated -%% as a byte offset into the buffer object's data store. -%% -%% To minimize errors, first verify that the texture is compressed by calling {@link gl:getTexLevelParameterfv/3} -%% with argument `?GL_TEXTURE_COMPRESSED'. If the texture is compressed, then determine -%% the amount of memory required to store the compressed texture by calling {@link gl:getTexLevelParameterfv/3} -%% with argument `?GL_TEXTURE_COMPRESSED_IMAGE_SIZE'. Finally, retrieve the internal -%% format of the texture by calling {@link gl:getTexLevelParameterfv/3} with argument `?GL_TEXTURE_INTERNAL_FORMAT' -%% . To store the texture for later use, associate the internal format and size with the -%% retrieved texture image. These data can be used by the respective texture or subtexture -%% loading routine used for loading `Target' textures. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetCompressedTexImage.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetCompressedTexImage.xhtml">external</a> documentation. -spec getCompressedTexImage(Target, Lod, Img) -> 'ok' when Target :: enum(),Lod :: integer(),Img :: mem(). getCompressedTexImage(Target,Lod,Img) -> send_bin(Img), @@ -9328,7 +3632,7 @@ getCompressedTexImage(Target,Lod,Img) -> %% or {@link gl:enableClientState/1} , respectively, when called with a parameter of `?GL_TEXTURE_COORD_ARRAY' %% . %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClientActiveTexture.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glClientActiveTexture.xml">external</a> documentation. -spec clientActiveTexture(Texture) -> 'ok' when Texture :: enum(). clientActiveTexture(Texture) -> cast(5373, <<Texture:?GLenum>>). @@ -9341,12 +3645,7 @@ clientActiveTexture(Texture) -> %% t r 1), %% and ``gl:multiTexCoord4'' defines all four components explicitly as (s t r q). %% -%% The current texture coordinates are part of the data that is associated with each vertex -%% and with the current raster position. Initially, the values for (s t r q) are (0 0 0 1). -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiTexCoord.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glMultiTexCoord.xml">external</a> documentation. -spec multiTexCoord1d(Target, S) -> 'ok' when Target :: enum(),S :: float(). multiTexCoord1d(Target,S) -> cast(5374, <<Target:?GLenum,0:32,S:?GLdouble>>). @@ -9511,19 +3810,7 @@ multiTexCoord4sv(Target,{S,T,R,Q}) -> multiTexCoord4s(Target,S,T,R,Q). %% specified by `M' . The current matrix is the projection matrix, modelview matrix, %% or texture matrix, depending on the current matrix mode (see {@link gl:matrixMode/1} ). %% -%% The current matrix, M, defines a transformation of coordinates. For instance, assume -%% M refers to the modelview matrix. If v=(v[0] v[1] v[2] v[3]) is the set of object coordinates of a vertex, -%% and `M' points to an array of 16 single- or double-precision floating-point values -%% m={m[0] m[1] ... m[15]}, then the modelview transformation M(v) does the following: -%% -%% M(v)=(m[0] m[1] m[2] m[3] m[4] m[5] m[6] m[7] m[8] m[9] m[10] m[11] m[12] m[13] m[14] m[15])×(v[0] v[1] v[2] v[3]) -%% -%% Projection and texture transformations are similarly defined. -%% -%% Calling ``gl:loadTransposeMatrix'' with matrix M is identical in operation to {@link gl:loadMatrixd/1} -%% with M T, where T represents the transpose. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadTransposeMatrix.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLoadTransposeMatrix.xml">external</a> documentation. -spec loadTransposeMatrixf(M) -> 'ok' when M :: matrix(). loadTransposeMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) -> cast(5390, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,M13:?GLfloat,M14:?GLfloat,M15:?GLfloat,M16:?GLfloat>>); @@ -9543,10 +3830,7 @@ loadTransposeMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) -> %% ``gl:multTransposeMatrix'' multiplies the current matrix with the one specified using `M' %% , and replaces the current matrix with the product. %% -%% The current matrix is determined by the current matrix mode (see {@link gl:matrixMode/1} ). -%% It is either the projection matrix, modelview matrix, or the texture matrix. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultTransposeMatrix.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glMultTransposeMatrix.xml">external</a> documentation. -spec multTransposeMatrixf(M) -> 'ok' when M :: matrix(). multTransposeMatrixf({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) -> cast(5392, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,M13:?GLfloat,M14:?GLfloat,M15:?GLfloat,M16:?GLfloat>>); @@ -9568,72 +3852,7 @@ multTransposeMatrixd({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) -> %% is initially disabled. Use {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_BLEND' %% to enable and disable blending. %% -%% ``gl:blendFuncSeparate'' defines the operation of blending for all draw buffers when -%% it is enabled. ``gl:blendFuncSeparatei'' defines the operation of blending for a single -%% draw buffer specified by `Buf' when enabled for that draw buffer. `SrcRGB' specifies -%% which method is used to scale the source RGB-color components. `DstRGB' specifies -%% which method is used to scale the destination RGB-color components. Likewise, `SrcAlpha' -%% specifies which method is used to scale the source alpha color component, and `DstAlpha' -%% specifies which method is used to scale the destination alpha component. The possible -%% methods are described in the following table. Each method defines four scale factors, -%% one each for red, green, blue, and alpha. -%% -%% In the table and in subsequent equations, first source, second source and destination -%% color components are referred to as (R s0 G s0 B s0 A s0), (R s1 G s1 B s1 A s1), and (R d G d B d A d), respectively. The color specified by {@link gl:blendColor/4} -%% is referred to as (R c G c B c A c). They are understood to have integer values between 0 and (k R k G k B -%% k A), where -%% -%% k c=2(m c)-1 -%% -%% and (m R m G m B m A) is the number of red, green, blue, and alpha bitplanes. -%% -%% Source and destination scale factors are referred to as (s R s G s B s A) and (d R d G d B d A). All scale factors have -%% range [0 1]. -%% -%% <table><tbody><tr><td>` Parameter '</td><td>` RGB Factor '</td><td>` Alpha Factor ' -%% </td></tr></tbody><tbody><tr><td>`?GL_ZERO'</td><td>(0 0 0)</td><td> 0</td></tr><tr><td>`?GL_ONE' -%% </td><td>(1 1 1)</td><td> 1</td></tr><tr><td>`?GL_SRC_COLOR'</td><td>(R s0 k/R G s0 k/G B s0 -%% k/B)</td><td> A s0 k/A</td> -%% </tr><tr><td>`?GL_ONE_MINUS_SRC_COLOR'</td><td>(1 1 1 1)-(R s0 k/R G s0 k/G B s0 k/B)</td><td> 1-A s0 k/A</td></tr><tr><td> -%% `?GL_DST_COLOR'</td><td>(R d k/R G d k/G B d k/B)</td><td> A d k/A</td></tr><tr><td>`?GL_ONE_MINUS_DST_COLOR' -%% </td><td>(1 1 1)-(R d k/R G d k/G B d k/B)</td><td> 1-A d k/A</td></tr><tr><td>`?GL_SRC_ALPHA'</td><td>(A s0 k/A A s0 -%% k/A A s0 k/A)</td><td> A -%% s0 k/A</td></tr><tr><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td>(1 1 1)-(A s0 k/A A s0 k/A A s0 k/A -%% )</td><td> 1-A s0 k/A</td></tr> -%% <tr><td>`?GL_DST_ALPHA'</td><td>(A d k/A A d k/A A d k/A)</td><td> A d k/A</td></tr><tr><td>`?GL_ONE_MINUS_DST_ALPHA' -%% </td><td>(1 1 1)-(A d k/A A d k/A A d k/A)</td><td> 1-A d k/A</td></tr><tr><td>`?GL_CONSTANT_COLOR'</td><td>(R c G c -%% B c)</td><td> -%% A c</td></tr><tr><td>`?GL_ONE_MINUS_CONSTANT_COLOR'</td><td>(1 1 1)-(R c G c B c)</td><td> 1-A c</td></tr> -%% <tr><td>`?GL_CONSTANT_ALPHA'</td><td>(A c A c A c)</td><td> A c</td></tr><tr><td>`?GL_ONE_MINUS_CONSTANT_ALPHA' -%% </td><td>(1 1 1)-(A c A c A c)</td><td> 1-A c</td></tr><tr><td>`?GL_SRC_ALPHA_SATURATE'</td><td>(i i i)</td><td> -%% 1</td></tr><tr><td>`?GL_SRC1_COLOR'</td><td>(R s1 k/R G s1 k/G B s1 k/B)</td><td> A s1 k/A</td></tr><tr><td>`?GL_ONE_MINUS_SRC_COLOR' -%% </td><td>(1 1 1 1)-(R s1 k/R G s1 k/G B s1 k/B)</td><td> 1-A s1 k/A</td></tr><tr><td>`?GL_SRC1_ALPHA'</td><td>(A s1 k/A A -%% s1 k/A A s1 k/A)</td><td> A -%% s1 k/A</td></tr><tr><td>`?GL_ONE_MINUS_SRC_ALPHA'</td><td>(1 1 1)-(A s1 k/A A s1 k/A A s1 k/A -%% )</td><td> 1-A s1 k/A</td></tr> -%% </tbody></table> -%% -%% In the table, -%% -%% i=min(A s 1-(A d)) -%% -%% To determine the blended RGBA values of a pixel, the system uses the following equations: -%% -%% -%% R d=min(k R R s s R+R d d R) G d=min(k G G s s G+G d d G) B d=min(k B B s s B+B d d B) A d=min(k A A s s A+A d d A) -%% -%% Despite the apparent precision of the above equations, blending arithmetic is not exactly -%% specified, because blending operates with imprecise integer color values. However, a blend -%% factor that should be equal to 1 is guaranteed not to modify its multiplicand, and a blend -%% factor equal to 0 reduces its multiplicand to 0. For example, when `SrcRGB' is `?GL_SRC_ALPHA' -%% , `DstRGB' is `?GL_ONE_MINUS_SRC_ALPHA', and A s is equal to k A, the equations -%% reduce to simple replacement: -%% -%% R d=R s G d=G s B d=B s A d=A s -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendFuncSeparate.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendFuncSeparate.xhtml">external</a> documentation. -spec blendFuncSeparate(SfactorRGB, DfactorRGB, SfactorAlpha, DfactorAlpha) -> 'ok' when SfactorRGB :: enum(),DfactorRGB :: enum(),SfactorAlpha :: enum(),DfactorAlpha :: enum(). blendFuncSeparate(SfactorRGB,DfactorRGB,SfactorAlpha,DfactorAlpha) -> cast(5394, <<SfactorRGB:?GLenum,DfactorRGB:?GLenum,SfactorAlpha:?GLenum,DfactorAlpha:?GLenum>>). @@ -9646,19 +3865,7 @@ blendFuncSeparate(SfactorRGB,DfactorRGB,SfactorAlpha,DfactorAlpha) -> %% normals, and colors and use them to construct a sequence of primitives with a single call %% to ``gl:multiDrawArrays''. %% -%% ``gl:multiDrawArrays'' behaves identically to {@link gl:drawArrays/3} except that `Primcount' -%% separate ranges of elements are specified instead. -%% -%% When ``gl:multiDrawArrays'' is called, it uses `Count' sequential elements from -%% each enabled array to construct a sequence of geometric primitives, beginning with element -%% `First' . `Mode' specifies what kind of primitives are constructed, and how the -%% array elements construct those primitives. -%% -%% Vertex attributes that are modified by ``gl:multiDrawArrays'' have an unspecified value -%% after ``gl:multiDrawArrays'' returns. Attributes that aren't modified remain well defined. -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultiDrawArrays.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMultiDrawArrays.xhtml">external</a> documentation. -spec multiDrawArrays(Mode, First, Count) -> 'ok' when Mode :: enum(),First :: [integer()]|mem(),Count :: [integer()]|mem(). multiDrawArrays(Mode,First,Count) when is_list(First), is_list(Count) -> FirstLen = length(First), @@ -9677,15 +3884,7 @@ multiDrawArrays(Mode,First,Count) -> %% %% The following values are accepted for `Pname' : %% -%% `?GL_POINT_FADE_THRESHOLD_SIZE': `Params' is a single floating-point value that -%% specifies the threshold value to which point sizes are clamped if they exceed the specified -%% value. The default value is 1.0. -%% -%% `?GL_POINT_SPRITE_COORD_ORIGIN': `Params' is a single enum specifying the point -%% sprite texture coordinate origin, either `?GL_LOWER_LEFT' or `?GL_UPPER_LEFT'. -%% The default value is `?GL_UPPER_LEFT'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPointParameter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPointParameter.xhtml">external</a> documentation. -spec pointParameterf(Pname, Param) -> 'ok' when Pname :: enum(),Param :: float(). pointParameterf(Pname,Param) -> cast(5397, <<Pname:?GLenum,Param:?GLfloat>>). @@ -9716,7 +3915,7 @@ pointParameteriv(Pname,Params) -> %% the current raster position. The value specified is interpolated and used in computing %% the fog color (see {@link gl:fogf/2} ). %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFogCoord.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFogCoord.xml">external</a> documentation. -spec fogCoordf(Coord) -> 'ok' when Coord :: float(). fogCoordf(Coord) -> cast(5401, <<Coord:?GLfloat>>). @@ -9742,22 +3941,7 @@ fogCoorddv({Coord}) -> fogCoordd(Coord). %% specifies the byte stride from one fog coordinate to the next, allowing vertices and %% attributes to be packed into a single array or stored in separate arrays. %% -%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2} -%% ) while a fog coordinate array is specified, `Pointer' is treated as a byte offset -%% into the buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING' -%% ) is saved as fog coordinate vertex array client-side state (`?GL_FOG_COORD_ARRAY_BUFFER_BINDING' -%% ). -%% -%% When a fog coordinate array is specified, `Type' , `Stride' , and `Pointer' -%% are saved as client-side state, in addition to the current vertex array buffer object -%% binding. -%% -%% To enable and disable the fog coordinate array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1} -%% with the argument `?GL_FOG_COORD_ARRAY'. If enabled, the fog coordinate array is -%% used when {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} , see `glMultiDrawElements' -%% , {@link gl:drawRangeElements/6} , or {@link gl:arrayElement/1} is called. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFogCoordPointer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glFogCoordPointer.xml">external</a> documentation. -spec fogCoordPointer(Type, Stride, Pointer) -> 'ok' when Type :: enum(),Stride :: integer(),Pointer :: offset()|mem(). fogCoordPointer(Type,Stride,Pointer) when is_integer(Pointer) -> cast(5403, <<Type:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>); @@ -9770,31 +3954,7 @@ fogCoordPointer(Type,Stride,Pointer) -> %% The GL stores both a primary four-valued RGBA color and a secondary four-valued RGBA %% color (where alpha is always set to 0.0) that is associated with every vertex. %% -%% The secondary color is interpolated and applied to each fragment during rasterization -%% when `?GL_COLOR_SUM' is enabled. When lighting is enabled, and `?GL_SEPARATE_SPECULAR_COLOR' -%% is specified, the value of the secondary color is assigned the value computed from the -%% specular term of the lighting computation. Both the primary and secondary current colors -%% are applied to each fragment, regardless of the state of `?GL_COLOR_SUM', under such -%% conditions. When `?GL_SEPARATE_SPECULAR_COLOR' is specified, the value returned from -%% querying the current secondary color is undefined. -%% -%% ``gl:secondaryColor3b'', ``gl:secondaryColor3s'', and ``gl:secondaryColor3i'' take -%% three signed byte, short, or long integers as arguments. When `v' is appended to -%% the name, the color commands can take a pointer to an array of such values. -%% -%% Color values are stored in floating-point format, with unspecified mantissa and exponent -%% sizes. Unsigned integer color components, when specified, are linearly mapped to floating-point -%% values such that the largest representable value maps to 1.0 (full intensity), and 0 maps -%% to 0.0 (zero intensity). Signed integer color components, when specified, are linearly -%% mapped to floating-point values such that the most positive representable value maps to -%% 1.0, and the most negative representable value maps to -1.0. (Note that this mapping -%% does not convert 0 precisely to 0.0). Floating-point values are mapped directly. -%% -%% Neither floating-point nor signed integer values are clamped to the range [0 1] before the -%% current color is updated. However, color components are clamped to this range before they -%% are interpolated or written into a color buffer. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColor.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glSecondaryColor.xml">external</a> documentation. -spec secondaryColor3b(Red, Green, Blue) -> 'ok' when Red :: integer(),Green :: integer(),Blue :: integer(). secondaryColor3b(Red,Green,Blue) -> cast(5405, <<Red:?GLbyte,Green:?GLbyte,Blue:?GLbyte>>). @@ -9881,23 +4041,7 @@ secondaryColor3usv({Red,Green,Blue}) -> secondaryColor3us(Red,Green,Blue). %% specifies the byte stride from one color to the next, allowing vertices and attributes %% to be packed into a single array or stored in separate arrays. %% -%% If a non-zero named buffer object is bound to the `?GL_ARRAY_BUFFER' target (see {@link gl:bindBuffer/2} -%% ) while a secondary color array is specified, `Pointer' is treated as a byte offset -%% into the buffer object's data store. Also, the buffer object binding (`?GL_ARRAY_BUFFER_BINDING' -%% ) is saved as secondary color vertex array client-side state (`?GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING' -%% ). -%% -%% When a secondary color array is specified, `Size' , `Type' , `Stride' , and `Pointer' -%% are saved as client-side state, in addition to the current vertex array buffer object -%% binding. -%% -%% To enable and disable the secondary color array, call {@link gl:enableClientState/1} and {@link gl:enableClientState/1} -%% with the argument `?GL_SECONDARY_COLOR_ARRAY'. If enabled, the secondary color array -%% is used when {@link gl:arrayElement/1} , {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} , -%% {@link gl:drawElements/4} , see `glMultiDrawElements', or {@link gl:drawRangeElements/6} -%% is called. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSecondaryColorPointer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glSecondaryColorPointer.xml">external</a> documentation. -spec secondaryColorPointer(Size, Type, Stride, Pointer) -> 'ok' when Size :: integer(),Type :: enum(),Stride :: integer(),Pointer :: offset()|mem(). secondaryColorPointer(Size,Type,Stride,Pointer) when is_integer(Pointer) -> cast(5413, <<Size:?GLint,Type:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>); @@ -9912,38 +4056,7 @@ secondaryColorPointer(Size,Type,Stride,Pointer) -> %% subpixel accuracy. See {@link gl:bitmap/7} , {@link gl:drawPixels/5} , and {@link gl:copyPixels/5} %% . %% -%% ``gl:windowPos2'' specifies the x and y coordinates, while z is implicitly set -%% to 0. ``gl:windowPos3'' specifies all three coordinates. The w coordinate of the current -%% raster position is always set to 1.0. -%% -%% ``gl:windowPos'' directly updates the x and y coordinates of the current raster -%% position with the values specified. That is, the values are neither transformed by the -%% current modelview and projection matrices, nor by the viewport-to-window transform. The -%% z coordinate of the current raster position is updated in the following manner: -%% -%% z={n f(n+z×(f-n)) if z<= 0 if z>= 1(otherwise)) -%% -%% where n is `?GL_DEPTH_RANGE''s near value, and f is `?GL_DEPTH_RANGE''s -%% far value. See {@link gl:depthRange/2} . -%% -%% The specified coordinates are not clip-tested, causing the raster position to always -%% be valid. -%% -%% The current raster position also includes some associated color data and texture coordinates. -%% If lighting is enabled, then `?GL_CURRENT_RASTER_COLOR' (in RGBA mode) or `?GL_CURRENT_RASTER_INDEX' -%% (in color index mode) is set to the color produced by the lighting calculation (see {@link gl:lightf/3} -%% , {@link gl:lightModelf/2} , and {@link gl:shadeModel/1} ). If lighting is disabled, current -%% color (in RGBA mode, state variable `?GL_CURRENT_COLOR') or color index (in color -%% index mode, state variable `?GL_CURRENT_INDEX') is used to update the current raster -%% color. `?GL_CURRENT_RASTER_SECONDARY_COLOR' (in RGBA mode) is likewise updated. -%% -%% Likewise, `?GL_CURRENT_RASTER_TEXTURE_COORDS' is updated as a function of `?GL_CURRENT_TEXTURE_COORDS' -%% , based on the texture matrix and the texture generation functions (see {@link gl:texGend/3} ). -%% The `?GL_CURRENT_RASTER_DISTANCE' is set to the `?GL_CURRENT_FOG_COORD'. -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glWindowPos.xml">external</a> documentation. -spec windowPos2d(X, Y) -> 'ok' when X :: float(),Y :: float(). windowPos2d(X,Y) -> cast(5415, <<X:?GLdouble,Y:?GLdouble>>). @@ -10028,13 +4141,7 @@ windowPos3sv({X,Y,Z}) -> windowPos3s(X,Y,Z). %% that the names form a contiguous set of integers; however, it is guaranteed that none %% of the returned names was in use immediately before the call to ``gl:genQueries''. %% -%% Query object names returned by a call to ``gl:genQueries'' are not returned by subsequent -%% calls, unless they are first deleted with {@link gl:deleteQueries/1} . -%% -%% No query objects are associated with the returned query object names until they are first -%% used by calling {@link gl:beginQuery/2} . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenQueries.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenQueries.xhtml">external</a> documentation. -spec genQueries(N) -> [integer()] when N :: integer(). genQueries(N) -> call(5423, <<N:?GLsizei>>). @@ -10045,10 +4152,7 @@ genQueries(N) -> %% . After a query object is deleted, it has no contents, and its name is free for reuse %% (for example by {@link gl:genQueries/1} ). %% -%% ``gl:deleteQueries'' silently ignores 0's and names that do not correspond to existing -%% query objects. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteQueries.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteQueries.xhtml">external</a> documentation. -spec deleteQueries(Ids) -> 'ok' when Ids :: [integer()]. deleteQueries(Ids) -> IdsLen = length(Ids), @@ -10061,10 +4165,7 @@ deleteQueries(Ids) -> %% object. If `Id' is zero, or is a non-zero value that is not currently the name of %% a query object, or if an error occurs, ``gl:isQuery'' returns `?GL_FALSE'. %% -%% A name returned by {@link gl:genQueries/1} , but not yet associated with a query object -%% by calling {@link gl:beginQuery/2} , is not the name of a query object. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsQuery.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsQuery.xhtml">external</a> documentation. -spec isQuery(Id) -> 0|1 when Id :: integer(). isQuery(Id) -> call(5425, <<Id:?GLuint>>). @@ -10078,60 +4179,7 @@ isQuery(Id) -> %% , `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN', or `?GL_TIME_ELAPSED'. The behavior %% of the query object depends on its type and is as follows. %% -%% If `Target' is `?GL_SAMPLES_PASSED', `Id' must be an unused name, or the -%% name of an existing occlusion query object. When ``gl:beginQuery'' is executed, the -%% query object's samples-passed counter is reset to 0. Subsequent rendering will increment -%% the counter for every sample that passes the depth test. If the value of `?GL_SAMPLE_BUFFERS' -%% is 0, then the samples-passed count is incremented by 1 for each fragment. If the value -%% of `?GL_SAMPLE_BUFFERS' is 1, then the samples-passed count is incremented by the -%% number of samples whose coverage bit is set. However, implementations, at their discression -%% may instead increase the samples-passed count by the value of `?GL_SAMPLES' if any -%% sample in the fragment is covered. When ``gl:endQuery'' is executed, the samples-passed -%% counter is assigned to the query object's result value. This value can be queried by calling -%% {@link gl:getQueryObjectiv/2} with `Pname' `?GL_QUERY_RESULT'. -%% -%% If `Target' is `?GL_ANY_SAMPLES_PASSED', `Id' must be an unused name, -%% or the name of an existing boolean occlusion query object. When ``gl:beginQuery'' is -%% executed, the query object's samples-passed flag is reset to `?GL_FALSE'. Subsequent -%% rendering causes the flag to be set to `?GL_TRUE' if any sample passes the depth -%% test. When ``gl:endQuery'' is executed, the samples-passed flag is assigned to the query -%% object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2} -%% with `Pname' `?GL_QUERY_RESULT'. -%% -%% If `Target' is `?GL_PRIMITIVES_GENERATED', `Id' must be an unused name, -%% or the name of an existing primitive query object previously bound to the `?GL_PRIMITIVES_GENERATED' -%% query binding. When ``gl:beginQuery'' is executed, the query object's primitives-generated -%% counter is reset to 0. Subsequent rendering will increment the counter once for every -%% vertex that is emitted from the geometry shader, or from the vertex shader if no geometry -%% shader is present. When ``gl:endQuery'' is executed, the primitives-generated counter -%% is assigned to the query object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2} -%% with `Pname' `?GL_QUERY_RESULT'. -%% -%% If `Target' is `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN', `Id' must -%% be an unused name, or the name of an existing primitive query object previously bound -%% to the `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN' query binding. When ``gl:beginQuery'' -%% is executed, the query object's primitives-written counter is reset to 0. Subsequent -%% rendering will increment the counter once for every vertex that is written into the bound -%% transform feedback buffer(s). If transform feedback mode is not activated between the -%% call to ``gl:beginQuery'' and ``gl:endQuery'', the counter will not be incremented. -%% When ``gl:endQuery'' is executed, the primitives-written counter is assigned to the -%% query object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2} -%% with `Pname' `?GL_QUERY_RESULT'. -%% -%% If `Target' is `?GL_TIME_ELAPSED', `Id' must be an unused name, or the -%% name of an existing timer query object previously bound to the `?GL_TIME_ELAPSED' -%% query binding. When ``gl:beginQuery'' is executed, the query object's time counter is -%% reset to 0. When ``gl:endQuery'' is executed, the elapsed server time that has passed -%% since the call to ``gl:beginQuery'' is written into the query object's time counter. -%% This value can be queried by calling {@link gl:getQueryObjectiv/2} with `Pname' `?GL_QUERY_RESULT' -%% . -%% -%% Querying the `?GL_QUERY_RESULT' implicitly flushes the GL pipeline until the rendering -%% delimited by the query object has completed and the result is available. `?GL_QUERY_RESULT_AVAILABLE' -%% can be queried to determine if the result is immediately available or if the rendering -%% is not yet complete. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginQuery.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBeginQuery.xhtml">external</a> documentation. -spec beginQuery(Target, Id) -> 'ok' when Target :: enum(),Id :: integer(). beginQuery(Target,Id) -> cast(5426, <<Target:?GLenum,Id:?GLuint>>). @@ -10144,7 +4192,7 @@ endQuery(Target) -> %% @doc glGetQuery %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQuery.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getQueryiv(Target, Pname) -> integer() when Target :: enum(),Pname :: enum(). getQueryiv(Target,Pname) -> call(5428, <<Target:?GLenum,Pname:?GLenum>>). @@ -10154,17 +4202,7 @@ getQueryiv(Target,Pname) -> %% ``gl:getQueryObject'' returns in `Params' a selected parameter of the query object %% specified by `Id' . %% -%% `Pname' names a specific query object parameter. `Pname' can be as follows: -%% -%% `?GL_QUERY_RESULT': `Params' returns the value of the query object's passed -%% samples counter. The initial value is 0. -%% -%% `?GL_QUERY_RESULT_AVAILABLE': `Params' returns whether the passed samples counter -%% is immediately available. If a delay would occur waiting for the query result, `?GL_FALSE' -%% is returned. Otherwise, `?GL_TRUE' is returned, which also indicates that the results -%% of all previous queries are available as well. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryObject.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetQueryObject.xhtml">external</a> documentation. -spec getQueryObjectiv(Id, Pname) -> integer() when Id :: integer(),Pname :: enum(). getQueryObjectiv(Id,Pname) -> call(5429, <<Id:?GLuint,Pname:?GLenum>>). @@ -10183,77 +4221,7 @@ getQueryObjectuiv(Id,Pname) -> %% object with name `Buffer' exists, one is created with that name. When a buffer object %% is bound to a target, the previous binding for that target is automatically broken. %% -%% Buffer object names are unsigned integers. The value zero is reserved, but there is no -%% default buffer object for each buffer object target. Instead, `Buffer' set to zero -%% effectively unbinds any buffer object previously bound, and restores client memory usage -%% for that buffer object target (if supported for that target). Buffer object names and -%% the corresponding buffer object contents are local to the shared object space of the current -%% GL rendering context; two rendering contexts share buffer object names only if they explicitly -%% enable sharing between contexts through the appropriate GL windows interfaces functions. -%% -%% {@link gl:genBuffers/1} must be used to generate a set of unused buffer object names. -%% -%% The state of a buffer object immediately after it is first bound is an unmapped zero-sized -%% memory buffer with `?GL_READ_WRITE' access and `?GL_STATIC_DRAW' usage. -%% -%% While a non-zero buffer object name is bound, GL operations on the target to which it -%% is bound affect the bound buffer object, and queries of the target to which it is bound -%% return state from the bound buffer object. While buffer object name zero is bound, as -%% in the initial state, attempts to modify or query state on the target to which it is bound -%% generates an `?GL_INVALID_OPERATION' error. -%% -%% When a non-zero buffer object is bound to the `?GL_ARRAY_BUFFER' target, the vertex -%% array pointer parameter is interpreted as an offset within the buffer object measured -%% in basic machine units. -%% -%% When a non-zero buffer object is bound to the `?GL_DRAW_INDIRECT_BUFFER' target, -%% parameters for draws issued through {@link gl:drawArraysIndirect/2} and {@link gl:drawElementsIndirect/3} -%% are sourced from that buffer object. -%% -%% While a non-zero buffer object is bound to the `?GL_ELEMENT_ARRAY_BUFFER' target, -%% the indices parameter of {@link gl:drawElements/4} , {@link gl:drawElementsInstanced/5} , {@link gl:drawElementsBaseVertex/5} -%% , {@link gl:drawRangeElements/6} , {@link gl:drawRangeElementsBaseVertex/7} , see `glMultiDrawElements' -%% , or see `glMultiDrawElementsBaseVertex' is interpreted as an offset within the -%% buffer object measured in basic machine units. -%% -%% While a non-zero buffer object is bound to the `?GL_PIXEL_PACK_BUFFER' target, -%% the following commands are affected: {@link gl:getCompressedTexImage/3} , {@link gl:getTexImage/5} -%% , and {@link gl:readPixels/7} . The pointer parameter is interpreted as an offset within -%% the buffer object measured in basic machine units. -%% -%% While a non-zero buffer object is bound to the `?GL_PIXEL_UNPACK_BUFFER' target, -%% the following commands are affected: {@link gl:compressedTexImage1D/7} , {@link gl:compressedTexImage2D/8} -%% , {@link gl:compressedTexImage3D/9} , {@link gl:compressedTexSubImage1D/7} , {@link gl:compressedTexSubImage2D/9} -%% , {@link gl:compressedTexSubImage3D/11} , {@link gl:texImage1D/8} , {@link gl:texImage2D/9} , {@link gl:texImage3D/10} -%% , {@link gl:texSubImage1D/7} , {@link gl:texSubImage1D/7} , and {@link gl:texSubImage1D/7} . -%% The pointer parameter is interpreted as an offset within the buffer object measured in -%% basic machine units. -%% -%% The buffer targets `?GL_COPY_READ_BUFFER' and `?GL_COPY_WRITE_BUFFER' are provided -%% to allow {@link gl:copyBufferSubData/5} to be used without disturbing the state of other -%% bindings. However, {@link gl:copyBufferSubData/5} may be used with any pair of buffer binding -%% points. -%% -%% The `?GL_TRANSFORM_FEEDBACK_BUFFER' buffer binding point may be passed to ``gl:bindBuffer'' -%% , but will not directly affect transform feedback state. Instead, the indexed `?GL_TRANSFORM_FEEDBACK_BUFFER' -%% bindings must be used through a call to {@link gl:bindBufferBase/3} or {@link gl:bindBufferRange/5} -%% . This will affect the generic `?GL_TRANSFORM_FEEDABCK_BUFFER' binding. -%% -%% Likewise, the `?GL_UNIFORM_BUFFER' and `?GL_ATOMIC_COUNTER_BUFFER' buffer binding -%% points may be used, but do not directly affect uniform buffer or atomic counter buffer -%% state, respectively. {@link gl:bindBufferBase/3} or {@link gl:bindBufferRange/5} must be -%% used to bind a buffer to an indexed uniform buffer or atomic counter buffer binding point. -%% -%% -%% A buffer object binding created with ``gl:bindBuffer'' remains active until a different -%% buffer object name is bound to the same target, or until the bound buffer object is deleted -%% with {@link gl:deleteBuffers/1} . -%% -%% Once created, a named buffer object may be re-bound to any target as often as needed. -%% However, the GL implementation may make choices about how to optimize the storage of a -%% buffer object based on its initial binding target. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindBuffer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindBuffer.xhtml">external</a> documentation. -spec bindBuffer(Target, Buffer) -> 'ok' when Target :: enum(),Buffer :: integer(). bindBuffer(Target,Buffer) -> cast(5431, <<Target:?GLenum,Buffer:?GLuint>>). @@ -10265,10 +4233,7 @@ bindBuffer(Target,Buffer) -> %% free for reuse (for example by {@link gl:genBuffers/1} ). If a buffer object that is currently %% bound is deleted, the binding reverts to 0 (the absence of any buffer object). %% -%% ``gl:deleteBuffers'' silently ignores 0's and names that do not correspond to existing -%% buffer objects. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteBuffers.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteBuffers.xhtml">external</a> documentation. -spec deleteBuffers(Buffers) -> 'ok' when Buffers :: [integer()]. deleteBuffers(Buffers) -> BuffersLen = length(Buffers), @@ -10282,13 +4247,7 @@ deleteBuffers(Buffers) -> %% that none of the returned names was in use immediately before the call to ``gl:genBuffers'' %% . %% -%% Buffer object names returned by a call to ``gl:genBuffers'' are not returned by subsequent -%% calls, unless they are first deleted with {@link gl:deleteBuffers/1} . -%% -%% No buffer objects are associated with the returned buffer object names until they are -%% first bound by calling {@link gl:bindBuffer/2} . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenBuffers.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenBuffers.xhtml">external</a> documentation. -spec genBuffers(N) -> [integer()] when N :: integer(). genBuffers(N) -> call(5433, <<N:?GLsizei>>). @@ -10300,10 +4259,7 @@ genBuffers(N) -> %% the name of a buffer object, or if an error occurs, ``gl:isBuffer'' returns `?GL_FALSE' %% . %% -%% A name returned by {@link gl:genBuffers/1} , but not yet associated with a buffer object -%% by calling {@link gl:bindBuffer/2} , is not the name of a buffer object. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsBuffer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsBuffer.xhtml">external</a> documentation. -spec isBuffer(Buffer) -> 0|1 when Buffer :: integer(). isBuffer(Buffer) -> call(5434, <<Buffer:?GLuint>>). @@ -10317,31 +4273,7 @@ isBuffer(Buffer) -> %% is not mapped, it has a `?NULL' mapped pointer, and its mapped access is `?GL_READ_WRITE' %% . %% -%% `Usage' is a hint to the GL implementation as to how a buffer object's data store -%% will be accessed. This enables the GL implementation to make more intelligent decisions -%% that may significantly impact buffer object performance. It does not, however, constrain -%% the actual usage of the data store. `Usage' can be broken down into two parts: first, -%% the frequency of access (modification and usage), and second, the nature of that access. -%% The frequency of access may be one of these: -%% -%% STREAM: The data store contents will be modified once and used at most a few times. -%% -%% STATIC: The data store contents will be modified once and used many times. -%% -%% DYNAMIC: The data store contents will be modified repeatedly and used many times. -%% -%% The nature of access may be one of these: -%% -%% DRAW: The data store contents are modified by the application, and used as the source -%% for GL drawing and image specification commands. -%% -%% READ: The data store contents are modified by reading data from the GL, and used to return -%% that data when queried by the application. -%% -%% COPY: The data store contents are modified by reading data from the GL, and used as the -%% source for GL drawing and image specification commands. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBufferData.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferData.xhtml">external</a> documentation. -spec bufferData(Target, Size, Data, Usage) -> 'ok' when Target :: enum(),Size :: integer(),Data :: offset()|mem(),Usage :: enum(). bufferData(Target,Size,Data,Usage) when is_integer(Data) -> cast(5435, <<Target:?GLenum,0:32,Size:?GLsizeiptr,Data:?GLuint,Usage:?GLenum>>); @@ -10357,7 +4289,7 @@ bufferData(Target,Size,Data,Usage) -> %% is thrown if `Offset' and `Size' together define a range beyond the bounds of %% the buffer object's data store. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBufferSubData.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBufferSubData.xhtml">external</a> documentation. -spec bufferSubData(Target, Offset, Size, Data) -> 'ok' when Target :: enum(),Offset :: integer(),Size :: integer(),Data :: offset()|mem(). bufferSubData(Target,Offset,Size,Data) when is_integer(Data) -> cast(5437, <<Target:?GLenum,0:32,Offset:?GLintptr,Size:?GLsizeiptr,Data:?GLuint>>); @@ -10373,7 +4305,7 @@ bufferSubData(Target,Offset,Size,Data) -> %% is thrown if the buffer object is currently mapped, or if `Offset' and `Size' %% together define a range beyond the bounds of the buffer object's data store. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferSubData.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetBufferSubData.xhtml">external</a> documentation. -spec getBufferSubData(Target, Offset, Size, Data) -> 'ok' when Target :: enum(),Offset :: integer(),Size :: integer(),Data :: mem(). getBufferSubData(Target,Offset,Size,Data) -> send_bin(Data), @@ -10384,21 +4316,7 @@ getBufferSubData(Target,Offset,Size,Data) -> %% ``gl:getBufferParameteriv'' returns in `Data' a selected parameter of the buffer %% object specified by `Target' . %% -%% `Value' names a specific buffer object parameter, as follows: -%% -%% `?GL_BUFFER_ACCESS': `Params' returns the access policy set while mapping the -%% buffer object. The initial value is `?GL_READ_WRITE'. -%% -%% `?GL_BUFFER_MAPPED': `Params' returns a flag indicating whether the buffer object -%% is currently mapped. The initial value is `?GL_FALSE'. -%% -%% `?GL_BUFFER_SIZE': `Params' returns the size of the buffer object, measured -%% in bytes. The initial value is 0. -%% -%% `?GL_BUFFER_USAGE': `Params' returns the buffer object's usage pattern. The -%% initial value is `?GL_STATIC_DRAW'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferParameteriv.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGetBufferParameteriv.xml">external</a> documentation. -spec getBufferParameteriv(Target, Pname) -> integer() when Target :: enum(),Pname :: enum(). getBufferParameteriv(Target,Pname) -> call(5440, <<Target:?GLenum,Pname:?GLenum>>). @@ -10412,35 +4330,7 @@ getBufferParameteriv(Target,Pname) -> %% draw buffer whereas ``gl:blendEquationSeparate'' sets the blend equations for all draw %% buffers. %% -%% The blend equations use the source and destination blend factors specified by either {@link gl:blendFunc/2} -%% or {@link gl:blendFuncSeparate/4} . See {@link gl:blendFunc/2} or {@link gl:blendFuncSeparate/4} -%% for a description of the various blend factors. -%% -%% In the equations that follow, source and destination color components are referred to -%% as (R s G s B s A s) and (R d G d B d A d), respectively. The result color is referred to as (R r G r B r A r). The source and destination -%% blend factors are denoted (s R s G s B s A) and (d R d G d B d A), respectively. For these equations all color components -%% are understood to have values in the range [0 1]. <table><tbody><tr><td>` Mode '</td><td> -%% ` RGB Components '</td><td>` Alpha Component '</td></tr></tbody><tbody><tr><td>`?GL_FUNC_ADD' -%% </td><td> Rr=R s s R+R d d R Gr=G s s G+G d d G Br=B s s B+B d d B</td><td> Ar=A s -%% s A+A d d A</td></tr><tr><td>`?GL_FUNC_SUBTRACT'</td><td> Rr=R s s R-R d d R Gr=G -%% s s G-G d d G Br=B s s B-B d d B</td><td> Ar=A s s A-A d d A</td></tr><tr><td>`?GL_FUNC_REVERSE_SUBTRACT' -%% </td><td> Rr=R d d R-R s s R Gr=G d d G-G s s G Br=B d d B-B s s B</td><td> Ar=A d -%% d A-A s s A</td></tr><tr><td>`?GL_MIN'</td><td> Rr=min(R s R d) Gr=min(G s G d) Br=min(B s B d)</td><td> Ar=min -%% (A s A d)</td></tr><tr><td>`?GL_MAX'</td><td> Rr=max(R s R d) Gr=max(G s G d) Br=max(B s B d)</td><td> Ar=max(A s A d)</td></tr></tbody> -%% </table> -%% -%% The results of these equations are clamped to the range [0 1]. -%% -%% The `?GL_MIN' and `?GL_MAX' equations are useful for applications that analyze -%% image data (image thresholding against a constant color, for example). The `?GL_FUNC_ADD' -%% equation is useful for antialiasing and transparency, among other things. -%% -%% Initially, both the RGB blend equation and the alpha blend equation are set to `?GL_FUNC_ADD' -%% . -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquationSeparate.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendEquationSeparate.xhtml">external</a> documentation. -spec blendEquationSeparate(ModeRGB, ModeAlpha) -> 'ok' when ModeRGB :: enum(),ModeAlpha :: enum(). blendEquationSeparate(ModeRGB,ModeAlpha) -> cast(5441, <<ModeRGB:?GLenum,ModeAlpha:?GLenum>>). @@ -10455,32 +4345,7 @@ blendEquationSeparate(ModeRGB,ModeAlpha) -> %% or equal to `N' is implicitly set to `?GL_NONE' and any data written to such %% an output is discarded. %% -%% The symbolic constants contained in `Bufs' may be any of the following: -%% -%% `?GL_NONE': The fragment shader output value is not written into any color buffer. -%% -%% `?GL_FRONT_LEFT': The fragment shader output value is written into the front left -%% color buffer. -%% -%% `?GL_FRONT_RIGHT': The fragment shader output value is written into the front right -%% color buffer. -%% -%% `?GL_BACK_LEFT': The fragment shader output value is written into the back left color -%% buffer. -%% -%% `?GL_BACK_RIGHT': The fragment shader output value is written into the back right -%% color buffer. -%% -%% `?GL_COLOR_ATTACHMENT'`n': The fragment shader output value is written into -%% the `n'th color attachment of the current framebuffer. `n' may range from 0 -%% to the value of `?GL_MAX_COLOR_ATTACHMENTS'. -%% -%% Except for `?GL_NONE', the preceding symbolic constants may not appear more than -%% once in `Bufs' . The maximum number of draw buffers supported is implementation dependent -%% and can be queried by calling {@link gl:getBooleanv/1} with the argument `?GL_MAX_DRAW_BUFFERS' -%% . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawBuffers.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawBuffers.xhtml">external</a> documentation. -spec drawBuffers(Bufs) -> 'ok' when Bufs :: [enum()]. drawBuffers(Bufs) -> BufsLen = length(Bufs), @@ -10495,55 +4360,7 @@ drawBuffers(Bufs) -> %% used in multipass rendering algorithms to achieve special effects, such as decals, outlining, %% and constructive solid geometry rendering. %% -%% The stencil test conditionally eliminates a pixel based on the outcome of a comparison -%% between the value in the stencil buffer and a reference value. To enable and disable the -%% test, call {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_STENCIL_TEST' -%% ; to control it, call {@link gl:stencilFunc/3} or {@link gl:stencilFuncSeparate/4} . -%% -%% There can be two separate sets of `Sfail' , `Dpfail' , and `Dppass' parameters; -%% one affects back-facing polygons, and the other affects front-facing polygons as well -%% as other non-polygon primitives. {@link gl:stencilOp/3} sets both front and back stencil -%% state to the same values, as if {@link gl:stencilOpSeparate/4} were called with `Face' -%% set to `?GL_FRONT_AND_BACK'. -%% -%% ``gl:stencilOpSeparate'' takes three arguments that indicate what happens to the stored -%% stencil value while stenciling is enabled. If the stencil test fails, no change is made -%% to the pixel's color or depth buffers, and `Sfail' specifies what happens to the -%% stencil buffer contents. The following eight actions are possible. -%% -%% `?GL_KEEP': Keeps the current value. -%% -%% `?GL_ZERO': Sets the stencil buffer value to 0. -%% -%% `?GL_REPLACE': Sets the stencil buffer value to `ref', as specified by {@link gl:stencilFunc/3} -%% . -%% -%% `?GL_INCR': Increments the current stencil buffer value. Clamps to the maximum representable -%% unsigned value. -%% -%% `?GL_INCR_WRAP': Increments the current stencil buffer value. Wraps stencil buffer -%% value to zero when incrementing the maximum representable unsigned value. -%% -%% `?GL_DECR': Decrements the current stencil buffer value. Clamps to 0. -%% -%% `?GL_DECR_WRAP': Decrements the current stencil buffer value. Wraps stencil buffer -%% value to the maximum representable unsigned value when decrementing a stencil buffer value -%% of zero. -%% -%% `?GL_INVERT': Bitwise inverts the current stencil buffer value. -%% -%% Stencil buffer values are treated as unsigned integers. When incremented and decremented, -%% values are clamped to 0 and 2 n-1, where n is the value returned by querying `?GL_STENCIL_BITS' -%% . -%% -%% The other two arguments to ``gl:stencilOpSeparate'' specify stencil buffer actions -%% that depend on whether subsequent depth buffer tests succeed ( `Dppass' ) or fail ( `Dpfail' -%% ) (see {@link gl:depthFunc/1} ). The actions are specified using the same eight symbolic -%% constants as `Sfail' . Note that `Dpfail' is ignored when there is no depth buffer, -%% or when the depth buffer is not enabled. In these cases, `Sfail' and `Dppass' -%% specify stencil action when the stencil test fails and passes, respectively. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilOpSeparate.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glStencilOpSeparate.xhtml">external</a> documentation. -spec stencilOpSeparate(Face, Sfail, Dpfail, Dppass) -> 'ok' when Face :: enum(),Sfail :: enum(),Dpfail :: enum(),Dppass :: enum(). stencilOpSeparate(Face,Sfail,Dpfail,Dppass) -> cast(5443, <<Face:?GLenum,Sfail:?GLenum,Dpfail:?GLenum,Dppass:?GLenum>>). @@ -10556,57 +4373,7 @@ stencilOpSeparate(Face,Sfail,Dpfail,Dppass) -> %% used in multipass rendering algorithms to achieve special effects, such as decals, outlining, %% and constructive solid geometry rendering. %% -%% The stencil test conditionally eliminates a pixel based on the outcome of a comparison -%% between the reference value and the value in the stencil buffer. To enable and disable -%% the test, call {@link gl:enable/1} and {@link gl:enable/1} with argument `?GL_STENCIL_TEST' -%% . To specify actions based on the outcome of the stencil test, call {@link gl:stencilOp/3} -%% or {@link gl:stencilOpSeparate/4} . -%% -%% There can be two separate sets of `Func' , `Ref' , and `Mask' parameters; -%% one affects back-facing polygons, and the other affects front-facing polygons as well -%% as other non-polygon primitives. {@link gl:stencilFunc/3} sets both front and back stencil -%% state to the same values, as if {@link gl:stencilFuncSeparate/4} were called with `Face' -%% set to `?GL_FRONT_AND_BACK'. -%% -%% `Func' is a symbolic constant that determines the stencil comparison function. It -%% accepts one of eight values, shown in the following list. `Ref' is an integer reference -%% value that is used in the stencil comparison. It is clamped to the range [0 2 n-1], where n -%% is the number of bitplanes in the stencil buffer. `Mask' is bitwise ANDed with both -%% the reference value and the stored stencil value, with the ANDed values participating -%% in the comparison. -%% -%% If `stencil' represents the value stored in the corresponding stencil buffer location, -%% the following list shows the effect of each comparison function that can be specified by `Func' -%% . Only if the comparison succeeds is the pixel passed through to the next stage in the -%% rasterization process (see {@link gl:stencilOp/3} ). All tests treat `stencil' values -%% as unsigned integers in the range [0 2 n-1], where n is the number of bitplanes in the stencil -%% buffer. -%% -%% The following values are accepted by `Func' : -%% -%% `?GL_NEVER': Always fails. -%% -%% `?GL_LESS': Passes if ( `Ref' & `Mask' ) < ( `stencil' & `Mask' -%% ). -%% -%% `?GL_LEQUAL': Passes if ( `Ref' & `Mask' ) <= ( `stencil' -%% & `Mask' ). -%% -%% `?GL_GREATER': Passes if ( `Ref' & `Mask' ) > ( `stencil' -%% & `Mask' ). -%% -%% `?GL_GEQUAL': Passes if ( `Ref' & `Mask' ) >= ( `stencil' -%% & `Mask' ). -%% -%% `?GL_EQUAL': Passes if ( `Ref' & `Mask' ) = ( `stencil' & `Mask' -%% ). -%% -%% `?GL_NOTEQUAL': Passes if ( `Ref' & `Mask' ) != ( `stencil' & -%% `Mask' ). -%% -%% `?GL_ALWAYS': Always passes. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilFuncSeparate.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glStencilFuncSeparate.xhtml">external</a> documentation. -spec stencilFuncSeparate(Face, Func, Ref, Mask) -> 'ok' when Face :: enum(),Func :: enum(),Ref :: integer(),Mask :: integer(). stencilFuncSeparate(Face,Func,Ref,Mask) -> cast(5444, <<Face:?GLenum,Func:?GLenum,Ref:?GLint,Mask:?GLuint>>). @@ -10619,12 +4386,7 @@ stencilFuncSeparate(Face,Func,Ref,Mask) -> %% to the corresponding bit in the stencil buffer. Where a 0 appears, the corresponding bit %% is write-protected. Initially, all bits are enabled for writing. %% -%% There can be two separate `Mask' writemasks; one affects back-facing polygons, and -%% the other affects front-facing polygons as well as other non-polygon primitives. {@link gl:stencilMask/1} -%% sets both front and back stencil writemasks to the same values, as if {@link gl:stencilMaskSeparate/2} -%% were called with `Face' set to `?GL_FRONT_AND_BACK'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilMaskSeparate.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glStencilMaskSeparate.xhtml">external</a> documentation. -spec stencilMaskSeparate(Face, Mask) -> 'ok' when Face :: enum(),Mask :: integer(). stencilMaskSeparate(Face,Mask) -> cast(5445, <<Face:?GLenum,Mask:?GLuint>>). @@ -10638,17 +4400,7 @@ stencilMaskSeparate(Face,Mask) -> %% the program object specified by `Program' . This indicates that `Shader' will %% be included in link operations that will be performed on `Program' . %% -%% All operations that can be performed on a shader object are valid whether or not the -%% shader object is attached to a program object. It is permissible to attach a shader object -%% to a program object before source code has been loaded into the shader object or before -%% the shader object has been compiled. It is permissible to attach multiple shader objects -%% of the same type because each may contain a portion of the complete shader. It is also -%% permissible to attach a shader object to more than one program object. If a shader object -%% is deleted while it is attached to a program object, it will be flagged for deletion, -%% and deletion will not occur until {@link gl:detachShader/2} is called to detach it from -%% all program objects to which it is attached. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAttachShader.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glAttachShader.xhtml">external</a> documentation. -spec attachShader(Program, Shader) -> 'ok' when Program :: integer(),Shader :: integer(). attachShader(Program,Shader) -> cast(5446, <<Program:?GLuint,Shader:?GLuint>>). @@ -10663,29 +4415,7 @@ attachShader(Program,Shader) -> %% attribute `Index' will modify the value of the user-defined attribute variable specified %% by `Name' . %% -%% If `Name' refers to a matrix attribute variable, `Index' refers to the first -%% column of the matrix. Other matrix columns are then automatically bound to locations `Index+1' -%% for a matrix of type `mat2'; `Index+1' and `Index+2' for a matrix of type -%% `mat3'; and `Index+1' , `Index+2' , and `Index+3' for a matrix of type `mat4' -%% . -%% -%% This command makes it possible for vertex shaders to use descriptive names for attribute -%% variables rather than generic variables that are numbered from 0 to `?GL_MAX_VERTEX_ATTRIBS' -%% -1. The values sent to each generic attribute index are part of current state. If a different -%% program object is made current by calling {@link gl:useProgram/1} , the generic vertex attributes -%% are tracked in such a way that the same values will be observed by attributes in the new -%% program object that are also bound to `Index' . -%% -%% Attribute variable name-to-generic attribute index bindings for a program object can be -%% explicitly assigned at any time by calling ``gl:bindAttribLocation''. Attribute bindings -%% do not go into effect until {@link gl:linkProgram/1} is called. After a program object -%% has been linked successfully, the index values for generic attributes remain fixed (and -%% their values can be queried) until the next link command occurs. -%% -%% Any attribute binding that occurs after the program object has been linked will not take -%% effect until the next time the program object is linked. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindAttribLocation.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindAttribLocation.xhtml">external</a> documentation. -spec bindAttribLocation(Program, Index, Name) -> 'ok' when Program :: integer(),Index :: integer(),Name :: string(). bindAttribLocation(Program,Index,Name) -> NameLen = length(Name), @@ -10696,17 +4426,7 @@ bindAttribLocation(Program,Index,Name) -> %% ``gl:compileShader'' compiles the source code strings that have been stored in the shader %% object specified by `Shader' . %% -%% The compilation status will be stored as part of the shader object's state. This value -%% will be set to `?GL_TRUE' if the shader was compiled without errors and is ready -%% for use, and `?GL_FALSE' otherwise. It can be queried by calling {@link gl:getShaderiv/2} -%% with arguments `Shader' and `?GL_COMPILE_STATUS'. -%% -%% Compilation of a shader can fail for a number of reasons as specified by the OpenGL Shading -%% Language Specification. Whether or not the compilation was successful, information about -%% the compilation can be obtained from the shader object's information log by calling {@link gl:getShaderInfoLog/2} -%% . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompileShader.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCompileShader.xhtml">external</a> documentation. -spec compileShader(Shader) -> 'ok' when Shader :: integer(). compileShader(Shader) -> cast(5448, <<Shader:?GLuint>>). @@ -10721,15 +4441,7 @@ compileShader(Shader) -> %% between a vertex shader and a fragment shader). When no longer needed as part of a program %% object, shader objects can be detached. %% -%% One or more executables are created in a program object by successfully attaching shader -%% objects to it with {@link gl:attachShader/2} , successfully compiling the shader objects -%% with {@link gl:compileShader/1} , and successfully linking the program object with {@link gl:linkProgram/1} -%% . These executables are made part of current state when {@link gl:useProgram/1} is called. -%% Program objects can be deleted by calling {@link gl:deleteProgram/1} . The memory associated -%% with the program object will be deleted when it is no longer part of current rendering -%% state for any context. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateProgram.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCreateProgram.xhtml">external</a> documentation. -spec createProgram() -> integer(). createProgram() -> call(5449, <<>>). @@ -10748,11 +4460,7 @@ createProgram() -> %% programmable geometry processor. A shader of type `?GL_FRAGMENT_SHADER' is a shader %% that is intended to run on the programmable fragment processor. %% -%% When created, a shader object's `?GL_SHADER_TYPE' parameter is set to either `?GL_VERTEX_SHADER' -%% , `?GL_TESS_CONTROL_SHADER', `?GL_TESS_EVALUATION_SHADER', `?GL_GEOMETRY_SHADER' -%% or `?GL_FRAGMENT_SHADER', depending on the value of `ShaderType' . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateShader.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCreateShader.xhtml">external</a> documentation. -spec createShader(Type) -> integer() when Type :: enum(). createShader(Type) -> call(5450, <<Type:?GLenum>>). @@ -10763,17 +4471,7 @@ createShader(Type) -> %% object specified by `Program.' This command effectively undoes the effects of a call %% to {@link gl:createProgram/0} . %% -%% If a program object is in use as part of current rendering state, it will be flagged for -%% deletion, but it will not be deleted until it is no longer part of current state for any -%% rendering context. If a program object to be deleted has shader objects attached to it, -%% those shader objects will be automatically detached but not deleted unless they have already -%% been flagged for deletion by a previous call to {@link gl:deleteShader/1} . A value of 0 -%% for `Program' will be silently ignored. -%% -%% To determine whether a program object has been flagged for deletion, call {@link gl:getProgramiv/2} -%% with arguments `Program' and `?GL_DELETE_STATUS'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteProgram.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteProgram.xhtml">external</a> documentation. -spec deleteProgram(Program) -> 'ok' when Program :: integer(). deleteProgram(Program) -> cast(5451, <<Program:?GLuint>>). @@ -10784,15 +4482,7 @@ deleteProgram(Program) -> %% object specified by `Shader' . This command effectively undoes the effects of a call %% to {@link gl:createShader/1} . %% -%% If a shader object to be deleted is attached to a program object, it will be flagged for -%% deletion, but it will not be deleted until it is no longer attached to any program object, -%% for any rendering context (i.e., it must be detached from wherever it was attached before -%% it will be deleted). A value of 0 for `Shader' will be silently ignored. -%% -%% To determine whether an object has been flagged for deletion, call {@link gl:getShaderiv/2} -%% with arguments `Shader' and `?GL_DELETE_STATUS'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteShader.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteShader.xhtml">external</a> documentation. -spec deleteShader(Shader) -> 'ok' when Shader :: integer(). deleteShader(Shader) -> cast(5452, <<Shader:?GLuint>>). @@ -10803,11 +4493,7 @@ deleteShader(Shader) -> %% object specified by `Program' . This command can be used to undo the effect of the %% command {@link gl:attachShader/2} . %% -%% If `Shader' has already been flagged for deletion by a call to {@link gl:deleteShader/1} -%% and it is not attached to any other program object, it will be deleted after it has been -%% detached. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDetachShader.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDetachShader.xhtml">external</a> documentation. -spec detachShader(Program, Shader) -> 'ok' when Program :: integer(),Shader :: integer(). detachShader(Program,Shader) -> cast(5453, <<Program:?GLuint,Shader:?GLuint>>). @@ -10822,7 +4508,7 @@ detachShader(Program,Shader) -> %% such as {@link gl:drawArrays/3} , {@link gl:drawElements/4} , {@link gl:drawRangeElements/6} , see `glMultiDrawElements' %% , or {@link gl:multiDrawArrays/3} . %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEnableVertexAttribArray.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glEnableVertexAttribArray.xhtml">external</a> documentation. -spec disableVertexAttribArray(Index) -> 'ok' when Index :: integer(). disableVertexAttribArray(Index) -> cast(5454, <<Index:?GLuint>>). @@ -10841,52 +4527,7 @@ enableVertexAttribArray(Index) -> %% of 0 for `Index' selects the first active attribute variable. Permissible values %% for `Index' range from 0 to the number of active attribute variables minus 1. %% -%% A vertex shader may use either built-in attribute variables, user-defined attribute variables, -%% or both. Built-in attribute variables have a prefix of "gl_" and reference conventional -%% OpenGL vertex attribtes (e.g., `Gl_Vertex' , `Gl_Normal' , etc., see the OpenGL -%% Shading Language specification for a complete list.) User-defined attribute variables -%% have arbitrary names and obtain their values through numbered generic vertex attributes. -%% An attribute variable (either built-in or user-defined) is considered active if it is -%% determined during the link operation that it may be accessed during program execution. -%% Therefore, `Program' should have previously been the target of a call to {@link gl:linkProgram/1} -%% , but it is not necessary for it to have been linked successfully. -%% -%% The size of the character buffer required to store the longest attribute variable name -%% in `Program' can be obtained by calling {@link gl:getProgramiv/2} with the value `?GL_ACTIVE_ATTRIBUTE_MAX_LENGTH' -%% . This value should be used to allocate a buffer of sufficient size to store the returned -%% attribute name. The size of this character buffer is passed in `BufSize' , and a pointer -%% to this character buffer is passed in `Name' . -%% -%% ``gl:getActiveAttrib'' returns the name of the attribute variable indicated by `Index' -%% , storing it in the character buffer specified by `Name' . The string returned will -%% be null terminated. The actual number of characters written into this buffer is returned -%% in `Length' , and this count does not include the null termination character. If the -%% length of the returned string is not required, a value of `?NULL' can be passed in -%% the `Length' argument. -%% -%% The `Type' argument specifies a pointer to a variable into which the attribute variable's -%% data type will be written. The symbolic constants `?GL_FLOAT', `?GL_FLOAT_VEC2', -%% `?GL_FLOAT_VEC3', `?GL_FLOAT_VEC4', `?GL_FLOAT_MAT2', `?GL_FLOAT_MAT3', -%% `?GL_FLOAT_MAT4', `?GL_FLOAT_MAT2x3', `?GL_FLOAT_MAT2x4', `?GL_FLOAT_MAT3x2' -%% , `?GL_FLOAT_MAT3x4', `?GL_FLOAT_MAT4x2', `?GL_FLOAT_MAT4x3', `?GL_INT' -%% , `?GL_INT_VEC2', `?GL_INT_VEC3', `?GL_INT_VEC4', `?GL_UNSIGNED_INT_VEC' -%% , `?GL_UNSIGNED_INT_VEC2', `?GL_UNSIGNED_INT_VEC3', `?GL_UNSIGNED_INT_VEC4', -%% `?DOUBLE', `?DOUBLE_VEC2', `?DOUBLE_VEC3', `?DOUBLE_VEC4', `?DOUBLE_MAT2' -%% , `?DOUBLE_MAT3', `?DOUBLE_MAT4', `?DOUBLE_MAT2x3', `?DOUBLE_MAT2x4', -%% `?DOUBLE_MAT3x2', `?DOUBLE_MAT3x4', `?DOUBLE_MAT4x2', or `?DOUBLE_MAT4x3' -%% may be returned. The `Size' argument will return the size of the attribute, in units -%% of the type returned in `Type' . -%% -%% The list of active attribute variables may include both built-in attribute variables (which -%% begin with the prefix "gl_") as well as user-defined attribute variable names. -%% -%% This function will return as much information as it can about the specified active attribute -%% variable. If no information is available, `Length' will be 0, and `Name' will -%% be an empty string. This situation could occur if this function is called after a link -%% operation that failed. If an error occurs, the return values `Length' , `Size' , `Type' -%% , and `Name' will be unmodified. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveAttrib.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveAttrib.xhtml">external</a> documentation. -spec getActiveAttrib(Program, Index, BufSize) -> {Size :: integer(),Type :: enum(),Name :: string()} when Program :: integer(),Index :: integer(),BufSize :: integer(). getActiveAttrib(Program,Index,BufSize) -> call(5456, <<Program:?GLuint,Index:?GLuint,BufSize:?GLsizei>>). @@ -10899,141 +4540,7 @@ getActiveAttrib(Program,Index,BufSize) -> %% A value of 0 for `Index' selects the first active uniform variable. Permissible values %% for `Index' range from 0 to the number of active uniform variables minus 1. %% -%% Shaders may use either built-in uniform variables, user-defined uniform variables, or -%% both. Built-in uniform variables have a prefix of "gl_" and reference existing OpenGL -%% state or values derived from such state (e.g., `Gl_DepthRangeParameters' , see the -%% OpenGL Shading Language specification for a complete list.) User-defined uniform variables -%% have arbitrary names and obtain their values from the application through calls to {@link gl:uniform1f/2} -%% . A uniform variable (either built-in or user-defined) is considered active if it is determined -%% during the link operation that it may be accessed during program execution. Therefore, `Program' -%% should have previously been the target of a call to {@link gl:linkProgram/1} , but it is -%% not necessary for it to have been linked successfully. -%% -%% The size of the character buffer required to store the longest uniform variable name in `Program' -%% can be obtained by calling {@link gl:getProgramiv/2} with the value `?GL_ACTIVE_UNIFORM_MAX_LENGTH' -%% . This value should be used to allocate a buffer of sufficient size to store the returned -%% uniform variable name. The size of this character buffer is passed in `BufSize' , -%% and a pointer to this character buffer is passed in `Name.' -%% -%% ``gl:getActiveUniform'' returns the name of the uniform variable indicated by `Index' -%% , storing it in the character buffer specified by `Name' . The string returned will -%% be null terminated. The actual number of characters written into this buffer is returned -%% in `Length' , and this count does not include the null termination character. If the -%% length of the returned string is not required, a value of `?NULL' can be passed in -%% the `Length' argument. -%% -%% The `Type' argument will return a pointer to the uniform variable's data type. The -%% symbolic constants returned for uniform types are shown in the table below. <table><tbody> -%% <tr><td>` Returned Symbolic Contant '</td><td>` Shader Uniform Type '</td></tr></tbody> -%% <tbody><tr><td>`?GL_FLOAT'</td><td>`?float'</td></tr><tr><td>`?GL_FLOAT_VEC2' -%% </td><td>`?vec2'</td></tr><tr><td>`?GL_FLOAT_VEC3'</td><td>`?vec3'</td></tr> -%% <tr><td>`?GL_FLOAT_VEC4'</td><td>`?vec4'</td></tr><tr><td>`?GL_DOUBLE'</td> -%% <td>`?double'</td></tr><tr><td>`?GL_DOUBLE_VEC2'</td><td>`?dvec2'</td></tr> -%% <tr><td>`?GL_DOUBLE_VEC3'</td><td>`?dvec3'</td></tr><tr><td>`?GL_DOUBLE_VEC4' -%% </td><td>`?dvec4'</td></tr><tr><td>`?GL_INT'</td><td>`?int'</td></tr><tr><td> -%% `?GL_INT_VEC2'</td><td>`?ivec2'</td></tr><tr><td>`?GL_INT_VEC3'</td><td>`?ivec3' -%% </td></tr><tr><td>`?GL_INT_VEC4'</td><td>`?ivec4'</td></tr><tr><td>`?GL_UNSIGNED_INT' -%% </td><td>`?unsigned int'</td></tr><tr><td>`?GL_UNSIGNED_INT_VEC2'</td><td>`?uvec2' -%% </td></tr><tr><td>`?GL_UNSIGNED_INT_VEC3'</td><td>`?uvec3'</td></tr><tr><td>`?GL_UNSIGNED_INT_VEC4' -%% </td><td>`?uvec4'</td></tr><tr><td>`?GL_BOOL'</td><td>`?bool'</td></tr><tr> -%% <td>`?GL_BOOL_VEC2'</td><td>`?bvec2'</td></tr><tr><td>`?GL_BOOL_VEC3'</td><td> -%% `?bvec3'</td></tr><tr><td>`?GL_BOOL_VEC4'</td><td>`?bvec4'</td></tr><tr><td> -%% `?GL_FLOAT_MAT2'</td><td>`?mat2'</td></tr><tr><td>`?GL_FLOAT_MAT3'</td><td> -%% `?mat3'</td></tr><tr><td>`?GL_FLOAT_MAT4'</td><td>`?mat4'</td></tr><tr><td> -%% `?GL_FLOAT_MAT2x3'</td><td>`?mat2x3'</td></tr><tr><td>`?GL_FLOAT_MAT2x4'</td> -%% <td>`?mat2x4'</td></tr><tr><td>`?GL_FLOAT_MAT3x2'</td><td>`?mat3x2'</td></tr> -%% <tr><td>`?GL_FLOAT_MAT3x4'</td><td>`?mat3x4'</td></tr><tr><td>`?GL_FLOAT_MAT4x2' -%% </td><td>`?mat4x2'</td></tr><tr><td>`?GL_FLOAT_MAT4x3'</td><td>`?mat4x3'</td> -%% </tr><tr><td>`?GL_DOUBLE_MAT2'</td><td>`?dmat2'</td></tr><tr><td>`?GL_DOUBLE_MAT3' -%% </td><td>`?dmat3'</td></tr><tr><td>`?GL_DOUBLE_MAT4'</td><td>`?dmat4'</td></tr> -%% <tr><td>`?GL_DOUBLE_MAT2x3'</td><td>`?dmat2x3'</td></tr><tr><td>`?GL_DOUBLE_MAT2x4' -%% </td><td>`?dmat2x4'</td></tr><tr><td>`?GL_DOUBLE_MAT3x2'</td><td>`?dmat3x2'</td> -%% </tr><tr><td>`?GL_DOUBLE_MAT3x4'</td><td>`?dmat3x4'</td></tr><tr><td>`?GL_DOUBLE_MAT4x2' -%% </td><td>`?dmat4x2'</td></tr><tr><td>`?GL_DOUBLE_MAT4x3'</td><td>`?dmat4x3'</td> -%% </tr><tr><td>`?GL_SAMPLER_1D'</td><td>`?sampler1D'</td></tr><tr><td>`?GL_SAMPLER_2D' -%% </td><td>`?sampler2D'</td></tr><tr><td>`?GL_SAMPLER_3D'</td><td>`?sampler3D' -%% </td></tr><tr><td>`?GL_SAMPLER_CUBE'</td><td>`?samplerCube'</td></tr><tr><td>`?GL_SAMPLER_1D_SHADOW' -%% </td><td>`?sampler1DShadow'</td></tr><tr><td>`?GL_SAMPLER_2D_SHADOW'</td><td>`?sampler2DShadow' -%% </td></tr><tr><td>`?GL_SAMPLER_1D_ARRAY'</td><td>`?sampler1DArray'</td></tr><tr> -%% <td>`?GL_SAMPLER_2D_ARRAY'</td><td>`?sampler2DArray'</td></tr><tr><td>`?GL_SAMPLER_1D_ARRAY_SHADOW' -%% </td><td>`?sampler1DArrayShadow'</td></tr><tr><td>`?GL_SAMPLER_2D_ARRAY_SHADOW'</td> -%% <td>`?sampler2DArrayShadow'</td></tr><tr><td>`?GL_SAMPLER_2D_MULTISAMPLE'</td><td> -%% `?sampler2DMS'</td></tr><tr><td>`?GL_SAMPLER_2D_MULTISAMPLE_ARRAY'</td><td>`?sampler2DMSArray' -%% </td></tr><tr><td>`?GL_SAMPLER_CUBE_SHADOW'</td><td>`?samplerCubeShadow'</td></tr> -%% <tr><td>`?GL_SAMPLER_BUFFER'</td><td>`?samplerBuffer'</td></tr><tr><td>`?GL_SAMPLER_2D_RECT' -%% </td><td>`?sampler2DRect'</td></tr><tr><td>`?GL_SAMPLER_2D_RECT_SHADOW'</td><td> -%% `?sampler2DRectShadow'</td></tr><tr><td>`?GL_INT_SAMPLER_1D'</td><td>`?isampler1D' -%% </td></tr><tr><td>`?GL_INT_SAMPLER_2D'</td><td>`?isampler2D'</td></tr><tr><td>`?GL_INT_SAMPLER_3D' -%% </td><td>`?isampler3D'</td></tr><tr><td>`?GL_INT_SAMPLER_CUBE'</td><td>`?isamplerCube' -%% </td></tr><tr><td>`?GL_INT_SAMPLER_1D_ARRAY'</td><td>`?isampler1DArray'</td></tr> -%% <tr><td>`?GL_INT_SAMPLER_2D_ARRAY'</td><td>`?isampler2DArray'</td></tr><tr><td>`?GL_INT_SAMPLER_2D_MULTISAMPLE' -%% </td><td>`?isampler2DMS'</td></tr><tr><td>`?GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY'</td> -%% <td>`?isampler2DMSArray'</td></tr><tr><td>`?GL_INT_SAMPLER_BUFFER'</td><td>`?isamplerBuffer' -%% </td></tr><tr><td>`?GL_INT_SAMPLER_2D_RECT'</td><td>`?isampler2DRect'</td></tr><tr> -%% <td>`?GL_UNSIGNED_INT_SAMPLER_1D'</td><td>`?usampler1D'</td></tr><tr><td>`?GL_UNSIGNED_INT_SAMPLER_2D' -%% </td><td>`?usampler2D'</td></tr><tr><td>`?GL_UNSIGNED_INT_SAMPLER_3D'</td><td>`?usampler3D' -%% </td></tr><tr><td>`?GL_UNSIGNED_INT_SAMPLER_CUBE'</td><td>`?usamplerCube'</td></tr> -%% <tr><td>`?GL_UNSIGNED_INT_SAMPLER_1D_ARRAY'</td><td>`?usampler2DArray'</td></tr> -%% <tr><td>`?GL_UNSIGNED_INT_SAMPLER_2D_ARRAY'</td><td>`?usampler2DArray'</td></tr> -%% <tr><td>`?GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE'</td><td>`?usampler2DMS'</td></tr> -%% <tr><td>`?GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY'</td><td>`?usampler2DMSArray' -%% </td></tr><tr><td>`?GL_UNSIGNED_INT_SAMPLER_BUFFER'</td><td>`?usamplerBuffer'</td> -%% </tr><tr><td>`?GL_UNSIGNED_INT_SAMPLER_2D_RECT'</td><td>`?usampler2DRect'</td></tr> -%% <tr><td>`?GL_IMAGE_1D'</td><td>`?image1D'</td></tr><tr><td>`?GL_IMAGE_2D'</td> -%% <td>`?image2D'</td></tr><tr><td>`?GL_IMAGE_3D'</td><td>`?image3D'</td></tr> -%% <tr><td>`?GL_IMAGE_2D_RECT'</td><td>`?image2DRect'</td></tr><tr><td>`?GL_IMAGE_CUBE' -%% </td><td>`?imageCube'</td></tr><tr><td>`?GL_IMAGE_BUFFER'</td><td>`?imageBuffer' -%% </td></tr><tr><td>`?GL_IMAGE_1D_ARRAY'</td><td>`?image1DArray'</td></tr><tr><td> -%% `?GL_IMAGE_2D_ARRAY'</td><td>`?image2DArray'</td></tr><tr><td>`?GL_IMAGE_2D_MULTISAMPLE' -%% </td><td>`?image2DMS'</td></tr><tr><td>`?GL_IMAGE_2D_MULTISAMPLE_ARRAY'</td><td> -%% `?image2DMSArray'</td></tr><tr><td>`?GL_INT_IMAGE_1D'</td><td>`?iimage1D'</td> -%% </tr><tr><td>`?GL_INT_IMAGE_2D'</td><td>`?iimage2D'</td></tr><tr><td>`?GL_INT_IMAGE_3D' -%% </td><td>`?iimage3D'</td></tr><tr><td>`?GL_INT_IMAGE_2D_RECT'</td><td>`?iimage2DRect' -%% </td></tr><tr><td>`?GL_INT_IMAGE_CUBE'</td><td>`?iimageCube'</td></tr><tr><td>`?GL_INT_IMAGE_BUFFER' -%% </td><td>`?iimageBuffer'</td></tr><tr><td>`?GL_INT_IMAGE_1D_ARRAY'</td><td>`?iimage1DArray' -%% </td></tr><tr><td>`?GL_INT_IMAGE_2D_ARRAY'</td><td>`?iimage2DArray'</td></tr><tr> -%% <td>`?GL_INT_IMAGE_2D_MULTISAMPLE'</td><td>`?iimage2DMS'</td></tr><tr><td>`?GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY' -%% </td><td>`?iimage2DMSArray'</td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_1D'</td><td> -%% `?uimage1D'</td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_2D'</td><td>`?uimage2D' -%% </td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_3D'</td><td>`?uimage3D'</td></tr><tr><td> -%% `?GL_UNSIGNED_INT_IMAGE_2D_RECT'</td><td>`?uimage2DRect'</td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_CUBE' -%% </td><td>`?uimageCube'</td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_BUFFER'</td><td> -%% `?uimageBuffer'</td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_1D_ARRAY'</td><td>`?uimage1DArray' -%% </td></tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_2D_ARRAY'</td><td>`?uimage2DArray'</td> -%% </tr><tr><td>`?GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE'</td><td>`?uimage2DMS'</td></tr> -%% <tr><td>`?GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY'</td><td>`?uimage2DMSArray'</td> -%% </tr><tr><td>`?GL_UNSIGNED_INT_ATOMIC_COUNTER'</td><td>`?atomic_uint'</td></tr></tbody> -%% </table> -%% -%% If one or more elements of an array are active, the name of the array is returned in `Name' -%% , the type is returned in `Type' , and the `Size' parameter returns the highest -%% array element index used, plus one, as determined by the compiler and/or linker. Only -%% one active uniform variable will be reported for a uniform array. -%% -%% Uniform variables that are declared as structures or arrays of structures will not be -%% returned directly by this function. Instead, each of these uniform variables will be reduced -%% to its fundamental components containing the "." and "[]" operators such that each of -%% the names is valid as an argument to {@link gl:getUniformLocation/2} . Each of these reduced -%% uniform variables is counted as one active uniform variable and is assigned an index. -%% A valid name cannot be a structure, an array of structures, or a subcomponent of a vector -%% or matrix. -%% -%% The size of the uniform variable will be returned in `Size' . Uniform variables other -%% than arrays will have a size of 1. Structures and arrays of structures will be reduced -%% as described earlier, such that each of the names returned will be a data type in the -%% earlier list. If this reduction results in an array, the size returned will be as described -%% for uniform arrays; otherwise, the size returned will be 1. -%% -%% The list of active uniform variables may include both built-in uniform variables (which -%% begin with the prefix "gl_") as well as user-defined uniform variable names. -%% -%% This function will return as much information as it can about the specified active uniform -%% variable. If no information is available, `Length' will be 0, and `Name' will -%% be an empty string. This situation could occur if this function is called after a link -%% operation that failed. If an error occurs, the return values `Length' , `Size' , `Type' -%% , and `Name' will be unmodified. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniform.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveUniform.xhtml">external</a> documentation. -spec getActiveUniform(Program, Index, BufSize) -> {Size :: integer(),Type :: enum(),Name :: string()} when Program :: integer(),Index :: integer(),BufSize :: integer(). getActiveUniform(Program,Index,BufSize) -> call(5457, <<Program:?GLuint,Index:?GLuint,BufSize:?GLsizei>>). @@ -11047,13 +4554,7 @@ getActiveUniform(Program,Index,BufSize) -> %% number of shader names that may be returned in `Shaders' is specified by `MaxCount' %% . %% -%% If the number of names actually returned is not required (for instance, if it has just -%% been obtained by calling {@link gl:getProgramiv/2} ), a value of `?NULL' may be passed -%% for count. If no shader objects are attached to `Program' , a value of 0 will be returned -%% in `Count' . The actual number of attached shaders can be obtained by calling {@link gl:getProgramiv/2} -%% with the value `?GL_ATTACHED_SHADERS'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetAttachedShaders.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetAttachedShaders.xhtml">external</a> documentation. -spec getAttachedShaders(Program, MaxCount) -> [integer()] when Program :: integer(),MaxCount :: integer(). getAttachedShaders(Program,MaxCount) -> call(5458, <<Program:?GLuint,MaxCount:?GLsizei>>). @@ -11067,17 +4568,7 @@ getAttachedShaders(Program,MaxCount) -> %% attribute variable is not an active attribute in the specified program object or if `Name' %% starts with the reserved prefix "gl_", a value of -1 is returned. %% -%% The association between an attribute variable name and a generic attribute index can be -%% specified at any time by calling {@link gl:bindAttribLocation/3} . Attribute bindings do -%% not go into effect until {@link gl:linkProgram/1} is called. After a program object has -%% been linked successfully, the index values for attribute variables remain fixed until -%% the next link command occurs. The attribute values can only be queried after a link if -%% the link was successful. ``gl:getAttribLocation'' returns the binding that actually -%% went into effect the last time {@link gl:linkProgram/1} was called for the specified program -%% object. Attribute bindings that have been specified since the last link operation are -%% not returned by ``gl:getAttribLocation''. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetAttribLocation.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetAttribLocation.xhtml">external</a> documentation. -spec getAttribLocation(Program, Name) -> integer() when Program :: integer(),Name :: string(). getAttribLocation(Program,Name) -> NameLen = length(Name), @@ -11088,68 +4579,7 @@ getAttribLocation(Program,Name) -> %% ``gl:getProgram'' returns in `Params' the value of a parameter for a specific program %% object. The following parameters are defined: %% -%% `?GL_DELETE_STATUS': `Params' returns `?GL_TRUE' if `Program' is currently -%% flagged for deletion, and `?GL_FALSE' otherwise. -%% -%% `?GL_LINK_STATUS': `Params' returns `?GL_TRUE' if the last link operation -%% on `Program' was successful, and `?GL_FALSE' otherwise. -%% -%% `?GL_VALIDATE_STATUS': `Params' returns `?GL_TRUE' or if the last validation -%% operation on `Program' was successful, and `?GL_FALSE' otherwise. -%% -%% `?GL_INFO_LOG_LENGTH': `Params' returns the number of characters in the information -%% log for `Program' including the null termination character (i.e., the size of the -%% character buffer required to store the information log). If `Program' has no information -%% log, a value of 0 is returned. -%% -%% `?GL_ATTACHED_SHADERS': `Params' returns the number of shader objects attached -%% to `Program' . -%% -%% `?GL_ACTIVE_ATOMIC_COUNTER_BUFFERS': `Params' returns the number of active attribute -%% atomic counter buffers used by `Program' . -%% -%% `?GL_ACTIVE_ATTRIBUTES': `Params' returns the number of active attribute variables -%% for `Program' . -%% -%% `?GL_ACTIVE_ATTRIBUTE_MAX_LENGTH': `Params' returns the length of the longest -%% active attribute name for `Program' , including the null termination character (i.e., -%% the size of the character buffer required to store the longest attribute name). If no -%% active attributes exist, 0 is returned. -%% -%% `?GL_ACTIVE_UNIFORMS': `Params' returns the number of active uniform variables -%% for `Program' . -%% -%% `?GL_ACTIVE_UNIFORM_MAX_LENGTH': `Params' returns the length of the longest -%% active uniform variable name for `Program' , including the null termination character -%% (i.e., the size of the character buffer required to store the longest uniform variable -%% name). If no active uniform variables exist, 0 is returned. -%% -%% `?GL_PROGRAM_BINARY_LENGTH': `Params' returns the length of the program binary, -%% in bytes that will be returned by a call to {@link gl:getProgramBinary/2} . When a progam's -%% `?GL_LINK_STATUS' is `?GL_FALSE', its program binary length is zero. -%% -%% `?GL_TRANSFORM_FEEDBACK_BUFFER_MODE': `Params' returns a symbolic constant indicating -%% the buffer mode used when transform feedback is active. This may be `?GL_SEPARATE_ATTRIBS' -%% or `?GL_INTERLEAVED_ATTRIBS'. -%% -%% `?GL_TRANSFORM_FEEDBACK_VARYINGS': `Params' returns the number of varying variables -%% to capture in transform feedback mode for the program. -%% -%% `?GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH': `Params' returns the length of -%% the longest variable name to be used for transform feedback, including the null-terminator. -%% -%% -%% `?GL_GEOMETRY_VERTICES_OUT': `Params' returns the maximum number of vertices -%% that the geometry shader in `Program' will output. -%% -%% `?GL_GEOMETRY_INPUT_TYPE': `Params' returns a symbolic constant indicating the -%% primitive type accepted as input to the geometry shader contained in `Program' . -%% -%% `?GL_GEOMETRY_OUTPUT_TYPE': `Params' returns a symbolic constant indicating -%% the primitive type that will be output by the geometry shader contained in `Program' . -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgram.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetProgram.xhtml">external</a> documentation. -spec getProgramiv(Program, Pname) -> integer() when Program :: integer(),Pname :: enum(). getProgramiv(Program,Pname) -> call(5460, <<Program:?GLuint,Pname:?GLenum>>). @@ -11160,21 +4590,7 @@ getProgramiv(Program,Pname) -> %% The information log for a program object is modified when the program object is linked %% or validated. The string that is returned will be null terminated. %% -%% ``gl:getProgramInfoLog'' returns in `InfoLog' as much of the information log as -%% it can, up to a maximum of `MaxLength' characters. The number of characters actually -%% returned, excluding the null termination character, is specified by `Length' . If -%% the length of the returned string is not required, a value of `?NULL' can be passed -%% in the `Length' argument. The size of the buffer required to store the returned -%% information log can be obtained by calling {@link gl:getProgramiv/2} with the value `?GL_INFO_LOG_LENGTH' -%% . -%% -%% The information log for a program object is either an empty string, or a string containing -%% information about the last link operation, or a string containing information about the -%% last validation operation. It may contain diagnostic messages, warning messages, and -%% other information. When a program object is created, its information log will be a string -%% of length 0. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramInfoLog.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetProgramInfoLog.xhtml">external</a> documentation. -spec getProgramInfoLog(Program, BufSize) -> string() when Program :: integer(),BufSize :: integer(). getProgramInfoLog(Program,BufSize) -> call(5461, <<Program:?GLuint,BufSize:?GLsizei>>). @@ -11184,28 +4600,7 @@ getProgramInfoLog(Program,BufSize) -> %% ``gl:getShader'' returns in `Params' the value of a parameter for a specific %% shader object. The following parameters are defined: %% -%% `?GL_SHADER_TYPE': `Params' returns `?GL_VERTEX_SHADER' if `Shader' -%% is a vertex shader object, `?GL_GEOMETRY_SHADER' if `Shader' is a geometry -%% shader object, and `?GL_FRAGMENT_SHADER' if `Shader' is a fragment shader -%% object. -%% -%% `?GL_DELETE_STATUS': `Params' returns `?GL_TRUE' if `Shader' is -%% currently flagged for deletion, and `?GL_FALSE' otherwise. -%% -%% `?GL_COMPILE_STATUS': `Params' returns `?GL_TRUE' if the last compile -%% operation on `Shader' was successful, and `?GL_FALSE' otherwise. -%% -%% `?GL_INFO_LOG_LENGTH': `Params' returns the number of characters in the information -%% log for `Shader' including the null termination character (i.e., the size of -%% the character buffer required to store the information log). If `Shader' has -%% no information log, a value of 0 is returned. -%% -%% `?GL_SHADER_SOURCE_LENGTH': `Params' returns the length of the concatenation -%% of the source strings that make up the shader source for the `Shader' , including -%% the null termination character. (i.e., the size of the character buffer required to -%% store the shader source). If no source code exists, 0 is returned. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShader.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetShader.xhtml">external</a> documentation. -spec getShaderiv(Shader, Pname) -> integer() when Shader :: integer(),Pname :: enum(). getShaderiv(Shader,Pname) -> call(5462, <<Shader:?GLuint,Pname:?GLenum>>). @@ -11216,19 +4611,7 @@ getShaderiv(Shader,Pname) -> %% The information log for a shader object is modified when the shader is compiled. The %% string that is returned will be null terminated. %% -%% ``gl:getShaderInfoLog'' returns in `InfoLog' as much of the information log as -%% it can, up to a maximum of `MaxLength' characters. The number of characters actually -%% returned, excluding the null termination character, is specified by `Length' . If -%% the length of the returned string is not required, a value of `?NULL' can be passed -%% in the `Length' argument. The size of the buffer required to store the returned -%% information log can be obtained by calling {@link gl:getShaderiv/2} with the value `?GL_INFO_LOG_LENGTH' -%% . -%% -%% The information log for a shader object is a string that may contain diagnostic messages, -%% warning messages, and other information about the last compile operation. When a shader -%% object is created, its information log will be a string of length 0. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderInfoLog.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetShaderInfoLog.xhtml">external</a> documentation. -spec getShaderInfoLog(Shader, BufSize) -> string() when Shader :: integer(),BufSize :: integer(). getShaderInfoLog(Shader,BufSize) -> call(5463, <<Shader:?GLuint,BufSize:?GLsizei>>). @@ -11240,15 +4623,7 @@ getShaderInfoLog(Shader,BufSize) -> %% are the result of a previous call to {@link gl:shaderSource/2} . The string returned by %% the function will be null terminated. %% -%% ``gl:getShaderSource'' returns in `Source' as much of the source code string as -%% it can, up to a maximum of `BufSize' characters. The number of characters actually -%% returned, excluding the null termination character, is specified by `Length' . If -%% the length of the returned string is not required, a value of `?NULL' can be passed -%% in the `Length' argument. The size of the buffer required to store the returned source -%% code string can be obtained by calling {@link gl:getShaderiv/2} with the value `?GL_SHADER_SOURCE_LENGTH' -%% . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderSource.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetShaderSource.xhtml">external</a> documentation. -spec getShaderSource(Shader, BufSize) -> string() when Shader :: integer(),BufSize :: integer(). getShaderSource(Shader,BufSize) -> call(5464, <<Shader:?GLuint,BufSize:?GLsizei>>). @@ -11263,25 +4638,7 @@ getShaderSource(Shader,BufSize) -> %% in `Program' , if `Name' starts with the reserved prefix "gl_", or if `Name' %% is associated with an atomic counter or a named uniform block. %% -%% Uniform variables that are structures or arrays of structures may be queried by calling ``gl:getUniformLocation'' -%% for each field within the structure. The array element operator "[]" and the structure -%% field operator "." may be used in `Name' in order to select elements within an array -%% or fields within a structure. The result of using these operators is not allowed to be -%% another structure, an array of structures, or a subcomponent of a vector or a matrix. -%% Except if the last part of `Name' indicates a uniform variable array, the location -%% of the first element of an array can be retrieved by using the name of the array, or by -%% using the name appended by "[0]". -%% -%% The actual locations assigned to uniform variables are not known until the program object -%% is linked successfully. After linking has occurred, the command ``gl:getUniformLocation'' -%% can be used to obtain the location of a uniform variable. This location value can then -%% be passed to {@link gl:uniform1f/2} to set the value of the uniform variable or to {@link gl:getUniformfv/2} -%% in order to query the current value of the uniform variable. After a program object has -%% been linked successfully, the index values for uniform variables remain fixed until the -%% next link command occurs. Uniform variable locations and values can only be queried after -%% a link if the link was successful. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformLocation.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetUniformLocation.xhtml">external</a> documentation. -spec getUniformLocation(Program, Name) -> integer() when Program :: integer(),Name :: string(). getUniformLocation(Program,Name) -> NameLen = length(Name), @@ -11300,15 +4657,7 @@ getUniformLocation(Program,Name) -> %% The values for uniform variables declared as a matrix will be returned in column major %% order. %% -%% The locations assigned to uniform variables are not known until the program object is -%% linked. After linking has occurred, the command {@link gl:getUniformLocation/2} can be -%% used to obtain the location of a uniform variable. This location value can then be passed -%% to ``gl:getUniform'' in order to query the current value of the uniform variable. After -%% a program object has been linked successfully, the index values for uniform variables -%% remain fixed until the next link command occurs. The uniform variable values can only -%% be queried after a link if the link was successful. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniform.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetUniform.xhtml">external</a> documentation. -spec getUniformfv(Program, Location) -> matrix() when Program :: integer(),Location :: integer(). getUniformfv(Program,Location) -> call(5466, <<Program:?GLuint,Location:?GLint>>). @@ -11325,63 +4674,7 @@ getUniformiv(Program,Location) -> %% parameter. The generic vertex attribute to be queried is specified by `Index' , and %% the parameter to be queried is specified by `Pname' . %% -%% The accepted parameter names are as follows: -%% -%% `?GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING': `Params' returns a single value, the -%% name of the buffer object currently bound to the binding point corresponding to generic -%% vertex attribute array `Index' . If no buffer object is bound, 0 is returned. The -%% initial value is 0. -%% -%% `?GL_VERTEX_ATTRIB_ARRAY_ENABLED': `Params' returns a single value that is non-zero -%% (true) if the vertex attribute array for `Index' is enabled and 0 (false) if it is -%% disabled. The initial value is `?GL_FALSE'. -%% -%% `?GL_VERTEX_ATTRIB_ARRAY_SIZE': `Params' returns a single value, the size of -%% the vertex attribute array for `Index' . The size is the number of values for each -%% element of the vertex attribute array, and it will be 1, 2, 3, or 4. The initial value -%% is 4. -%% -%% `?GL_VERTEX_ATTRIB_ARRAY_STRIDE': `Params' returns a single value, the array -%% stride for (number of bytes between successive elements in) the vertex attribute array -%% for `Index' . A value of 0 indicates that the array elements are stored sequentially -%% in memory. The initial value is 0. -%% -%% `?GL_VERTEX_ATTRIB_ARRAY_TYPE': `Params' returns a single value, a symbolic -%% constant indicating the array type for the vertex attribute array for `Index' . Possible -%% values are `?GL_BYTE', `?GL_UNSIGNED_BYTE', `?GL_SHORT', `?GL_UNSIGNED_SHORT' -%% , `?GL_INT', `?GL_UNSIGNED_INT', `?GL_FLOAT', and `?GL_DOUBLE'. The -%% initial value is `?GL_FLOAT'. -%% -%% `?GL_VERTEX_ATTRIB_ARRAY_NORMALIZED': `Params' returns a single value that is -%% non-zero (true) if fixed-point data types for the vertex attribute array indicated by `Index' -%% are normalized when they are converted to floating point, and 0 (false) otherwise. The -%% initial value is `?GL_FALSE'. -%% -%% `?GL_VERTEX_ATTRIB_ARRAY_INTEGER': `Params' returns a single value that is non-zero -%% (true) if fixed-point data types for the vertex attribute array indicated by `Index' -%% have integer data types, and 0 (false) otherwise. The initial value is 0 (`?GL_FALSE'). -%% -%% -%% `?GL_VERTEX_ATTRIB_ARRAY_DIVISOR': `Params' returns a single value that is the -%% frequency divisor used for instanced rendering. See {@link gl:vertexAttribDivisor/2} . The -%% initial value is 0. -%% -%% `?GL_CURRENT_VERTEX_ATTRIB': `Params' returns four values that represent the -%% current value for the generic vertex attribute specified by index. Generic vertex attribute -%% 0 is unique in that it has no current state, so an error will be generated if `Index' -%% is 0. The initial value for all other generic vertex attributes is (0,0,0,1). -%% -%% ``gl:getVertexAttribdv'' and ``gl:getVertexAttribfv'' return the current attribute -%% values as four single-precision floating-point values; ``gl:getVertexAttribiv'' reads -%% them as floating-point values and converts them to four integer values; ``gl:getVertexAttribIiv'' -%% and ``gl:getVertexAttribIuiv'' read and return them as signed or unsigned integer values, -%% respectively; ``gl:getVertexAttribLdv'' reads and returns them as four double-precision -%% floating-point values. -%% -%% All of the parameters except `?GL_CURRENT_VERTEX_ATTRIB' represent state stored in -%% the currently bound vertex array object. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttrib.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetVertexAttrib.xhtml">external</a> documentation. -spec getVertexAttribdv(Index, Pname) -> {float(),float(),float(),float()} when Index :: integer(),Pname :: enum(). getVertexAttribdv(Index,Pname) -> call(5468, <<Index:?GLuint,Pname:?GLenum>>). @@ -11405,7 +4698,7 @@ getVertexAttribiv(Index,Pname) -> %% . If `Program' is zero or a non-zero value that is not the name of a program object, %% or if an error occurs, ``gl:isProgram'' returns `?GL_FALSE'. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsProgram.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsProgram.xhtml">external</a> documentation. -spec isProgram(Program) -> 0|1 when Program :: integer(). isProgram(Program) -> call(5471, <<Program:?GLuint>>). @@ -11417,7 +4710,7 @@ isProgram(Program) -> %% . If `Shader' is zero or a non-zero value that is not the name of a shader object, %% or if an error occurs, ``gl:isShader '' returns `?GL_FALSE'. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsShader.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsShader.xhtml">external</a> documentation. -spec isShader(Shader) -> 0|1 when Shader :: integer(). isShader(Shader) -> call(5472, <<Shader:?GLuint>>). @@ -11433,111 +4726,7 @@ isShader(Shader) -> %% they will be used to create an executable that will run on the programmable fragment processor. %% %% -%% The status of the link operation will be stored as part of the program object's state. -%% This value will be set to `?GL_TRUE' if the program object was linked without errors -%% and is ready for use, and `?GL_FALSE' otherwise. It can be queried by calling {@link gl:getProgramiv/2} -%% with arguments `Program' and `?GL_LINK_STATUS'. -%% -%% As a result of a successful link operation, all active user-defined uniform variables -%% belonging to `Program' will be initialized to 0, and each of the program object's -%% active uniform variables will be assigned a location that can be queried by calling {@link gl:getUniformLocation/2} -%% . Also, any active user-defined attribute variables that have not been bound to a generic -%% vertex attribute index will be bound to one at this time. -%% -%% Linking of a program object can fail for a number of reasons as specified in the `OpenGL Shading Language Specification' -%% . The following lists some of the conditions that will cause a link error. -%% -%% The number of active attribute variables supported by the implementation has been exceeded. -%% -%% -%% The storage limit for uniform variables has been exceeded. -%% -%% The number of active uniform variables supported by the implementation has been exceeded. -%% -%% The `main' function is missing for the vertex, geometry or fragment shader. -%% -%% A varying variable actually used in the fragment shader is not declared in the same way -%% (or is not declared at all) in the vertex shader, or geometry shader shader if present. -%% -%% A reference to a function or variable name is unresolved. -%% -%% A shared global is declared with two different types or two different initial values. -%% -%% One or more of the attached shader objects has not been successfully compiled. -%% -%% Binding a generic attribute matrix caused some rows of the matrix to fall outside the -%% allowed maximum of `?GL_MAX_VERTEX_ATTRIBS'. -%% -%% Not enough contiguous vertex attribute slots could be found to bind attribute matrices. -%% -%% The program object contains objects to form a fragment shader but does not contain objects -%% to form a vertex shader. -%% -%% The program object contains objects to form a geometry shader but does not contain objects -%% to form a vertex shader. -%% -%% The program object contains objects to form a geometry shader and the input primitive -%% type, output primitive type, or maximum output vertex count is not specified in any compiled -%% geometry shader object. -%% -%% The program object contains objects to form a geometry shader and the input primitive -%% type, output primitive type, or maximum output vertex count is specified differently in -%% multiple geometry shader objects. -%% -%% The number of active outputs in the fragment shader is greater than the value of `?GL_MAX_DRAW_BUFFERS' -%% . -%% -%% The program has an active output assigned to a location greater than or equal to the value -%% of `?GL_MAX_DUAL_SOURCE_DRAW_BUFFERS' and has an active output assigned an index -%% greater than or equal to one. -%% -%% More than one varying out variable is bound to the same number and index. -%% -%% The explicit binding assigments do not leave enough space for the linker to automatically -%% assign a location for a varying out array, which requires multiple contiguous locations. -%% -%% The `Count' specified by {@link gl:transformFeedbackVaryings/3} is non-zero, but the -%% program object has no vertex or geometry shader. -%% -%% Any variable name specified to {@link gl:transformFeedbackVaryings/3} in the `Varyings' -%% array is not declared as an output in the vertex shader (or the geometry shader, if active). -%% -%% -%% Any two entries in the `Varyings' array given {@link gl:transformFeedbackVaryings/3} -%% specify the same varying variable. -%% -%% The total number of components to capture in any transform feedback varying variable is -%% greater than the constant `?GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS' and the -%% buffer mode is `?SEPARATE_ATTRIBS'. -%% -%% When a program object has been successfully linked, the program object can be made part -%% of current state by calling {@link gl:useProgram/1} . Whether or not the link operation -%% was successful, the program object's information log will be overwritten. The information -%% log can be retrieved by calling {@link gl:getProgramInfoLog/2} . -%% -%% ``gl:linkProgram'' will also install the generated executables as part of the current -%% rendering state if the link operation was successful and the specified program object -%% is already currently in use as a result of a previous call to {@link gl:useProgram/1} . -%% If the program object currently in use is relinked unsuccessfully, its link status will -%% be set to `?GL_FALSE' , but the executables and associated state will remain part -%% of the current state until a subsequent call to ``gl:useProgram'' removes it from use. -%% After it is removed from use, it cannot be made part of current state until it has been -%% successfully relinked. -%% -%% If `Program' contains shader objects of type `?GL_VERTEX_SHADER', and optionally -%% of type `?GL_GEOMETRY_SHADER', but does not contain shader objects of type `?GL_FRAGMENT_SHADER' -%% , the vertex shader executable will be installed on the programmable vertex processor, -%% the geometry shader executable, if present, will be installed on the programmable geometry -%% processor, but no executable will be installed on the fragment processor. The results -%% of rasterizing primitives with such a program will be undefined. -%% -%% The program object's information log is updated and the program is generated at the time -%% of the link operation. After the link operation, applications are free to modify attached -%% shader objects, compile attached shader objects, detach shader objects, delete shader -%% objects, and attach additional shader objects. None of these operations affects the information -%% log or the program that is part of the program object. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLinkProgram.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glLinkProgram.xhtml">external</a> documentation. -spec linkProgram(Program) -> 'ok' when Program :: integer(). linkProgram(Program) -> cast(5473, <<Program:?GLuint>>). @@ -11555,7 +4744,7 @@ linkProgram(Program) -> %% than 0 to indicate that the string is null terminated. The source code strings are not %% scanned or parsed at this time; they are simply copied into the specified shader object. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShaderSource.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glShaderSource.xhtml">external</a> documentation. -spec shaderSource(Shader, String) -> 'ok' when Shader :: integer(),String :: iolist(). shaderSource(Shader,String) -> StringTemp = list_to_binary([[Str|[0]] || Str <- String ]), @@ -11570,35 +4759,7 @@ shaderSource(Shader,String) -> %% compiling the shader objects with {@link gl:compileShader/1} , and successfully linking %% the program object with {@link gl:linkProgram/1} . %% -%% A program object will contain an executable that will run on the vertex processor if -%% it contains one or more shader objects of type `?GL_VERTEX_SHADER' that have been -%% successfully compiled and linked. A program object will contain an executable that will -%% run on the geometry processor if it contains one or more shader objects of type `?GL_GEOMETRY_SHADER' -%% that have been successfully compiled and linked. Similarly, a program object will contain -%% an executable that will run on the fragment processor if it contains one or more shader -%% objects of type `?GL_FRAGMENT_SHADER' that have been successfully compiled and -%% linked. -%% -%% While a program object is in use, applications are free to modify attached shader objects, -%% compile attached shader objects, attach additional shader objects, and detach or delete -%% shader objects. None of these operations will affect the executables that are part of -%% the current state. However, relinking the program object that is currently in use will -%% install the program object as part of the current rendering state if the link operation -%% was successful (see {@link gl:linkProgram/1} ). If the program object currently in use -%% is relinked unsuccessfully, its link status will be set to `?GL_FALSE', but the -%% executables and associated state will remain part of the current state until a subsequent -%% call to ``gl:useProgram'' removes it from use. After it is removed from use, it cannot -%% be made part of current state until it has been successfully relinked. -%% -%% If `Program' is zero, then the current rendering state refers to an `invalid' -%% program object and the results of shader execution are undefined. However, this is not -%% an error. -%% -%% If `Program' does not contain shader objects of type `?GL_FRAGMENT_SHADER', -%% an executable will be installed on the vertex, and possibly geometry processors, but -%% the results of fragment shader execution will be undefined. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUseProgram.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUseProgram.xhtml">external</a> documentation. -spec useProgram(Program) -> 'ok' when Program :: integer(). useProgram(Program) -> cast(5475, <<Program:?GLuint>>). @@ -11611,62 +4772,7 @@ useProgram(Program) -> %% on the program object that was made part of current state by calling {@link gl:useProgram/1} %% . %% -%% The commands ``gl:uniform{1|2|3|4}{f|i|ui}'' are used to change the value of the uniform -%% variable specified by `Location' using the values passed as arguments. The number -%% specified in the command should match the number of components in the data type of the -%% specified uniform variable (e.g., `1' for float, int, unsigned int, bool; `2' -%% for vec2, ivec2, uvec2, bvec2, etc.). The suffix `f' indicates that floating-point -%% values are being passed; the suffix `i' indicates that integer values are being passed; -%% the suffix `ui' indicates that unsigned integer values are being passed, and this -%% type should also match the data type of the specified uniform variable. The `i' variants -%% of this function should be used to provide values for uniform variables defined as int, ivec2 -%% , ivec3, ivec4, or arrays of these. The `ui' variants of this function should be -%% used to provide values for uniform variables defined as unsigned int, uvec2, uvec3, uvec4, -%% or arrays of these. The `f' variants should be used to provide values for uniform -%% variables of type float, vec2, vec3, vec4, or arrays of these. Either the `i', `ui' -%% or `f' variants may be used to provide values for uniform variables of type bool, bvec2 -%% , bvec3, bvec4, or arrays of these. The uniform variable will be set to false if the input -%% value is 0 or 0.0f, and it will be set to true otherwise. -%% -%% All active uniform variables defined in a program object are initialized to 0 when the -%% program object is linked successfully. They retain the values assigned to them by a call -%% to ``gl:uniform '' until the next successful link operation occurs on the program object, -%% when they are once again initialized to 0. -%% -%% The commands ``gl:uniform{1|2|3|4}{f|i|ui}v'' can be used to modify a single uniform -%% variable or a uniform variable array. These commands pass a count and a pointer to the -%% values to be loaded into a uniform variable or a uniform variable array. A count of 1 -%% should be used if modifying the value of a single uniform variable, and a count of 1 or -%% greater can be used to modify an entire array or part of an array. When loading `n' -%% elements starting at an arbitrary position `m' in a uniform variable array, elements -%% `m' + `n' - 1 in the array will be replaced with the new values. If `M' + `N' -%% - 1 is larger than the size of the uniform variable array, values for all array elements -%% beyond the end of the array will be ignored. The number specified in the name of the command -%% indicates the number of components for each element in `Value' , and it should match -%% the number of components in the data type of the specified uniform variable (e.g., `1' -%% for float, int, bool; `2' for vec2, ivec2, bvec2, etc.). The data type specified -%% in the name of the command must match the data type for the specified uniform variable -%% as described previously for ``gl:uniform{1|2|3|4}{f|i|ui}''. -%% -%% For uniform variable arrays, each element of the array is considered to be of the type -%% indicated in the name of the command (e.g., ``gl:uniform3f'' or ``gl:uniform3fv'' -%% can be used to load a uniform variable array of type vec3). The number of elements of -%% the uniform variable array to be modified is specified by `Count' -%% -%% The commands ``gl:uniformMatrix{2|3|4|2x3|3x2|2x4|4x2|3x4|4x3}fv'' are used to modify -%% a matrix or an array of matrices. The numbers in the command name are interpreted as the -%% dimensionality of the matrix. The number `2' indicates a 2 × 2 matrix (i.e., 4 values), -%% the number `3' indicates a 3 × 3 matrix (i.e., 9 values), and the number `4' -%% indicates a 4 × 4 matrix (i.e., 16 values). Non-square matrix dimensionality is explicit, -%% with the first number representing the number of columns and the second number representing -%% the number of rows. For example, `2x4' indicates a 2 × 4 matrix with 2 columns and -%% 4 rows (i.e., 8 values). If `Transpose' is `?GL_FALSE', each matrix is assumed -%% to be supplied in column major order. If `Transpose' is `?GL_TRUE', each matrix -%% is assumed to be supplied in row major order. The `Count' argument indicates the -%% number of matrices to be passed. A count of 1 should be used if modifying the value of -%% a single matrix, and a count greater than 1 can be used to modify an array of matrices. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniform.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUniform.xhtml">external</a> documentation. -spec uniform1f(Location, V0) -> 'ok' when Location :: integer(),V0 :: float(). uniform1f(Location,V0) -> cast(5476, <<Location:?GLint,V0:?GLfloat>>). @@ -11811,19 +4917,7 @@ uniformMatrix4fv(Location,Transpose,Value) -> %% a way for OpenGL implementers to convey more information about why the current program %% is inefficient, suboptimal, failing to execute, and so on. %% -%% The status of the validation operation will be stored as part of the program object's -%% state. This value will be set to `?GL_TRUE' if the validation succeeded, and `?GL_FALSE' -%% otherwise. It can be queried by calling {@link gl:getProgramiv/2} with arguments `Program' -%% and `?GL_VALIDATE_STATUS'. If validation is successful, `Program' is guaranteed -%% to execute given the current state. Otherwise, `Program' is guaranteed to not execute. -%% -%% -%% This function is typically useful only during application development. The informational -%% string stored in the information log is completely implementation dependent; therefore, -%% an application should not expect different OpenGL implementations to produce identical -%% information strings. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgram.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glValidateProgram.xhtml">external</a> documentation. -spec validateProgram(Program) -> 'ok' when Program :: integer(). validateProgram(Program) -> cast(5495, <<Program:?GLuint>>). @@ -11833,72 +4927,7 @@ validateProgram(Program) -> %% The ``gl:vertexAttrib'' family of entry points allows an application to pass generic %% vertex attributes in numbered locations. %% -%% Generic attributes are defined as four-component values that are organized into an array. -%% The first entry of this array is numbered 0, and the size of the array is specified by -%% the implementation-dependent constant `?GL_MAX_VERTEX_ATTRIBS'. Individual elements -%% of this array can be modified with a ``gl:vertexAttrib'' call that specifies the index -%% of the element to be modified and a value for that element. -%% -%% These commands can be used to specify one, two, three, or all four components of the generic -%% vertex attribute specified by `Index' . A `1' in the name of the command indicates -%% that only one value is passed, and it will be used to modify the first component of the -%% generic vertex attribute. The second and third components will be set to 0, and the fourth -%% component will be set to 1. Similarly, a `2' in the name of the command indicates -%% that values are provided for the first two components, the third component will be set -%% to 0, and the fourth component will be set to 1. A `3' in the name of the command -%% indicates that values are provided for the first three components and the fourth component -%% will be set to 1, whereas a `4' in the name indicates that values are provided for -%% all four components. -%% -%% The letters `s', `f', `i', `d', `ub', `us', and `ui' -%% indicate whether the arguments are of type short, float, int, double, unsigned byte, unsigned -%% short, or unsigned int. When `v' is appended to the name, the commands can take a -%% pointer to an array of such values. -%% -%% Additional capitalized letters can indicate further alterations to the default behavior -%% of the glVertexAttrib function: -%% -%% The commands containing `N' indicate that the arguments will be passed as fixed-point -%% values that are scaled to a normalized range according to the component conversion rules -%% defined by the OpenGL specification. Signed values are understood to represent fixed-point -%% values in the range [-1,1], and unsigned values are understood to represent fixed-point -%% values in the range [0,1]. -%% -%% The commands containing `I' indicate that the arguments are extended to full signed -%% or unsigned integers. -%% -%% The commands containing `P' indicate that the arguments are stored as packed components -%% within a larger natural type. -%% -%% The commands containing `L' indicate that the arguments are full 64-bit quantities -%% and should be passed directly to shader inputs declared as 64-bit double precision types. -%% -%% -%% OpenGL Shading Language attribute variables are allowed to be of type mat2, mat3, or mat4. -%% Attributes of these types may be loaded using the ``gl:vertexAttrib'' entry points. -%% Matrices must be loaded into successive generic attribute slots in column major order, -%% with one column of the matrix in each generic attribute slot. -%% -%% A user-defined attribute variable declared in a vertex shader can be bound to a generic -%% attribute index by calling {@link gl:bindAttribLocation/3} . This allows an application -%% to use more descriptive variable names in a vertex shader. A subsequent change to the -%% specified generic vertex attribute will be immediately reflected as a change to the corresponding -%% attribute variable in the vertex shader. -%% -%% The binding between a generic vertex attribute index and a user-defined attribute variable -%% in a vertex shader is part of the state of a program object, but the current value of -%% the generic vertex attribute is not. The value of each generic vertex attribute is part -%% of current state, just like standard vertex attributes, and it is maintained even if a -%% different program object is used. -%% -%% An application may freely modify generic vertex attributes that are not bound to a named -%% vertex shader attribute variable. These values are simply maintained as part of current -%% state and will not be accessed by the vertex shader. If a generic vertex attribute bound -%% to an attribute variable in a vertex shader is not updated while the vertex shader is -%% executing, the vertex shader will repeatedly use the current value for the generic vertex -%% attribute. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttrib.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttrib.xhtml">external</a> documentation. -spec vertexAttrib1d(Index, X) -> 'ok' when Index :: integer(),X :: float(). vertexAttrib1d(Index,X) -> cast(5496, <<Index:?GLuint,0:32,X:?GLdouble>>). @@ -12096,37 +5125,7 @@ vertexAttrib4usv(Index,{V1,V2,V3,V4}) -> %% and `Stride' specifies the byte stride from one attribute to the next, allowing vertices %% and attributes to be packed into a single array or stored in separate arrays. %% -%% For ``gl:vertexAttribPointer'', if `Normalized' is set to `?GL_TRUE', it -%% indicates that values stored in an integer format are to be mapped to the range [-1,1] -%% (for signed values) or [0,1] (for unsigned values) when they are accessed and converted -%% to floating point. Otherwise, values will be converted to floats directly without normalization. -%% -%% -%% For ``gl:vertexAttribIPointer'', only the integer types `?GL_BYTE', `?GL_UNSIGNED_BYTE' -%% , `?GL_SHORT', `?GL_UNSIGNED_SHORT', `?GL_INT', `?GL_UNSIGNED_INT' -%% are accepted. Values are always left as integer values. -%% -%% ``gl:vertexAttribLPointer'' specifies state for a generic vertex attribute array associated -%% with a shader attribute variable declared with 64-bit double precision components. `Type' -%% must be `?GL_DOUBLE'. `Index' , `Size' , and `Stride' behave as described -%% for ``gl:vertexAttribPointer'' and ``gl:vertexAttribIPointer''. -%% -%% If `Pointer' is not NULL, a non-zero named buffer object must be bound to the `?GL_ARRAY_BUFFER' -%% target (see {@link gl:bindBuffer/2} ), otherwise an error is generated. `Pointer' -%% is treated as a byte offset into the buffer object's data store. The buffer object binding -%% (`?GL_ARRAY_BUFFER_BINDING') is saved as generic vertex attribute array state (`?GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING' -%% ) for index `Index' . -%% -%% When a generic vertex attribute array is specified, `Size' , `Type' , `Normalized' -%% , `Stride' , and `Pointer' are saved as vertex array state, in addition to the -%% current vertex array buffer object binding. -%% -%% To enable and disable a generic vertex attribute array, call {@link gl:disableVertexAttribArray/1} -%% and {@link gl:disableVertexAttribArray/1} with `Index' . If enabled, the generic vertex -%% attribute array is used when {@link gl:drawArrays/3} , {@link gl:multiDrawArrays/3} , {@link gl:drawElements/4} -%% , see `glMultiDrawElements', or {@link gl:drawRangeElements/6} is called. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribPointer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttribPointer.xhtml">external</a> documentation. -spec vertexAttribPointer(Index, Size, Type, Normalized, Stride, Pointer) -> 'ok' when Index :: integer(),Size :: integer(),Type :: enum(),Normalized :: 0|1,Stride :: integer(),Pointer :: offset()|mem(). vertexAttribPointer(Index,Size,Type,Normalized,Stride,Pointer) when is_integer(Pointer) -> cast(5519, <<Index:?GLuint,Size:?GLint,Type:?GLenum,Normalized:?GLboolean,0:24,Stride:?GLsizei,Pointer:?GLuint>>); @@ -12184,7 +5183,7 @@ uniformMatrix4x3fv(Location,Transpose,Value) -> %% @doc glColorMaski %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glColorMaski.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec colorMaski(Index, R, G, B, A) -> 'ok' when Index :: integer(),R :: 0|1,G :: 0|1,B :: 0|1,A :: 0|1. colorMaski(Index,R,G,B,A) -> cast(5527, <<Index:?GLuint,R:?GLboolean,G:?GLboolean,B:?GLboolean,A:?GLboolean>>). @@ -12209,14 +5208,14 @@ enablei(Target,Index) -> %% @doc glEnablei %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glEnablei.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec disablei(Target, Index) -> 'ok' when Target :: enum(),Index :: integer(). disablei(Target,Index) -> cast(5531, <<Target:?GLenum,Index:?GLuint>>). %% @doc glIsEnabledi %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsEnabledi.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec isEnabledi(Target, Index) -> 0|1 when Target :: enum(),Index :: integer(). isEnabledi(Target,Index) -> call(5532, <<Target:?GLenum,Index:?GLuint>>). @@ -12228,23 +5227,7 @@ isEnabledi(Target,Index) -> %% a call to ``gl:beginTransformFeedback'' until a subsequent call to {@link gl:beginTransformFeedback/1} %% . Transform feedback commands must be paired. %% -%% If no geometry shader is present, while transform feedback is active the `Mode' -%% parameter to {@link gl:drawArrays/3} must match those specified in the following table: <table> -%% <tbody><tr><td>` Transform Feedback ' `PrimitiveMode' </td><td>` Allowed Render Primitive ' -%% `Modes' </td></tr></tbody><tbody><tr><td>`?GL_POINTS'</td><td>`?GL_POINTS'</td> -%% </tr><tr><td>`?GL_LINES'</td><td>`?GL_LINES', `?GL_LINE_LOOP', `?GL_LINE_STRIP' -%% , `?GL_LINES_ADJACENCY', `?GL_LINE_STRIP_ADJACENCY'</td></tr><tr><td>`?GL_TRIANGLES' -%% </td><td>`?GL_TRIANGLES', `?GL_TRIANGLE_STRIP', `?GL_TRIANGLE_FAN', `?GL_TRIANGLES_ADJACENCY' -%% , `?GL_TRIANGLE_STRIP_ADJACENCY'</td></tr></tbody></table> -%% -%% If a geometry shader is present, the output primitive type from the geometry shader must -%% match those provided in the following table: <table><tbody><tr><td>` Transform Feedback ' -%% `PrimitiveMode' </td><td>` Allowed Geometry Shader Output Primitive Type '</td></tr> -%% </tbody><tbody><tr><td>`?GL_POINTS'</td><td>`?points'</td></tr><tr><td>`?GL_LINES' -%% </td><td>`?line_strip'</td></tr><tr><td>`?GL_TRIANGLES'</td><td>`?triangle_strip' -%% </td></tr></tbody></table> -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginTransformFeedback.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBeginTransformFeedback.xhtml">external</a> documentation. -spec beginTransformFeedback(PrimitiveMode) -> 'ok' when PrimitiveMode :: enum(). beginTransformFeedback(PrimitiveMode) -> cast(5533, <<PrimitiveMode:?GLenum>>). @@ -12265,11 +5248,7 @@ endTransformFeedback() -> %% a range of `Buffer' to the indexed buffer binding target, ``gl:bindBufferBase'' %% also binds the range to the generic buffer binding point specified by `Target' . %% -%% `Offset' specifies the offset in basic machine units into the buffer object `Buffer' -%% and `Size' specifies the amount of data that can be read from the buffer object -%% while used as an indexed target. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindBufferRange.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindBufferRange.xhtml">external</a> documentation. -spec bindBufferRange(Target, Index, Buffer, Offset, Size) -> 'ok' when Target :: enum(),Index :: integer(),Buffer :: integer(),Offset :: integer(),Size :: integer(). bindBufferRange(Target,Index,Buffer,Offset,Size) -> cast(5535, <<Target:?GLenum,Index:?GLuint,Buffer:?GLuint,0:32,Offset:?GLintptr,Size:?GLsizeiptr>>). @@ -12284,7 +5263,7 @@ bindBufferRange(Target,Index,Buffer,Offset,Size) -> %% binding target, ``gl:bindBufferBase'' also binds `Buffer' to the generic buffer %% binding point specified by `Target' . %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindBufferBase.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindBufferBase.xhtml">external</a> documentation. -spec bindBufferBase(Target, Index, Buffer) -> 'ok' when Target :: enum(),Index :: integer(),Buffer :: integer(). bindBufferBase(Target,Index,Buffer) -> cast(5536, <<Target:?GLenum,Index:?GLuint,Buffer:?GLuint>>). @@ -12297,32 +5276,7 @@ bindBufferBase(Target,Index,Buffer) -> %% from the emitted vertices. Otherwise, the values of the selected vertex shader outputs %% are recorded. %% -%% The state set by ``gl:tranformFeedbackVaryings'' is stored and takes effect next time {@link gl:linkProgram/1} -%% is called on `Program' . When {@link gl:linkProgram/1} is called, `Program' is -%% linked so that the values of the specified varying variables for the vertices of each -%% primitive generated by the GL are written to a single buffer object if `BufferMode' -%% is `?GL_INTERLEAVED_ATTRIBS' or multiple buffer objects if `BufferMode' is `?GL_SEPARATE_ATTRIBS' -%% . -%% -%% In addition to the errors generated by ``gl:transformFeedbackVaryings'', the program `Program' -%% will fail to link if: -%% -%% The count specified by ``gl:transformFeedbackVaryings'' is non-zero, but the program -%% object has no vertex or geometry shader. -%% -%% Any variable name specified in the `Varyings' array is not declared as an output -%% in the vertex shader (or the geometry shader, if active). -%% -%% Any two entries in the `Varyings' array specify the same varying variable. -%% -%% The total number of components to capture in any varying variable in `Varyings' -%% is greater than the constant `?GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS' and -%% the buffer mode is `?GL_SEPARATE_ATTRIBS'. -%% -%% The total number of components to capture is greater than the constant `?GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS' -%% and the buffer mode is `?GL_INTERLEAVED_ATTRIBS'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTransformFeedbackVaryings.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTransformFeedbackVaryings.xhtml">external</a> documentation. -spec transformFeedbackVaryings(Program, Varyings, BufferMode) -> 'ok' when Program :: integer(),Varyings :: iolist(),BufferMode :: enum(). transformFeedbackVaryings(Program,Varyings,BufferMode) -> VaryingsTemp = list_to_binary([[Str|[0]] || Str <- Varyings ]), @@ -12338,26 +5292,7 @@ transformFeedbackVaryings(Program,Varyings,BufferMode) -> %% the `Varyings' array passed to {@link gl:transformFeedbackVaryings/3} , and an `Index' %% of `?GL_TRANSFORM_FEEDBACK_VARYINGS-1' selects the last such variable. %% -%% The name of the selected varying is returned as a null-terminated string in `Name' . -%% The actual number of characters written into `Name' , excluding the null terminator, -%% is returned in `Length' . If `Length' is NULL, no length is returned. The maximum -%% number of characters that may be written into `Name' , including the null terminator, -%% is specified by `BufSize' . -%% -%% The length of the longest varying name in program is given by `?GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH' -%% , which can be queried with {@link gl:getProgramiv/2} . -%% -%% For the selected varying variable, its type is returned into `Type' . The size of -%% the varying is returned into `Size' . The value in `Size' is in units of the -%% type returned in `Type' . The type returned can be any of the scalar, vector, or matrix -%% attribute types returned by {@link gl:getActiveAttrib/3} . If an error occurred, the return -%% parameters `Length' , `Size' , `Type' and `Name' will be unmodified. -%% This command will return as much information about the varying variables as possible. -%% If no information is available, `Length' will be set to zero and `Name' will -%% be an empty string. This situation could arise if ``gl:getTransformFeedbackVarying'' -%% is called after a failed link. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTransformFeedbackVarying.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetTransformFeedbackVarying.xhtml">external</a> documentation. -spec getTransformFeedbackVarying(Program, Index, BufSize) -> {Size :: integer(),Type :: enum(),Name :: string()} when Program :: integer(),Index :: integer(),BufSize :: integer(). getTransformFeedbackVarying(Program,Index,BufSize) -> call(5538, <<Program:?GLuint,Index:?GLuint,BufSize:?GLsizei>>). @@ -12372,7 +5307,7 @@ getTransformFeedbackVarying(Program,Index,BufSize) -> %% is disabled. If `Clamp' is `?GL_FIXED_ONLY', read color clamping is enabled %% only if the selected read buffer has fixed point components and disabled otherwise. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClampColor.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glClampColor.xhtml">external</a> documentation. -spec clampColor(Target, Clamp) -> 'ok' when Target :: enum(),Clamp :: enum(). clampColor(Target,Clamp) -> cast(5539, <<Target:?GLenum,Clamp:?GLenum>>). @@ -12393,18 +5328,7 @@ clampColor(Target,Clamp) -> %% is `?GL_QUERY_NO_WAIT', the GL may choose to unconditionally execute the subsequent %% rendering commands without waiting for the query to complete. %% -%% If `Mode' is `?GL_QUERY_BY_REGION_WAIT', the GL will also wait for occlusion -%% query results and discard rendering commands if the result of the occlusion query is zero. -%% If the query result is non-zero, subsequent rendering commands are executed, but the GL -%% may discard the results of the commands for any region of the framebuffer that did not -%% contribute to the sample count in the specified occlusion query. Any such discarding is -%% done in an implementation-dependent manner, but the rendering command results may not -%% be discarded for any samples that contributed to the occlusion query sample count. If `Mode' -%% is `?GL_QUERY_BY_REGION_NO_WAIT', the GL operates as in `?GL_QUERY_BY_REGION_WAIT' -%% , but may choose to unconditionally execute the subsequent rendering commands without -%% waiting for the query to complete. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginConditionalRender.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBeginConditionalRender.xhtml">external</a> documentation. -spec beginConditionalRender(Id, Mode) -> 'ok' when Id :: integer(),Mode :: enum(). beginConditionalRender(Id,Mode) -> cast(5540, <<Id:?GLuint,Mode:?GLenum>>). @@ -12417,7 +5341,7 @@ endConditionalRender() -> %% @doc glVertexAttribIPointer %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribIPointer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec vertexAttribIPointer(Index, Size, Type, Stride, Pointer) -> 'ok' when Index :: integer(),Size :: integer(),Type :: enum(),Stride :: integer(),Pointer :: offset()|mem(). vertexAttribIPointer(Index,Size,Type,Stride,Pointer) when is_integer(Pointer) -> cast(5542, <<Index:?GLuint,Size:?GLint,Type:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>); @@ -12433,7 +5357,7 @@ getVertexAttribIiv(Index,Pname) -> %% @doc glGetVertexAttribI %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttribI.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getVertexAttribIuiv(Index, Pname) -> {integer(),integer(),integer(),integer()} when Index :: integer(),Pname :: enum(). getVertexAttribIuiv(Index,Pname) -> call(5545, <<Index:?GLuint,Pname:?GLenum>>). @@ -12556,21 +5480,7 @@ getUniformuiv(Program,Location) -> %% . `Name' must be a null-terminated string. `ColorNumber' must be less than `?GL_MAX_DRAW_BUFFERS' %% . %% -%% The bindings specified by ``gl:bindFragDataLocation'' have no effect until `Program' -%% is next linked. Bindings may be specified at any time after `Program' has been created. -%% Specifically, they may be specified before shader objects are attached to the program. -%% Therefore, any name may be specified in `Name' , including a name that is never used -%% as a varying out variable in any fragment shader object. Names beginning with `?gl_' -%% are reserved by the GL. -%% -%% In addition to the errors generated by ``gl:bindFragDataLocation'', the program `Program' -%% will fail to link if: -%% -%% The number of active outputs is greater than the value `?GL_MAX_DRAW_BUFFERS'. -%% -%% More than one varying out variable is bound to the same color number. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindFragDataLocation.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindFragDataLocation.xhtml">external</a> documentation. -spec bindFragDataLocation(Program, Color, Name) -> 'ok' when Program :: integer(),Color :: integer(),Name :: string(). bindFragDataLocation(Program,Color,Name) -> NameLen = length(Name), @@ -12584,7 +5494,7 @@ bindFragDataLocation(Program,Color,Name) -> %% not the name of an active user-defined varying out fragment shader variable within `Program' %% , -1 will be returned. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetFragDataLocation.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetFragDataLocation.xhtml">external</a> documentation. -spec getFragDataLocation(Program, Name) -> integer() when Program :: integer(),Name :: string(). getFragDataLocation(Program,Name) -> NameLen = length(Name), @@ -12655,7 +5565,7 @@ texParameterIiv(Target,Pname,Params) -> %% @doc glTexParameterI %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexParameterI.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec texParameterIuiv(Target, Pname, Params) -> 'ok' when Target :: enum(),Pname :: enum(),Params :: tuple(). texParameterIuiv(Target,Pname,Params) -> cast(5570, <<Target:?GLenum,Pname:?GLenum,(size(Params)):?GLuint, @@ -12669,7 +5579,7 @@ getTexParameterIiv(Target,Pname) -> %% @doc glGetTexParameterI %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetTexParameterI.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getTexParameterIuiv(Target, Pname) -> {integer(),integer(),integer(),integer()} when Target :: enum(),Pname :: enum(). getTexParameterIuiv(Target,Pname) -> call(5572, <<Target:?GLenum,Pname:?GLenum>>). @@ -12685,24 +5595,7 @@ getTexParameterIuiv(Target,Pname) -> %% and conversion for fixed-point color buffers are performed in the same fashion as {@link gl:clearColor/4} %% . %% -%% If `Buffer' is `?GL_DEPTH', `DrawBuffer' must be zero, and `Value' -%% points to a single value to clear the depth buffer to. Only ``gl:clearBufferfv'' should -%% be used to clear depth buffers. Clamping and conversion for fixed-point depth buffers -%% are performed in the same fashion as {@link gl:clearDepth/1} . -%% -%% If `Buffer' is `?GL_STENCIL', `DrawBuffer' must be zero, and `Value' -%% points to a single value to clear the stencil buffer to. Only ``gl:clearBufferiv'' should -%% be used to clear stencil buffers. Masing and type conversion are performed in the same -%% fashion as {@link gl:clearStencil/1} . -%% -%% ``gl:clearBufferfi'' may be used to clear the depth and stencil buffers. `Buffer' -%% must be `?GL_DEPTH_STENCIL' and `DrawBuffer' must be zero. `Depth' and `Stencil' -%% are the depth and stencil values, respectively. -%% -%% The result of ``gl:clearBuffer'' is undefined if no conversion between the type of `Value' -%% and the buffer being cleared is defined. However, this is not an error. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearBuffer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glClearBuffer.xhtml">external</a> documentation. -spec clearBufferiv(Buffer, Drawbuffer, Value) -> 'ok' when Buffer :: enum(),Drawbuffer :: integer(),Value :: tuple(). clearBufferiv(Buffer,Drawbuffer,Value) -> cast(5573, <<Buffer:?GLenum,Drawbuffer:?GLint,(size(Value)):?GLuint, @@ -12724,7 +5617,7 @@ clearBufferfv(Buffer,Drawbuffer,Value) -> %% @doc glClearBufferfi %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearBufferfi.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec clearBufferfi(Buffer, Drawbuffer, Depth, Stencil) -> 'ok' when Buffer :: enum(),Drawbuffer :: integer(),Depth :: float(),Stencil :: integer(). clearBufferfi(Buffer,Drawbuffer,Depth,Stencil) -> cast(5576, <<Buffer:?GLenum,Drawbuffer:?GLint,Depth:?GLfloat,Stencil:?GLint>>). @@ -12737,14 +5630,14 @@ getStringi(Name,Index) -> %% @doc glDrawArraysInstance %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawArraysInstance.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec drawArraysInstanced(Mode, First, Count, Primcount) -> 'ok' when Mode :: enum(),First :: integer(),Count :: integer(),Primcount :: integer(). drawArraysInstanced(Mode,First,Count,Primcount) -> cast(5578, <<Mode:?GLenum,First:?GLint,Count:?GLsizei,Primcount:?GLsizei>>). %% @doc glDrawElementsInstance %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsInstance.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec drawElementsInstanced(Mode, Count, Type, Indices, Primcount) -> 'ok' when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Primcount :: integer(). drawElementsInstanced(Mode,Count,Type,Indices,Primcount) when is_integer(Indices) -> cast(5579, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Primcount:?GLsizei>>); @@ -12760,62 +5653,9 @@ drawElementsInstanced(Mode,Count,Type,Indices,Primcount) -> %% buffer texture is detached and no new buffer object is attached. If `Buffer' is non-zero, %% it must be the name of an existing buffer object. `Target' must be `?GL_TEXTURE_BUFFER' %% . `Internalformat' specifies the storage format, and must be one of the following -%% sized internal formats: <table><tbody><tr><td></td><td></td><td></td><td></td><td>` Component ' -%% </td></tr></tbody><tbody><tr><td>`Sized Internal Format'</td><td>`Base Type'</td> -%% <td>`Components'</td><td>`Norm'</td><td>0</td><td>1</td><td>2</td><td>3</td></tr> -%% <tr><td>`?GL_R8'</td><td>ubyte</td><td>1</td><td>YES</td><td>R</td><td>0</td><td>0</td> -%% <td>1</td></tr><tr><td>`?GL_R16'</td><td>ushort</td><td>1</td><td>YES</td><td>R</td><td> -%% 0</td><td>0</td><td>1</td></tr><tr><td>`?GL_R16F'</td><td>half</td><td>1</td><td>NO</td> -%% <td>R</td><td>0</td><td>0</td><td>1</td></tr><tr><td>`?GL_R32F'</td><td>float</td><td> -%% 1</td><td>NO</td><td>R</td><td>0</td><td>0</td><td>1</td></tr><tr><td>`?GL_R8I'</td><td> -%% byte</td><td>1</td><td>NO</td><td>R</td><td>0</td><td>0</td><td>1</td></tr><tr><td>`?GL_R16I' -%% </td><td>short</td><td>1</td><td>NO</td><td>R</td><td>0</td><td>0</td><td>1</td></tr><tr><td> -%% `?GL_R32I'</td><td>int</td><td>1</td><td>NO</td><td>R</td><td>0</td><td>0</td><td>1</td> -%% </tr><tr><td>`?GL_R8UI'</td><td>ubyte</td><td>1</td><td>NO</td><td>R</td><td>0</td><td> -%% 0</td><td>1</td></tr><tr><td>`?GL_R16UI'</td><td>ushort</td><td>1</td><td>NO</td><td> -%% R</td><td>0</td><td>0</td><td>1</td></tr><tr><td>`?GL_R32UI'</td><td>uint</td><td>1</td> -%% <td>NO</td><td>R</td><td>0</td><td>0</td><td>1</td></tr><tr><td>`?GL_RG8'</td><td>ubyte -%% </td><td>2</td><td>YES</td><td>R</td><td>G</td><td>0</td><td>1</td></tr><tr><td>`?GL_RG16' -%% </td><td>ushort</td><td>2</td><td>YES</td><td>R</td><td>G</td><td>0</td><td>1</td></tr><tr> -%% <td>`?GL_RG16F'</td><td>half</td><td>2</td><td>NO</td><td>R</td><td>G</td><td>0</td><td> -%% 1</td></tr><tr><td>`?GL_RG32F'</td><td>float</td><td>2</td><td>NO</td><td>R</td><td>G -%% </td><td>0</td><td>1</td></tr><tr><td>`?GL_RG8I'</td><td>byte</td><td>2</td><td>NO</td> -%% <td>R</td><td>G</td><td>0</td><td>1</td></tr><tr><td>`?GL_RG16I'</td><td>short</td><td> -%% 2</td><td>NO</td><td>R</td><td>G</td><td>0</td><td>1</td></tr><tr><td>`?GL_RG32I'</td> -%% <td>int</td><td>2</td><td>NO</td><td>R</td><td>G</td><td>0</td><td>1</td></tr><tr><td>`?GL_RG8UI' -%% </td><td>ubyte</td><td>2</td><td>NO</td><td>R</td><td>G</td><td>0</td><td>1</td></tr><tr><td> -%% `?GL_RG16UI'</td><td>ushort</td><td>2</td><td>NO</td><td>R</td><td>G</td><td>0</td><td> -%% 1</td></tr><tr><td>`?GL_RG32UI'</td><td>uint</td><td>2</td><td>NO</td><td>R</td><td>G -%% </td><td>0</td><td>1</td></tr><tr><td>`?GL_RGB32F'</td><td>float</td><td>3</td><td>NO -%% </td><td>R</td><td>G</td><td>B</td><td>1</td></tr><tr><td>`?GL_RGB32I'</td><td>int</td> -%% <td>3</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>1</td></tr><tr><td>`?GL_RGB32UI' -%% </td><td>uint</td><td>3</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>1</td></tr><tr><td> -%% `?GL_RGBA8'</td><td>uint</td><td>4</td><td>YES</td><td>R</td><td>G</td><td>B</td><td> -%% A</td></tr><tr><td>`?GL_RGBA16'</td><td>short</td><td>4</td><td>YES</td><td>R</td><td> -%% G</td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA16F'</td><td>half</td><td>4</td><td>NO -%% </td><td>R</td><td>G</td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA32F'</td><td>float -%% </td><td>4</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA8I' -%% </td><td>byte</td><td>4</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>A</td></tr><tr><td> -%% `?GL_RGBA16I'</td><td>short</td><td>4</td><td>NO</td><td>R</td><td>G</td><td>B</td><td> -%% A</td></tr><tr><td>`?GL_RGBA32I'</td><td>int</td><td>4</td><td>NO</td><td>R</td><td>G -%% </td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA8UI'</td><td>ubyte</td><td>4</td><td>NO -%% </td><td>R</td><td>G</td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA16UI'</td><td>ushort -%% </td><td>4</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>A</td></tr><tr><td>`?GL_RGBA32UI' -%% </td><td>uint</td><td>4</td><td>NO</td><td>R</td><td>G</td><td>B</td><td>A</td></tr></tbody> -%% </table> -%% -%% When a buffer object is attached to a buffer texture, the buffer object's data store -%% is taken as the texture's texel array. The number of texels in the buffer texture's texel -%% array is given by buffer_size components×sizeof( base_type/) -%% -%% where `buffer_size' is the size of the buffer object, in basic machine units and -%% components and base type are the element count and base data type for elements, as specified -%% in the table above. The number of texels in the texel array is then clamped to the implementation-dependent -%% limit `?GL_MAX_TEXTURE_BUFFER_SIZE'. When a buffer texture is accessed in a shader, -%% the results of a texel fetch are undefined if the specified texel coordinate is negative, -%% or greater than or equal to the clamped number of texels in the texel array. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexBuffer.xml">external</a> documentation. +%% sized internal formats: +%% +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexBuffer.xhtml">external</a> documentation. -spec texBuffer(Target, Internalformat, Buffer) -> 'ok' when Target :: enum(),Internalformat :: enum(),Buffer :: integer(). texBuffer(Target,Internalformat,Buffer) -> cast(5581, <<Target:?GLenum,Internalformat:?GLenum,Buffer:?GLuint>>). @@ -12825,19 +5665,7 @@ texBuffer(Target,Internalformat,Buffer) -> %% ``gl:primitiveRestartIndex'' specifies a vertex array element that is treated specially %% when primitive restarting is enabled. This is known as the primitive restart index. %% -%% When one of the `Draw*' commands transfers a set of generic attribute array elements -%% to the GL, if the index within the vertex arrays corresponding to that set is equal to -%% the primitive restart index, then the GL does not process those elements as a vertex. -%% Instead, it is as if the drawing command ended with the immediately preceding transfer, -%% and another drawing command is immediately started with the same parameters, but only -%% transferring the immediately following element through the end of the originally specified -%% elements. -%% -%% When either {@link gl:drawElementsBaseVertex/5} , {@link gl:drawElementsInstancedBaseVertex/6} -%% or see `glMultiDrawElementsBaseVertex' is used, the primitive restart comparison -%% occurs before the basevertex offset is added to the array index. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPrimitiveRestartIndex.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPrimitiveRestartIndex.xhtml">external</a> documentation. -spec primitiveRestartIndex(Index) -> 'ok' when Index :: integer(). primitiveRestartIndex(Index) -> cast(5582, <<Index:?GLuint>>). @@ -12850,7 +5678,7 @@ getInteger64i_v(Target,Index) -> %% @doc glGetBufferParameteri64v %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferParameteri64v.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getBufferParameteri64v(Target, Pname) -> [integer()] when Target :: enum(),Pname :: enum(). getBufferParameteri64v(Target,Pname) -> call(5584, <<Target:?GLenum,Pname:?GLenum>>). @@ -12863,51 +5691,7 @@ getBufferParameteri64v(Target,Pname) -> %% `Target' must be `?GL_DRAW_FRAMEBUFFER', `?GL_READ_FRAMEBUFFER', or `?GL_FRAMEBUFFER' %% . `?GL_FRAMEBUFFER' is equivalent to `?GL_DRAW_FRAMEBUFFER'. %% -%% `Attachment' specifies the logical attachment of the framebuffer and must be `?GL_COLOR_ATTACHMENT' -%% `i', `?GL_DEPTH_ATTACHMENT', `?GL_STENCIL_ATTACHMENT' or `?GL_DEPTH_STENCIL_ATTACHMMENT' -%% . `i' in `?GL_COLOR_ATTACHMENT'`i' may range from zero to the value of `?GL_MAX_COLOR_ATTACHMENTS' -%% - 1. Attaching a level of a texture to `?GL_DEPTH_STENCIL_ATTACHMENT' is equivalent -%% to attaching that level to both the `?GL_DEPTH_ATTACHMENT'`and' the `?GL_STENCIL_ATTACHMENT' -%% attachment points simultaneously. -%% -%% `Textarget' specifies what type of texture is named by `Texture' , and for cube -%% map textures, specifies the face that is to be attached. If `Texture' is not zero, -%% it must be the name of an existing texture with type `Textarget' , unless it is a -%% cube map texture, in which case `Textarget' must be `?GL_TEXTURE_CUBE_MAP_POSITIVE_X' -%% `?GL_TEXTURE_CUBE_MAP_NEGATIVE_X', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Y', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Y' -%% , `?GL_TEXTURE_CUBE_MAP_POSITIVE_Z', or `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Z'. -%% -%% If `Texture' is non-zero, the specified `Level' of the texture object named `Texture' -%% is attached to the framebfufer attachment point named by `Attachment' . For ``gl:framebufferTexture1D'' -%% , ``gl:framebufferTexture2D'', and ``gl:framebufferTexture3D'', `Texture' must -%% be zero or the name of an existing texture with a target of `Textarget' , or `Texture' -%% must be the name of an existing cube-map texture and `Textarget' must be one of `?GL_TEXTURE_CUBE_MAP_POSITIVE_X' -%% , `?GL_TEXTURE_CUBE_MAP_POSITIVE_Y', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Z', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_X' -%% , `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Y', or `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Z'. -%% -%% If `Textarget' is `?GL_TEXTURE_RECTANGLE', `?GL_TEXTURE_2D_MULTISAMPLE', -%% or `?GL_TEXTURE_2D_MULTISAMPLE_ARRAY', then `Level' must be zero. If `Textarget' -%% is `?GL_TEXTURE_3D', then level must be greater than or equal to zero and less than -%% or equal to log2 of the value of `?GL_MAX_3D_TEXTURE_SIZE'. If `Textarget' is -%% one of `?GL_TEXTURE_CUBE_MAP_POSITIVE_X', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Y', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Z' -%% , `?GL_TEXTURE_CUBE_MAP_NEGATIVE_X', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Y', or `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Z' -%% , then `Level' must be greater than or equal to zero and less than or equal to log2 -%% of the value of `?GL_MAX_CUBE_MAP_TEXTURE_SIZE'. For all other values of `Textarget' -%% , `Level' must be greater than or equal to zero and no larger than log2 of the value -%% of `?GL_MAX_TEXTURE_SIZE'. -%% -%% `Layer' specifies the layer of a 2-dimensional image within a 3-dimensional texture. -%% -%% -%% For ``gl:framebufferTexture1D'', if `Texture' is not zero, then `Textarget' -%% must be `?GL_TEXTURE_1D'. For ``gl:framebufferTexture2D'', if `Texture' is -%% not zero, `Textarget' must be one of `?GL_TEXTURE_2D', `?GL_TEXTURE_RECTANGLE' -%% , `?GL_TEXTURE_CUBE_MAP_POSITIVE_X', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Y', `?GL_TEXTURE_CUBE_MAP_POSITIVE_Z' -%% , `?GL_TEXTURE_CUBE_MAP_NEGATIVE_X', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Y', `?GL_TEXTURE_CUBE_MAP_NEGATIVE_Z' -%% , or `?GL_TEXTURE_2D_MULTISAMPLE'. For ``gl:framebufferTexture3D'', if `Texture' -%% is not zero, then `Textarget' must be `?GL_TEXTURE_3D'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFramebufferTexture.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glFramebufferTexture.xhtml">external</a> documentation. -spec framebufferTexture(Target, Attachment, Texture, Level) -> 'ok' when Target :: enum(),Attachment :: enum(),Texture :: integer(),Level :: integer(). framebufferTexture(Target,Attachment,Texture,Level) -> cast(5585, <<Target:?GLenum,Attachment:?GLenum,Texture:?GLuint,Level:?GLint>>). @@ -12921,9 +5705,7 @@ framebufferTexture(Target,Attachment,Texture,Level) -> %% vertices being rendered. An attribute is referred to as instanced if its `?GL_VERTEX_ATTRIB_ARRAY_DIVISOR' %% value is non-zero. %% -%% `Index' must be less than the value of `?GL_MAX_VERTEX_ATTRIBUTES'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribDivisor.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glVertexAttribDivisor.xhtml">external</a> documentation. -spec vertexAttribDivisor(Index, Divisor) -> 'ok' when Index :: integer(),Divisor :: integer(). vertexAttribDivisor(Index,Divisor) -> cast(5586, <<Index:?GLuint,Divisor:?GLuint>>). @@ -12938,13 +5720,7 @@ vertexAttribDivisor(Index,Divisor) -> %% is the value of `?GL_SAMPLES' for the current framebuffer. At least 1 sample for %% each covered fragment is generated. %% -%% A `Value' of 1.0 indicates that each sample in the framebuffer should be indpendently -%% shaded. A `Value' of 0.0 effectively allows the GL to ignore sample rate shading. -%% Any value between 0.0 and 1.0 allows the GL to shade only a subset of the total samples -%% within each covered fragment. Which samples are shaded and the algorithm used to select -%% that subset of the fragment's samples is implementation dependent. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMinSampleShading.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMinSampleShading.xhtml">external</a> documentation. -spec minSampleShading(Value) -> 'ok' when Value :: clamp(). minSampleShading(Value) -> cast(5587, <<Value:?GLclampf>>). @@ -12963,7 +5739,7 @@ blendEquationSeparatei(Buf,ModeRGB,ModeAlpha) -> %% @doc glBlendFunci %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlendFunci.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec blendFunci(Buf, Src, Dst) -> 'ok' when Buf :: integer(),Src :: enum(),Dst :: enum(). blendFunci(Buf,Src,Dst) -> cast(5590, <<Buf:?GLuint,Src:?GLenum,Dst:?GLenum>>). @@ -12976,7 +5752,7 @@ blendFuncSeparatei(Buf,SrcRGB,DstRGB,SrcAlpha,DstAlpha) -> %% @doc glLoadTransposeMatrixARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadTransposeMatrixARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec loadTransposeMatrixfARB(M) -> 'ok' when M :: matrix(). loadTransposeMatrixfARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) -> cast(5592, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,M13:?GLfloat,M14:?GLfloat,M15:?GLfloat,M16:?GLfloat>>); @@ -12985,7 +5761,7 @@ loadTransposeMatrixfARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) -> %% @doc glLoadTransposeMatrixARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLoadTransposeMatrixARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec loadTransposeMatrixdARB(M) -> 'ok' when M :: matrix(). loadTransposeMatrixdARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) -> cast(5593, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble>>); @@ -12994,7 +5770,7 @@ loadTransposeMatrixdARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) -> %% @doc glMultTransposeMatrixARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultTransposeMatrixARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec multTransposeMatrixfARB(M) -> 'ok' when M :: matrix(). multTransposeMatrixfARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) -> cast(5594, <<M1:?GLfloat,M2:?GLfloat,M3:?GLfloat,M4:?GLfloat,M5:?GLfloat,M6:?GLfloat,M7:?GLfloat,M8:?GLfloat,M9:?GLfloat,M10:?GLfloat,M11:?GLfloat,M12:?GLfloat,M13:?GLfloat,M14:?GLfloat,M15:?GLfloat,M16:?GLfloat>>); @@ -13003,7 +5779,7 @@ multTransposeMatrixfARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) -> %% @doc glMultTransposeMatrixARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMultTransposeMatrixARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec multTransposeMatrixdARB(M) -> 'ok' when M :: matrix(). multTransposeMatrixdARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16}) -> cast(5595, <<M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble>>); @@ -13012,7 +5788,7 @@ multTransposeMatrixdARB({M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12}) -> %% @doc glWeightARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec weightbvARB(Weights) -> 'ok' when Weights :: [integer()]. weightbvARB(Weights) -> WeightsLen = length(Weights), @@ -13021,7 +5797,7 @@ weightbvARB(Weights) -> %% @doc glWeightARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec weightsvARB(Weights) -> 'ok' when Weights :: [integer()]. weightsvARB(Weights) -> WeightsLen = length(Weights), @@ -13030,7 +5806,7 @@ weightsvARB(Weights) -> %% @doc glWeightARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec weightivARB(Weights) -> 'ok' when Weights :: [integer()]. weightivARB(Weights) -> WeightsLen = length(Weights), @@ -13039,7 +5815,7 @@ weightivARB(Weights) -> %% @doc glWeightARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec weightfvARB(Weights) -> 'ok' when Weights :: [float()]. weightfvARB(Weights) -> WeightsLen = length(Weights), @@ -13048,7 +5824,7 @@ weightfvARB(Weights) -> %% @doc glWeightARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec weightdvARB(Weights) -> 'ok' when Weights :: [float()]. weightdvARB(Weights) -> WeightsLen = length(Weights), @@ -13057,7 +5833,7 @@ weightdvARB(Weights) -> %% @doc glWeightARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec weightubvARB(Weights) -> 'ok' when Weights :: [integer()]. weightubvARB(Weights) -> WeightsLen = length(Weights), @@ -13066,7 +5842,7 @@ weightubvARB(Weights) -> %% @doc glWeightARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec weightusvARB(Weights) -> 'ok' when Weights :: [integer()]. weightusvARB(Weights) -> WeightsLen = length(Weights), @@ -13075,7 +5851,7 @@ weightusvARB(Weights) -> %% @doc glWeightARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWeightARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec weightuivARB(Weights) -> 'ok' when Weights :: [integer()]. weightuivARB(Weights) -> WeightsLen = length(Weights), @@ -13084,21 +5860,21 @@ weightuivARB(Weights) -> %% @doc glVertexBlenARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexBlenARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec vertexBlendARB(Count) -> 'ok' when Count :: integer(). vertexBlendARB(Count) -> cast(5604, <<Count:?GLint>>). %% @doc glCurrentPaletteMatrixARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCurrentPaletteMatrixARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec currentPaletteMatrixARB(Index) -> 'ok' when Index :: integer(). currentPaletteMatrixARB(Index) -> cast(5605, <<Index:?GLint>>). %% @doc glMatrixIndexARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMatrixIndexARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec matrixIndexubvARB(Indices) -> 'ok' when Indices :: [integer()]. matrixIndexubvARB(Indices) -> IndicesLen = length(Indices), @@ -13107,7 +5883,7 @@ matrixIndexubvARB(Indices) -> %% @doc glMatrixIndexARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMatrixIndexARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec matrixIndexusvARB(Indices) -> 'ok' when Indices :: [integer()]. matrixIndexusvARB(Indices) -> IndicesLen = length(Indices), @@ -13116,7 +5892,7 @@ matrixIndexusvARB(Indices) -> %% @doc glMatrixIndexARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMatrixIndexARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec matrixIndexuivARB(Indices) -> 'ok' when Indices :: [integer()]. matrixIndexuivARB(Indices) -> IndicesLen = length(Indices), @@ -13125,7 +5901,7 @@ matrixIndexuivARB(Indices) -> %% @doc glProgramStringARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramStringARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec programStringARB(Target, Format, String) -> 'ok' when Target :: enum(),Format :: enum(),String :: string(). programStringARB(Target,Format,String) -> StringLen = length(String), @@ -13133,14 +5909,14 @@ programStringARB(Target,Format,String) -> %% @doc glBindProgramARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindProgramARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec bindProgramARB(Target, Program) -> 'ok' when Target :: enum(),Program :: integer(). bindProgramARB(Target,Program) -> cast(5610, <<Target:?GLenum,Program:?GLuint>>). %% @doc glDeleteProgramsARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteProgramsARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec deleteProgramsARB(Programs) -> 'ok' when Programs :: [integer()]. deleteProgramsARB(Programs) -> ProgramsLen = length(Programs), @@ -13149,98 +5925,98 @@ deleteProgramsARB(Programs) -> %% @doc glGenProgramsARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenProgramsARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec genProgramsARB(N) -> [integer()] when N :: integer(). genProgramsARB(N) -> call(5612, <<N:?GLsizei>>). %% @doc glProgramEnvParameterARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramEnvParameterARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec programEnvParameter4dARB(Target, Index, X, Y, Z, W) -> 'ok' when Target :: enum(),Index :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float(). programEnvParameter4dARB(Target,Index,X,Y,Z,W) -> cast(5613, <<Target:?GLenum,Index:?GLuint,X:?GLdouble,Y:?GLdouble,Z:?GLdouble,W:?GLdouble>>). %% @doc glProgramEnvParameterARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramEnvParameterARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec programEnvParameter4dvARB(Target, Index, Params) -> 'ok' when Target :: enum(),Index :: integer(),Params :: {float(),float(),float(),float()}. programEnvParameter4dvARB(Target,Index,{P1,P2,P3,P4}) -> cast(5614, <<Target:?GLenum,Index:?GLuint,P1:?GLdouble,P2:?GLdouble,P3:?GLdouble,P4:?GLdouble>>). %% @doc glProgramEnvParameterARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramEnvParameterARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec programEnvParameter4fARB(Target, Index, X, Y, Z, W) -> 'ok' when Target :: enum(),Index :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float(). programEnvParameter4fARB(Target,Index,X,Y,Z,W) -> cast(5615, <<Target:?GLenum,Index:?GLuint,X:?GLfloat,Y:?GLfloat,Z:?GLfloat,W:?GLfloat>>). %% @doc glProgramEnvParameterARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramEnvParameterARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec programEnvParameter4fvARB(Target, Index, Params) -> 'ok' when Target :: enum(),Index :: integer(),Params :: {float(),float(),float(),float()}. programEnvParameter4fvARB(Target,Index,{P1,P2,P3,P4}) -> cast(5616, <<Target:?GLenum,Index:?GLuint,P1:?GLfloat,P2:?GLfloat,P3:?GLfloat,P4:?GLfloat>>). %% @doc glProgramLocalParameterARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramLocalParameterARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec programLocalParameter4dARB(Target, Index, X, Y, Z, W) -> 'ok' when Target :: enum(),Index :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float(). programLocalParameter4dARB(Target,Index,X,Y,Z,W) -> cast(5617, <<Target:?GLenum,Index:?GLuint,X:?GLdouble,Y:?GLdouble,Z:?GLdouble,W:?GLdouble>>). %% @doc glProgramLocalParameterARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramLocalParameterARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec programLocalParameter4dvARB(Target, Index, Params) -> 'ok' when Target :: enum(),Index :: integer(),Params :: {float(),float(),float(),float()}. programLocalParameter4dvARB(Target,Index,{P1,P2,P3,P4}) -> cast(5618, <<Target:?GLenum,Index:?GLuint,P1:?GLdouble,P2:?GLdouble,P3:?GLdouble,P4:?GLdouble>>). %% @doc glProgramLocalParameterARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramLocalParameterARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec programLocalParameter4fARB(Target, Index, X, Y, Z, W) -> 'ok' when Target :: enum(),Index :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float(). programLocalParameter4fARB(Target,Index,X,Y,Z,W) -> cast(5619, <<Target:?GLenum,Index:?GLuint,X:?GLfloat,Y:?GLfloat,Z:?GLfloat,W:?GLfloat>>). %% @doc glProgramLocalParameterARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramLocalParameterARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec programLocalParameter4fvARB(Target, Index, Params) -> 'ok' when Target :: enum(),Index :: integer(),Params :: {float(),float(),float(),float()}. programLocalParameter4fvARB(Target,Index,{P1,P2,P3,P4}) -> cast(5620, <<Target:?GLenum,Index:?GLuint,P1:?GLfloat,P2:?GLfloat,P3:?GLfloat,P4:?GLfloat>>). %% @doc glGetProgramEnvParameterARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramEnvParameterARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getProgramEnvParameterdvARB(Target, Index) -> {float(),float(),float(),float()} when Target :: enum(),Index :: integer(). getProgramEnvParameterdvARB(Target,Index) -> call(5621, <<Target:?GLenum,Index:?GLuint>>). %% @doc glGetProgramEnvParameterARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramEnvParameterARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getProgramEnvParameterfvARB(Target, Index) -> {float(),float(),float(),float()} when Target :: enum(),Index :: integer(). getProgramEnvParameterfvARB(Target,Index) -> call(5622, <<Target:?GLenum,Index:?GLuint>>). %% @doc glGetProgramLocalParameterARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramLocalParameterARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getProgramLocalParameterdvARB(Target, Index) -> {float(),float(),float(),float()} when Target :: enum(),Index :: integer(). getProgramLocalParameterdvARB(Target,Index) -> call(5623, <<Target:?GLenum,Index:?GLuint>>). %% @doc glGetProgramLocalParameterARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramLocalParameterARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getProgramLocalParameterfvARB(Target, Index) -> {float(),float(),float(),float()} when Target :: enum(),Index :: integer(). getProgramLocalParameterfvARB(Target,Index) -> call(5624, <<Target:?GLenum,Index:?GLuint>>). %% @doc glGetProgramStringARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramStringARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getProgramStringARB(Target, Pname, String) -> 'ok' when Target :: enum(),Pname :: enum(),String :: mem(). getProgramStringARB(Target,Pname,String) -> send_bin(String), @@ -13248,42 +6024,42 @@ getProgramStringARB(Target,Pname,String) -> %% @doc glGetBufferParameterARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetBufferParameterARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getBufferParameterivARB(Target, Pname) -> [integer()] when Target :: enum(),Pname :: enum(). getBufferParameterivARB(Target,Pname) -> call(5626, <<Target:?GLenum,Pname:?GLenum>>). %% @doc glDeleteObjectARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteObjectARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec deleteObjectARB(Obj) -> 'ok' when Obj :: integer(). deleteObjectARB(Obj) -> cast(5627, <<Obj:?GLhandleARB>>). %% @doc glGetHandleARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetHandleARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getHandleARB(Pname) -> integer() when Pname :: enum(). getHandleARB(Pname) -> call(5628, <<Pname:?GLenum>>). %% @doc glDetachObjectARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDetachObjectARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec detachObjectARB(ContainerObj, AttachedObj) -> 'ok' when ContainerObj :: integer(),AttachedObj :: integer(). detachObjectARB(ContainerObj,AttachedObj) -> cast(5629, <<ContainerObj:?GLhandleARB,AttachedObj:?GLhandleARB>>). %% @doc glCreateShaderObjectARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateShaderObjectARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec createShaderObjectARB(ShaderType) -> integer() when ShaderType :: enum(). createShaderObjectARB(ShaderType) -> call(5630, <<ShaderType:?GLenum>>). %% @doc glShaderSourceARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShaderSourceARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec shaderSourceARB(ShaderObj, String) -> 'ok' when ShaderObj :: integer(),String :: iolist(). shaderSourceARB(ShaderObj,String) -> StringTemp = list_to_binary([[Str|[0]] || Str <- String ]), @@ -13292,77 +6068,77 @@ shaderSourceARB(ShaderObj,String) -> %% @doc glCompileShaderARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompileShaderARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec compileShaderARB(ShaderObj) -> 'ok' when ShaderObj :: integer(). compileShaderARB(ShaderObj) -> cast(5632, <<ShaderObj:?GLhandleARB>>). %% @doc glCreateProgramObjectARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateProgramObjectARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec createProgramObjectARB() -> integer(). createProgramObjectARB() -> call(5633, <<>>). %% @doc glAttachObjectARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glAttachObjectARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec attachObjectARB(ContainerObj, Obj) -> 'ok' when ContainerObj :: integer(),Obj :: integer(). attachObjectARB(ContainerObj,Obj) -> cast(5634, <<ContainerObj:?GLhandleARB,Obj:?GLhandleARB>>). %% @doc glLinkProgramARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glLinkProgramARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec linkProgramARB(ProgramObj) -> 'ok' when ProgramObj :: integer(). linkProgramARB(ProgramObj) -> cast(5635, <<ProgramObj:?GLhandleARB>>). %% @doc glUseProgramObjectARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUseProgramObjectARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec useProgramObjectARB(ProgramObj) -> 'ok' when ProgramObj :: integer(). useProgramObjectARB(ProgramObj) -> cast(5636, <<ProgramObj:?GLhandleARB>>). %% @doc glValidateProgramARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgramARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec validateProgramARB(ProgramObj) -> 'ok' when ProgramObj :: integer(). validateProgramARB(ProgramObj) -> cast(5637, <<ProgramObj:?GLhandleARB>>). %% @doc glGetObjectParameterARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetObjectParameterARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getObjectParameterfvARB(Obj, Pname) -> float() when Obj :: integer(),Pname :: enum(). getObjectParameterfvARB(Obj,Pname) -> call(5638, <<Obj:?GLhandleARB,Pname:?GLenum>>). %% @doc glGetObjectParameterARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetObjectParameterARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getObjectParameterivARB(Obj, Pname) -> integer() when Obj :: integer(),Pname :: enum(). getObjectParameterivARB(Obj,Pname) -> call(5639, <<Obj:?GLhandleARB,Pname:?GLenum>>). %% @doc glGetInfoLogARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetInfoLogARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getInfoLogARB(Obj, MaxLength) -> string() when Obj :: integer(),MaxLength :: integer(). getInfoLogARB(Obj,MaxLength) -> call(5640, <<Obj:?GLhandleARB,MaxLength:?GLsizei>>). %% @doc glGetAttachedObjectsARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetAttachedObjectsARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getAttachedObjectsARB(ContainerObj, MaxCount) -> [integer()] when ContainerObj :: integer(),MaxCount :: integer(). getAttachedObjectsARB(ContainerObj,MaxCount) -> call(5641, <<ContainerObj:?GLhandleARB,MaxCount:?GLsizei>>). %% @doc glGetUniformLocationARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformLocationARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getUniformLocationARB(ProgramObj, Name) -> integer() when ProgramObj :: integer(),Name :: string(). getUniformLocationARB(ProgramObj,Name) -> NameLen = length(Name), @@ -13370,35 +6146,35 @@ getUniformLocationARB(ProgramObj,Name) -> %% @doc glGetActiveUniformARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniformARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getActiveUniformARB(ProgramObj, Index, MaxLength) -> {Size :: integer(),Type :: enum(),Name :: string()} when ProgramObj :: integer(),Index :: integer(),MaxLength :: integer(). getActiveUniformARB(ProgramObj,Index,MaxLength) -> call(5643, <<ProgramObj:?GLhandleARB,Index:?GLuint,MaxLength:?GLsizei>>). %% @doc glGetUniformARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getUniformfvARB(ProgramObj, Location) -> matrix() when ProgramObj :: integer(),Location :: integer(). getUniformfvARB(ProgramObj,Location) -> call(5644, <<ProgramObj:?GLhandleARB,Location:?GLint>>). %% @doc glGetUniformARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getUniformivARB(ProgramObj, Location) -> {integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer()} when ProgramObj :: integer(),Location :: integer(). getUniformivARB(ProgramObj,Location) -> call(5645, <<ProgramObj:?GLhandleARB,Location:?GLint>>). %% @doc glGetShaderSourceARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderSourceARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getShaderSourceARB(Obj, MaxLength) -> string() when Obj :: integer(),MaxLength :: integer(). getShaderSourceARB(Obj,MaxLength) -> call(5646, <<Obj:?GLhandleARB,MaxLength:?GLsizei>>). %% @doc glBindAttribLocationARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindAttribLocationARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec bindAttribLocationARB(ProgramObj, Index, Name) -> 'ok' when ProgramObj :: integer(),Index :: integer(),Name :: string(). bindAttribLocationARB(ProgramObj,Index,Name) -> NameLen = length(Name), @@ -13406,14 +6182,14 @@ bindAttribLocationARB(ProgramObj,Index,Name) -> %% @doc glGetActiveAttribARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveAttribARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getActiveAttribARB(ProgramObj, Index, MaxLength) -> {Size :: integer(),Type :: enum(),Name :: string()} when ProgramObj :: integer(),Index :: integer(),MaxLength :: integer(). getActiveAttribARB(ProgramObj,Index,MaxLength) -> call(5648, <<ProgramObj:?GLhandleARB,Index:?GLuint,MaxLength:?GLsizei>>). %% @doc glGetAttribLocationARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetAttribLocationARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getAttribLocationARB(ProgramObj, Name) -> integer() when ProgramObj :: integer(),Name :: string(). getAttribLocationARB(ProgramObj,Name) -> NameLen = length(Name), @@ -13429,7 +6205,7 @@ getAttribLocationARB(ProgramObj,Name) -> %% , then the name is not a renderbuffer object and ``gl:isRenderbuffer'' returns `?GL_FALSE' %% . %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsRenderbuffer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsRenderbuffer.xhtml">external</a> documentation. -spec isRenderbuffer(Renderbuffer) -> 0|1 when Renderbuffer :: integer(). isRenderbuffer(Renderbuffer) -> call(5650, <<Renderbuffer:?GLuint>>). @@ -13442,7 +6218,7 @@ isRenderbuffer(Renderbuffer) -> %% call to {@link gl:genRenderbuffers/1} , or zero to break the existing binding of a renderbuffer %% object to `Target' . %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindRenderbuffer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindRenderbuffer.xhtml">external</a> documentation. -spec bindRenderbuffer(Target, Renderbuffer) -> 'ok' when Target :: enum(),Renderbuffer :: integer(). bindRenderbuffer(Target,Renderbuffer) -> cast(5651, <<Target:?GLenum,Renderbuffer:?GLuint>>). @@ -13457,14 +6233,7 @@ bindRenderbuffer(Target,Renderbuffer) -> %% it is as though {@link gl:bindRenderbuffer/2} had been executed with a `Target' of `?GL_RENDERBUFFER' %% and a `Name' of zero. %% -%% If a renderbuffer object is attached to one or more attachment points in the currently -%% bound framebuffer, then it as if {@link gl:framebufferRenderbuffer/4} had been called, -%% with a `Renderbuffer' of zero for each attachment point to which this image was attached -%% in the currently bound framebuffer. In other words, this renderbuffer object is first -%% detached from all attachment ponits in the currently bound framebuffer. Note that the -%% renderbuffer image is specifically `not' detached from any non-bound framebuffers. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteRenderbuffers.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteRenderbuffers.xhtml">external</a> documentation. -spec deleteRenderbuffers(Renderbuffers) -> 'ok' when Renderbuffers :: [integer()]. deleteRenderbuffers(Renderbuffers) -> RenderbuffersLen = length(Renderbuffers), @@ -13478,13 +6247,7 @@ deleteRenderbuffers(Renderbuffers) -> %% is guaranteed that none of the returned names was in use immediately before the call to ``gl:genRenderbuffers'' %% . %% -%% Renderbuffer object names returned by a call to ``gl:genRenderbuffers'' are not returned -%% by subsequent calls, unless they are first deleted with {@link gl:deleteRenderbuffers/1} . -%% -%% The names returned in `Renderbuffers' are marked as used, for the purposes of ``gl:genRenderbuffers'' -%% only, but they acquire state and type only when they are first bound. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenRenderbuffers.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenRenderbuffers.xhtml">external</a> documentation. -spec genRenderbuffers(N) -> [integer()] when N :: integer(). genRenderbuffers(N) -> call(5653, <<N:?GLsizei>>). @@ -13494,18 +6257,7 @@ genRenderbuffers(N) -> %% ``gl:renderbufferStorage'' is equivalent to calling {@link gl:renderbufferStorageMultisample/5} %% with the `Samples' set to zero. %% -%% The target of the operation, specified by `Target' must be `?GL_RENDERBUFFER'. -%% `Internalformat' specifies the internal format to be used for the renderbuffer object's -%% storage and must be a color-renderable, depth-renderable, or stencil-renderable format. `Width' -%% and `Height' are the dimensions, in pixels, of the renderbuffer. Both `Width' -%% and `Height' must be less than or equal to the value of `?GL_MAX_RENDERBUFFER_SIZE' -%% . -%% -%% Upon success, ``gl:renderbufferStorage'' deletes any existing data store for the renderbuffer -%% image and the contents of the data store after calling ``gl:renderbufferStorage'' are -%% undefined. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRenderbufferStorage.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glRenderbufferStorage.xhtml">external</a> documentation. -spec renderbufferStorage(Target, Internalformat, Width, Height) -> 'ok' when Target :: enum(),Internalformat :: enum(),Width :: integer(),Height :: integer(). renderbufferStorage(Target,Internalformat,Width,Height) -> cast(5654, <<Target:?GLenum,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei>>). @@ -13520,20 +6272,7 @@ renderbufferStorage(Target,Internalformat,Width,Height) -> %% , `?GL_RENDERBUFFER_DEPTH_SIZE', `?GL_RENDERBUFFER_DEPTH_SIZE', `?GL_RENDERBUFFER_STENCIL_SIZE' %% , or `?GL_RENDERBUFFER_SAMPLES'. %% -%% Upon a successful return from ``gl:getRenderbufferParameteriv'', if `Pname' is `?GL_RENDERBUFFER_WIDTH' -%% , `?GL_RENDERBUFFER_HEIGHT', `?GL_RENDERBUFFER_INTERNAL_FORMAT', or `?GL_RENDERBUFFER_SAMPLES' -%% , then `Params' will contain the width in pixels, the height in pixels, the internal -%% format, or the number of samples, respectively, of the image of the renderbuffer currently -%% bound to `Target' . -%% -%% If `Pname' is `?GL_RENDERBUFFER_RED_SIZE', `?GL_RENDERBUFFER_GREEN_SIZE', -%% `?GL_RENDERBUFFER_BLUE_SIZE', `?GL_RENDERBUFFER_ALPHA_SIZE', `?GL_RENDERBUFFER_DEPTH_SIZE' -%% , or `?GL_RENDERBUFFER_STENCIL_SIZE', then `Params' will contain the actual -%% resolutions (not the resolutions specified when the image array was defined) for the red, -%% green, blue, alpha depth, or stencil components, respectively, of the image of the renderbuffer -%% currently bound to `Target' . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetRenderbufferParameter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetRenderbufferParameter.xhtml">external</a> documentation. -spec getRenderbufferParameteriv(Target, Pname) -> integer() when Target :: enum(),Pname :: enum(). getRenderbufferParameteriv(Target,Pname) -> call(5655, <<Target:?GLenum,Pname:?GLenum>>). @@ -13547,7 +6286,7 @@ getRenderbufferParameteriv(Target,Pname) -> %% , by that has not yet been bound through a call to {@link gl:bindFramebuffer/2} , then the %% name is not a framebuffer object and ``gl:isFramebuffer'' returns `?GL_FALSE'. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsFramebuffer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsFramebuffer.xhtml">external</a> documentation. -spec isFramebuffer(Framebuffer) -> 0|1 when Framebuffer :: integer(). isFramebuffer(Framebuffer) -> call(5656, <<Framebuffer:?GLuint>>). @@ -13565,7 +6304,7 @@ isFramebuffer(Framebuffer) -> %% a call to {@link gl:genFramebuffers/1} , or zero to break the existing binding of a framebuffer %% object to `Target' . %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindFramebuffer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindFramebuffer.xhtml">external</a> documentation. -spec bindFramebuffer(Target, Framebuffer) -> 'ok' when Target :: enum(),Framebuffer :: integer(). bindFramebuffer(Target,Framebuffer) -> cast(5657, <<Target:?GLenum,Framebuffer:?GLuint>>). @@ -13580,7 +6319,7 @@ bindFramebuffer(Target,Framebuffer) -> %% or `?GL_READ_FRAMEBUFFER' is deleted, it is as though {@link gl:bindFramebuffer/2} %% had been executed with the corresponding `Target' and `Framebuffer' zero. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteFramebuffers.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteFramebuffers.xhtml">external</a> documentation. -spec deleteFramebuffers(Framebuffers) -> 'ok' when Framebuffers :: [integer()]. deleteFramebuffers(Framebuffers) -> FramebuffersLen = length(Framebuffers), @@ -13594,13 +6333,7 @@ deleteFramebuffers(Framebuffers) -> %% that none of the returned names was in use immediately before the call to ``gl:genFramebuffers'' %% . %% -%% Framebuffer object names returned by a call to ``gl:genFramebuffers'' are not returned -%% by subsequent calls, unless they are first deleted with {@link gl:deleteFramebuffers/1} . -%% -%% The names returned in `Ids' are marked as used, for the purposes of ``gl:genFramebuffers'' -%% only, but they acquire state and type only when they are first bound. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenFramebuffers.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenFramebuffers.xhtml">external</a> documentation. -spec genFramebuffers(N) -> [integer()] when N :: integer(). genFramebuffers(N) -> call(5659, <<N:?GLsizei>>). @@ -13612,46 +6345,7 @@ genFramebuffers(N) -> %% or `?GL_FRAMEBUFFER'. `?GL_FRAMEBUFFER' is equivalent to `?GL_DRAW_FRAMEBUFFER' %% . %% -%% The return value is `?GL_FRAMEBUFFER_COMPLETE' if the framebuffer bound to `Target' -%% is complete. Otherwise, the return value is determined as follows: -%% -%% `?GL_FRAMEBUFFER_UNDEFINED' is returned if `Target' is the default framebuffer, -%% but the default framebuffer does not exist. -%% -%% `?GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT' is returned if any of the framebuffer attachment -%% points are framebuffer incomplete. -%% -%% `?GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT' is returned if the framebuffer does -%% not have at least one image attached to it. -%% -%% `?GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER' is returned if the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' -%% is `?GL_NONE' for any color attachment point(s) named by `?GL_DRAWBUFFERi'. -%% -%% `?GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER' is returned if `?GL_READ_BUFFER' is -%% not `?GL_NONE' and the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' is `?GL_NONE' -%% for the color attachment point named by `?GL_READ_BUFFER'. -%% -%% `?GL_FRAMEBUFFER_UNSUPPORTED' is returned if the combination of internal formats -%% of the attached images violates an implementation-dependent set of restrictions. -%% -%% `?GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE' is returned if the value of `?GL_RENDERBUFFER_SAMPLES' -%% is not the same for all attached renderbuffers; if the value of `?GL_TEXTURE_SAMPLES' -%% is the not same for all attached textures; or, if the attached images are a mix of renderbuffers -%% and textures, the value of `?GL_RENDERBUFFER_SAMPLES' does not match the value of `?GL_TEXTURE_SAMPLES' -%% . -%% -%% `?GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE' is also returned if the value of `?GL_TEXTURE_FIXED_SAMPLE_LOCATIONS' -%% is not the same for all attached textures; or, if the attached images are a mix of renderbuffers -%% and textures, the value of `?GL_TEXTURE_FIXED_SAMPLE_LOCATIONS' is not `?GL_TRUE' -%% for all attached textures. -%% -%% `?GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS' is returned if any framebuffer attachment -%% is layered, and any populated attachment is not layered, or if all populated color attachments -%% are not from textures of the same target. -%% -%% Additionally, if an error occurs, zero is returned. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCheckFramebufferStatus.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCheckFramebufferStatus.xhtml">external</a> documentation. -spec checkFramebufferStatus(Target) -> enum() when Target :: enum(). checkFramebufferStatus(Target) -> call(5660, <<Target:?GLenum>>). @@ -13684,24 +6378,7 @@ framebufferTexture3D(Target,Attachment,Textarget,Texture,Level,Zoffset) -> %% buffer identified by `Attachment' of the framebuffer currently bound to `Target' . %% %% -%% The value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' for the specified attachment -%% point is set to `?GL_RENDERBUFFER' and the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME' -%% is set to `Renderbuffer' . All other state values of the attachment point specified -%% by `Attachment' are set to their default values. No change is made to the state of -%% the renderbuuffer object and any previous attachment to the `Attachment' logical -%% buffer of the framebuffer `Target' is broken. -%% -%% Calling ``gl:framebufferRenderbuffer'' with the renderbuffer name zero will detach -%% the image, if any, identified by `Attachment' , in the framebuffer currently bound -%% to `Target' . All state values of the attachment point specified by attachment in -%% the object bound to target are set to their default values. -%% -%% Setting `Attachment' to the value `?GL_DEPTH_STENCIL_ATTACHMENT' is a special -%% case causing both the depth and stencil attachments of the framebuffer object to be set -%% to `Renderbuffer' , which should have the base internal format `?GL_DEPTH_STENCIL' -%% . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFramebufferRenderbuffer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glFramebufferRenderbuffer.xhtml">external</a> documentation. -spec framebufferRenderbuffer(Target, Attachment, Renderbuffertarget, Renderbuffer) -> 'ok' when Target :: enum(),Attachment :: enum(),Renderbuffertarget :: enum(),Renderbuffer :: integer(). framebufferRenderbuffer(Target,Attachment,Renderbuffertarget,Renderbuffer) -> cast(5664, <<Target:?GLenum,Attachment:?GLenum,Renderbuffertarget:?GLenum,Renderbuffer:?GLuint>>). @@ -13713,91 +6390,7 @@ framebufferRenderbuffer(Target,Attachment,Renderbuffertarget,Renderbuffer) -> %% be `?GL_DRAW_FRAMEBUFFER', `?GL_READ_FRAMEBUFFER' or `?GL_FRAMEBUFFER'. `?GL_FRAMEBUFFER' %% is equivalent to `?GL_DRAW_FRAMEBUFFER'. %% -%% If the default framebuffer is bound to `Target' then `Attachment' must be one -%% of `?GL_FRONT_LEFT', `?GL_FRONT_RIGHT', `?GL_BACK_LEFT', or `?GL_BACK_RIGHT' -%% , identifying a color buffer, `?GL_DEPTH', identifying the depth buffer, or `?GL_STENCIL' -%% , identifying the stencil buffer. -%% -%% If a framebuffer object is bound, then `Attachment' must be one of `?GL_COLOR_ATTACHMENT' -%% `i', `?GL_DEPTH_ATTACHMENT', `?GL_STENCIL_ATTACHMENT', or `?GL_DEPTH_STENCIL_ATTACHMENT' -%% . `i' in `?GL_COLOR_ATTACHMENT'`i' must be in the range zero to the value -%% of `?GL_MAX_COLOR_ATTACHMENTS' - 1. -%% -%% If `Attachment' is `?GL_DEPTH_STENCIL_ATTACHMENT' and different objects are -%% bound to the depth and stencil attachment points of `Target' the query will fail. -%% If the same object is bound to both attachment points, information about that object will -%% be returned. -%% -%% Upon successful return from ``gl:getFramebufferAttachmentParameteriv'', if `Pname' -%% is `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE', then `Params' will contain one of `?GL_NONE' -%% , `?GL_FRAMEBUFFER_DEFAULT', `?GL_TEXTURE', or `?GL_RENDERBUFFER', identifying -%% the type of object which contains the attached image. Other values accepted for `Pname' -%% depend on the type of object, as described below. -%% -%% If the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' is `?GL_NONE', no -%% framebuffer is bound to `Target' . In this case querying `Pname' `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME' -%% will return zero, and all other queries will generate an error. -%% -%% If the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' is not `?GL_NONE', -%% these queries apply to all other framebuffer types: -%% -%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE', `?GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE' -%% , `?GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE', `?GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE' -%% , `?GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE', or `?GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE' -%% , then `Params' will contain the number of bits in the corresponding red, green, -%% blue, alpha, depth, or stencil component of the specified attachment. Zero is returned -%% if the requested component is not present in `Attachment' . -%% -%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE', `Params' will -%% contain the format of components of the specified attachment, one of `?GL_FLOAT', `GL_INT' -%% , `GL_UNSIGNED_INT' , `GL_SIGNED_NORMALIZED' , or `GL_UNSIGNED_NORMALIZED' -%% for floating-point, signed integer, unsigned integer, signed normalized fixed-point, or -%% unsigned normalized fixed-point components respectively. Only color buffers may have integer -%% components. -%% -%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING', `Param' will -%% contain the encoding of components of the specified attachment, one of `?GL_LINEAR' -%% or `?GL_SRGB' for linear or sRGB-encoded components, respectively. Only color buffer -%% components may be sRGB-encoded; such components are treated as described in sections 4.1.7 -%% and 4.1.8. For the default framebuffer, color encoding is determined by the implementation. -%% For framebuffer objects, components are sRGB-encoded if the internal format of a color -%% attachment is one of the color-renderable SRGB formats. -%% -%% If the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' is `?GL_RENDERBUFFER', -%% then: -%% -%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME', `Params' will -%% contain the name of the renderbuffer object which contains the attached image. -%% -%% If the value of `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE' is `?GL_TEXTURE', -%% then: -%% -%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME', then `Params' -%% will contain the name of the texture object which contains the attached image. -%% -%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL', then `Params' -%% will contain the mipmap level of the texture object which contains the attached image. -%% -%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE' and the texture -%% object named `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME' is a cube map texture, then `Params' -%% will contain the cube map face of the cubemap texture object which contains the attached -%% image. Otherwise `Params' will contain the value zero. -%% -%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER' and the texture object -%% named `?GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME' is a layer of a three-dimensional -%% texture or a one-or two-dimensional array texture, then `Params' will contain the -%% number of the texture layer which contains the attached image. Otherwise `Params' -%% will contain the value zero. -%% -%% If `Pname' is `?GL_FRAMEBUFFER_ATTACHMENT_LAYERED', then `Params' will -%% contain `?GL_TRUE' if an entire level of a three-dimesional texture, cube map texture, -%% or one-or two-dimensional array texture is attached. Otherwise, `Params' will contain -%% `?GL_FALSE'. -%% -%% Any combinations of framebuffer type and `Pname' not described above will generate -%% an error. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetFramebufferAttachmentParameter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetFramebufferAttachmentParameter.xhtml">external</a> documentation. -spec getFramebufferAttachmentParameteriv(Target, Attachment, Pname) -> integer() when Target :: enum(),Attachment :: enum(),Pname :: enum(). getFramebufferAttachmentParameteriv(Target,Attachment,Pname) -> call(5665, <<Target:?GLenum,Attachment:?GLenum,Pname:?GLenum>>). @@ -13808,16 +6401,7 @@ getFramebufferAttachmentParameteriv(Target,Attachment,Pname) -> %% the active texture unit. For cube map textures, a `?GL_INVALID_OPERATION' error is %% generated if the texture attached to `Target' is not cube complete. %% -%% Mipmap generation replaces texel array levels level base+1 through q with arrays derived -%% from the level base array, regardless of their previous contents. All other mimap arrays, -%% including the level base array, are left unchanged by this computation. -%% -%% The internal formats of the derived mipmap arrays all match those of the level base -%% array. The contents of the derived arrays are computed by repeated, filtered reduction -%% of the level base array. For one- and two-dimensional texture arrays, each layer is filtered -%% independently. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenerateMipmap.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenerateMipmap.xhtml">external</a> documentation. -spec generateMipmap(Target) -> 'ok' when Target :: enum(). generateMipmap(Target) -> cast(5666, <<Target:?GLenum>>). @@ -13833,33 +6417,7 @@ generateMipmap(Target) -> %% by the locations ( `DstX0' ; `DstY0' ) and ( `DstX1' ; `DstY1' ). The lower %% bounds of the rectangle are inclusive, while the upper bounds are exclusive. %% -%% The actual region taken from the read framebuffer is limited to the intersection of the -%% source buffers being transferred, which may include the color buffer selected by the read -%% buffer, the depth buffer, and/or the stencil buffer depending on mask. The actual region -%% written to the draw framebuffer is limited to the intersection of the destination buffers -%% being written, which may include multiple draw buffers, the depth buffer, and/or the stencil -%% buffer depending on mask. Whether or not the source or destination regions are altered -%% due to these limits, the scaling and offset applied to pixels being transferred is performed -%% as though no such limits were present. -%% -%% If the sizes of the source and destination rectangles are not equal, `Filter' specifies -%% the interpolation method that will be applied to resize the source image , and must be `?GL_NEAREST' -%% or `?GL_LINEAR'. `?GL_LINEAR' is only a valid interpolation method for the -%% color buffer. If `Filter' is not `?GL_NEAREST' and `Mask' includes `?GL_DEPTH_BUFFER_BIT' -%% or `?GL_STENCIL_BUFFER_BIT', no data is transferred and a `?GL_INVALID_OPERATION' -%% error is generated. -%% -%% If `Filter' is `?GL_LINEAR' and the source rectangle would require sampling -%% outside the bounds of the source framebuffer, values are read as if the `?GL_CLAMP_TO_EDGE' -%% texture wrapping mode were applied. -%% -%% When the color buffer is transferred, values are taken from the read buffer of the read -%% framebuffer and written to each of the draw buffers of the draw framebuffer. -%% -%% If the source and destination rectangles overlap or are the same, and the read and draw -%% buffers are the same, the result of the operation is undefined. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBlitFramebuffer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlitFramebuffer.xhtml">external</a> documentation. -spec blitFramebuffer(SrcX0, SrcY0, SrcX1, SrcY1, DstX0, DstY0, DstX1, DstY1, Mask, Filter) -> 'ok' when SrcX0 :: integer(),SrcY0 :: integer(),SrcX1 :: integer(),SrcY1 :: integer(),DstX0 :: integer(),DstY0 :: integer(),DstX1 :: integer(),DstY1 :: integer(),Mask :: integer(),Filter :: enum(). blitFramebuffer(SrcX0,SrcY0,SrcX1,SrcY1,DstX0,DstY0,DstX1,DstY1,Mask,Filter) -> cast(5667, <<SrcX0:?GLint,SrcY0:?GLint,SrcX1:?GLint,SrcY1:?GLint,DstX0:?GLint,DstY0:?GLint,DstX1:?GLint,DstY1:?GLint,Mask:?GLbitfield,Filter:?GLenum>>). @@ -13869,21 +6427,7 @@ blitFramebuffer(SrcX0,SrcY0,SrcX1,SrcY1,DstX0,DstY0,DstX1,DstY1,Mask,Filter) -> %% ``gl:renderbufferStorageMultisample'' establishes the data storage, format, dimensions %% and number of samples of a renderbuffer object's image. %% -%% The target of the operation, specified by `Target' must be `?GL_RENDERBUFFER'. -%% `Internalformat' specifies the internal format to be used for the renderbuffer object's -%% storage and must be a color-renderable, depth-renderable, or stencil-renderable format. `Width' -%% and `Height' are the dimensions, in pixels, of the renderbuffer. Both `Width' -%% and `Height' must be less than or equal to the value of `?GL_MAX_RENDERBUFFER_SIZE' -%% . `Samples' specifies the number of samples to be used for the renderbuffer object's -%% image, and must be less than or equal to the value of `?GL_MAX_SAMPLES'. If `Internalformat' -%% is a signed or unsigned integer format then `Samples' must be less than or equal -%% to the value of `?GL_MAX_INTEGER_SAMPLES'. -%% -%% Upon success, ``gl:renderbufferStorageMultisample'' deletes any existing data store -%% for the renderbuffer image and the contents of the data store after calling ``gl:renderbufferStorageMultisample'' -%% are undefined. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glRenderbufferStorageMultisample.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glRenderbufferStorageMultisample.xhtml">external</a> documentation. -spec renderbufferStorageMultisample(Target, Samples, Internalformat, Width, Height) -> 'ok' when Target :: enum(),Samples :: integer(),Internalformat :: enum(),Width :: integer(),Height :: integer(). renderbufferStorageMultisample(Target,Samples,Internalformat,Width,Height) -> cast(5668, <<Target:?GLenum,Samples:?GLsizei,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei>>). @@ -13909,7 +6453,7 @@ framebufferTextureFaceARB(Target,Attachment,Texture,Level,Face) -> %% mapped range of the buffer. ``gl:flushMappedBufferRange'' may be called multiple times %% to indicate distinct subranges of the mapping which require flushing. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFlushMappedBufferRange.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glFlushMappedBufferRange.xhtml">external</a> documentation. -spec flushMappedBufferRange(Target, Offset, Length) -> 'ok' when Target :: enum(),Offset :: integer(),Length :: integer(). flushMappedBufferRange(Target,Offset,Length) -> cast(5671, <<Target:?GLenum,0:32,Offset:?GLintptr,Length:?GLsizeiptr>>). @@ -13920,11 +6464,7 @@ flushMappedBufferRange(Target,Offset,Length) -> %% is the name of a vertex array object previously returned from a call to {@link gl:genVertexArrays/1} %% , or zero to break the existing vertex array object binding. %% -%% If no vertex array object with name `Array' exists, one is created when `Array' -%% is first bound. If the bind is successful no change is made to the state of the vertex -%% array object, and any previous vertex array object binding is broken. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindVertexArray.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindVertexArray.xhtml">external</a> documentation. -spec bindVertexArray(Array) -> 'ok' when Array :: integer(). bindVertexArray(Array) -> cast(5672, <<Array:?GLuint>>). @@ -13937,7 +6477,7 @@ bindVertexArray(Array) -> %% is deleted, the binding for that object reverts to zero and the default vertex array becomes %% current. Unused names in `Arrays' are silently ignored, as is the value zero. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteVertexArrays.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteVertexArrays.xhtml">external</a> documentation. -spec deleteVertexArrays(Arrays) -> 'ok' when Arrays :: [integer()]. deleteVertexArrays(Arrays) -> ArraysLen = length(Arrays), @@ -13951,13 +6491,7 @@ deleteVertexArrays(Arrays) -> %% guaranteed that none of the returned names was in use immediately before the call to ``gl:genVertexArrays'' %% . %% -%% Vertex array object names returned by a call to ``gl:genVertexArrays'' are not returned -%% by subsequent calls, unless they are first deleted with {@link gl:deleteVertexArrays/1} . -%% -%% The names returned in `Arrays' are marked as used, for the purposes of ``gl:genVertexArrays'' -%% only, but they acquire state and type only when they are first bound. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenVertexArrays.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenVertexArrays.xhtml">external</a> documentation. -spec genVertexArrays(N) -> [integer()] when N :: integer(). genVertexArrays(N) -> call(5674, <<N:?GLsizei>>). @@ -13971,7 +6505,7 @@ genVertexArrays(N) -> %% been bound through a call to {@link gl:bindVertexArray/1} , then the name is not a vertex %% array object and ``gl:isVertexArray'' returns `?GL_FALSE'. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsVertexArray.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsVertexArray.xhtml">external</a> documentation. -spec isVertexArray(Array) -> 0|1 when Array :: integer(). isVertexArray(Array) -> call(5675, <<Array:?GLuint>>). @@ -13981,24 +6515,7 @@ isVertexArray(Array) -> %% ``gl:getUniformIndices'' retrieves the indices of a number of uniforms within `Program' %% . %% -%% `Program' must be the name of a program object for which the command {@link gl:linkProgram/1} -%% must have been called in the past, although it is not required that {@link gl:linkProgram/1} -%% must have succeeded. The link could have failed because the number of active uniforms -%% exceeded the limit. -%% -%% `UniformCount' indicates both the number of elements in the array of names `UniformNames' -%% and the number of indices that may be written to `UniformIndices' . -%% -%% `UniformNames' contains a list of `UniformCount' name strings identifying the -%% uniform names to be queried for indices. For each name string in `UniformNames' , -%% the index assigned to the active uniform of that name will be written to the corresponding -%% element of `UniformIndices' . If a string in `UniformNames' is not the name of -%% an active uniform, the special value `?GL_INVALID_INDEX' will be written to the corresponding -%% element of `UniformIndices' . -%% -%% If an error occurs, nothing is written to `UniformIndices' . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformIndices.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetUniformIndices.xhtml">external</a> documentation. -spec getUniformIndices(Program, UniformNames) -> [integer()] when Program :: integer(),UniformNames :: iolist(). getUniformIndices(Program,UniformNames) -> UniformNamesTemp = list_to_binary([[Str|[0]] || Str <- UniformNames ]), @@ -14007,7 +6524,7 @@ getUniformIndices(Program,UniformNames) -> %% @doc glGetActiveUniforms %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniforms.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getActiveUniformsiv(Program, UniformIndices, Pname) -> [integer()] when Program :: integer(),UniformIndices :: [integer()],Pname :: enum(). getActiveUniformsiv(Program,UniformIndices,Pname) -> UniformIndicesLen = length(UniformIndices), @@ -14026,19 +6543,7 @@ getActiveUniformsiv(Program,UniformIndices,Pname) -> %% is given by the value of `?GL_ACTIVE_UNIFORM_MAX_LENGTH', which can be queried with {@link gl:getProgramiv/2} %% . %% -%% If ``gl:getActiveUniformName'' is not successful, nothing is written to `Length' -%% or `UniformName' . -%% -%% `Program' must be the name of a program for which the command {@link gl:linkProgram/1} -%% has been issued in the past. It is not necessary for `Program' to have been linked -%% successfully. The link could have failed because the number of active uniforms exceeded -%% the limit. -%% -%% `UniformIndex' must be an active uniform index of the program `Program' , in -%% the range zero to `?GL_ACTIVE_UNIFORMS' - 1. The value of `?GL_ACTIVE_UNIFORMS' -%% can be queried with {@link gl:getProgramiv/2} . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniformName.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveUniformName.xhtml">external</a> documentation. -spec getActiveUniformName(Program, UniformIndex, BufSize) -> string() when Program :: integer(),UniformIndex :: integer(),BufSize :: integer(). getActiveUniformName(Program,UniformIndex,BufSize) -> call(5678, <<Program:?GLuint,UniformIndex:?GLuint,BufSize:?GLsizei>>). @@ -14048,21 +6553,7 @@ getActiveUniformName(Program,UniformIndex,BufSize) -> %% ``gl:getUniformBlockIndex'' retrieves the index of a uniform block within `Program' . %% %% -%% `Program' must be the name of a program object for which the command {@link gl:linkProgram/1} -%% must have been called in the past, although it is not required that {@link gl:linkProgram/1} -%% must have succeeded. The link could have failed because the number of active uniforms -%% exceeded the limit. -%% -%% `UniformBlockName' must contain a nul-terminated string specifying the name of the -%% uniform block. -%% -%% ``gl:getUniformBlockIndex'' returns the uniform block index for the uniform block named -%% `UniformBlockName' of `Program' . If `UniformBlockName' does not identify -%% an active uniform block of `Program' , ``gl:getUniformBlockIndex'' returns the special -%% identifier, `?GL_INVALID_INDEX'. Indices of the active uniform blocks of a program -%% are assigned in consecutive order, beginning with zero. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformBlockIndex.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetUniformBlockIndex.xhtml">external</a> documentation. -spec getUniformBlockIndex(Program, UniformBlockName) -> integer() when Program :: integer(),UniformBlockName :: string(). getUniformBlockIndex(Program,UniformBlockName) -> UniformBlockNameLen = length(UniformBlockName), @@ -14073,49 +6564,7 @@ getUniformBlockIndex(Program,UniformBlockName) -> %% ``gl:getActiveUniformBlockiv'' retrieves information about an active uniform block within %% `Program' . %% -%% `Program' must be the name of a program object for which the command {@link gl:linkProgram/1} -%% must have been called in the past, although it is not required that {@link gl:linkProgram/1} -%% must have succeeded. The link could have failed because the number of active uniforms -%% exceeded the limit. -%% -%% `UniformBlockIndex' is an active uniform block index of `Program' , and must -%% be less than the value of `?GL_ACTIVE_UNIFORM_BLOCKS'. -%% -%% Upon success, the uniform block parameter(s) specified by `Pname' are returned in `Params' -%% . If an error occurs, nothing will be written to `Params' . -%% -%% If `Pname' is `?GL_UNIFORM_BLOCK_BINDING', then the index of the uniform buffer -%% binding point last selected by the uniform block specified by `UniformBlockIndex' -%% for `Program' is returned. If no uniform block has been previously specified, zero -%% is returned. -%% -%% If `Pname' is `?GL_UNIFORM_BLOCK_DATA_SIZE', then the implementation-dependent -%% minimum total buffer object size, in basic machine units, required to hold all active -%% uniforms in the uniform block identified by `UniformBlockIndex' is returned. It is -%% neither guaranteed nor expected that a given implementation will arrange uniform values -%% as tightly packed in a buffer object. The exception to this is the `std140 uniform block layout' -%% , which guarantees specific packing behavior and does not require the application to query -%% for offsets and strides. In this case the minimum size may still be queried, even though -%% it is determined in advance based only on the uniform block declaration. -%% -%% If `Pname' is `?GL_UNIFORM_BLOCK_NAME_LENGTH', then the total length (including -%% the nul terminator) of the name of the uniform block identified by `UniformBlockIndex' -%% is returned. -%% -%% If `Pname' is `?GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS', then the number of active -%% uniforms in the uniform block identified by `UniformBlockIndex' is returned. -%% -%% If `Pname' is `?GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES', then a list of the -%% active uniform indices for the uniform block identified by `UniformBlockIndex' is -%% returned. The number of elements that will be written to `Params' is the value of `?GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS' -%% for `UniformBlockIndex' . -%% -%% If `Pname' is `?GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER', `?GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER' -%% , or `?GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER', then a boolean value indicating -%% whether the uniform block identified by `UniformBlockIndex' is referenced by the -%% vertex, geometry, or fragment programming stages of program, respectively, is returned. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniformBlock.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveUniformBlock.xhtml">external</a> documentation. -spec getActiveUniformBlockiv(Program, UniformBlockIndex, Pname, Params) -> 'ok' when Program :: integer(),UniformBlockIndex :: integer(),Pname :: enum(),Params :: mem(). getActiveUniformBlockiv(Program,UniformBlockIndex,Pname,Params) -> send_bin(Params), @@ -14126,26 +6575,7 @@ getActiveUniformBlockiv(Program,UniformBlockIndex,Pname,Params) -> %% ``gl:getActiveUniformBlockName'' retrieves the name of the active uniform block at `UniformBlockIndex' %% within `Program' . %% -%% `Program' must be the name of a program object for which the command {@link gl:linkProgram/1} -%% must have been called in the past, although it is not required that {@link gl:linkProgram/1} -%% must have succeeded. The link could have failed because the number of active uniforms -%% exceeded the limit. -%% -%% `UniformBlockIndex' is an active uniform block index of `Program' , and must -%% be less than the value of `?GL_ACTIVE_UNIFORM_BLOCKS'. -%% -%% Upon success, the name of the uniform block identified by `UnifomBlockIndex' is -%% returned into `UniformBlockName' . The name is nul-terminated. The actual number of -%% characters written into `UniformBlockName' , excluding the nul terminator, is returned -%% in `Length' . If `Length' is NULL, no length is returned. -%% -%% `BufSize' contains the maximum number of characters (including the nul terminator) -%% that will be written into `UniformBlockName' . -%% -%% If an error occurs, nothing will be written to `UniformBlockName' or `Length' . -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniformBlockName.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveUniformBlockName.xhtml">external</a> documentation. -spec getActiveUniformBlockName(Program, UniformBlockIndex, BufSize) -> string() when Program :: integer(),UniformBlockIndex :: integer(),BufSize :: integer(). getActiveUniformBlockName(Program,UniformBlockIndex,BufSize) -> call(5681, <<Program:?GLuint,UniformBlockIndex:?GLuint,BufSize:?GLsizei>>). @@ -14157,15 +6587,7 @@ getActiveUniformBlockName(Program,UniformBlockIndex,BufSize) -> %% `Program' is the name of a program object for which the command {@link gl:linkProgram/1} %% has been issued in the past. %% -%% If successful, ``gl:uniformBlockBinding'' specifies that `Program' will use the -%% data store of the buffer object bound to the binding point `UniformBlockBinding' -%% to extract the values of the uniforms in the uniform block identified by `UniformBlockIndex' -%% . -%% -%% When a program object is linked or re-linked, the uniform buffer object binding point -%% assigned to each of its active uniform blocks is reset to zero. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformBlockBinding.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUniformBlockBinding.xhtml">external</a> documentation. -spec uniformBlockBinding(Program, UniformBlockIndex, UniformBlockBinding) -> 'ok' when Program :: integer(),UniformBlockIndex :: integer(),UniformBlockBinding :: integer(). uniformBlockBinding(Program,UniformBlockIndex,UniformBlockBinding) -> cast(5682, <<Program:?GLuint,UniformBlockIndex:?GLuint,UniformBlockBinding:?GLuint>>). @@ -14177,21 +6599,7 @@ uniformBlockBinding(Program,UniformBlockIndex,UniformBlockBinding) -> %% by `Size' is copied from the source, at offset `Readoffset' to the destination %% at `Writeoffset' , also in basic machine units. %% -%% `Readtarget' and `Writetarget' must be `?GL_ARRAY_BUFFER', `?GL_COPY_READ_BUFFER' -%% , `?GL_COPY_WRITE_BUFFER', `?GL_ELEMENT_ARRAY_BUFFER', `?GL_PIXEL_PACK_BUFFER' -%% , `?GL_PIXEL_UNPACK_BUFFER', `?GL_TEXTURE_BUFFER', `?GL_TRANSFORM_FEEDBACK_BUFFER' -%% or `?GL_UNIFORM_BUFFER'. Any of these targets may be used, although the targets `?GL_COPY_READ_BUFFER' -%% and `?GL_COPY_WRITE_BUFFER' are provided specifically to allow copies between buffers -%% without disturbing other GL state. -%% -%% `Readoffset' , `Writeoffset' and `Size' must all be greater than or equal -%% to zero. Furthermore, `Readoffset' + `Size' must not exceeed the size of the -%% buffer object bound to `Readtarget' , and `Readoffset' + `Size' must not -%% exceeed the size of the buffer bound to `Writetarget' . If the same buffer object -%% is bound to both `Readtarget' and `Writetarget' , then the ranges specified by `Readoffset' -%% , `Writeoffset' and `Size' must not overlap. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCopyBufferSubData.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCopyBufferSubData.xhtml">external</a> documentation. -spec copyBufferSubData(ReadTarget, WriteTarget, ReadOffset, WriteOffset, Size) -> 'ok' when ReadTarget :: enum(),WriteTarget :: enum(),ReadOffset :: integer(),WriteOffset :: integer(),Size :: integer(). copyBufferSubData(ReadTarget,WriteTarget,ReadOffset,WriteOffset,Size) -> cast(5683, <<ReadTarget:?GLenum,WriteTarget:?GLenum,ReadOffset:?GLintptr,WriteOffset:?GLintptr,Size:?GLsizeiptr>>). @@ -14205,7 +6613,7 @@ copyBufferSubData(ReadTarget,WriteTarget,ReadOffset,WriteOffset,Size) -> %% were upconverted to 32-bit unsigned integers (with wrapping on overflow conditions). The %% operation is undefined if the sum would be negative. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsBaseVertex.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElementsBaseVertex.xhtml">external</a> documentation. -spec drawElementsBaseVertex(Mode, Count, Type, Indices, Basevertex) -> 'ok' when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Basevertex :: integer(). drawElementsBaseVertex(Mode,Count,Type,Indices,Basevertex) when is_integer(Indices) -> cast(5684, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Basevertex:?GLint>>); @@ -14227,7 +6635,7 @@ drawElementsBaseVertex(Mode,Count,Type,Indices,Basevertex) -> %% to 32-bit unsigned integers (with wrapping on overflow conditions). The operation is undefined %% if the sum would be negative. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawRangeElementsBaseVertex.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawRangeElementsBaseVertex.xhtml">external</a> documentation. -spec drawRangeElementsBaseVertex(Mode, Start, End, Count, Type, Indices, Basevertex) -> 'ok' when Mode :: enum(),Start :: integer(),End :: integer(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Basevertex :: integer(). drawRangeElementsBaseVertex(Mode,Start,End,Count,Type,Indices,Basevertex) when is_integer(Indices) -> cast(5686, <<Mode:?GLenum,Start:?GLuint,End:?GLuint,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Basevertex:?GLint>>); @@ -14244,7 +6652,7 @@ drawRangeElementsBaseVertex(Mode,Start,End,Count,Type,Indices,Basevertex) -> %% if the calculation were upconverted to 32-bit unsigned integers (with wrapping on overflow %% conditions). The operation is undefined if the sum would be negative. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsInstancedBaseVertex.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElementsInstancedBaseVertex.xhtml">external</a> documentation. -spec drawElementsInstancedBaseVertex(Mode, Count, Type, Indices, Primcount, Basevertex) -> 'ok' when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Primcount :: integer(),Basevertex :: integer(). drawElementsInstancedBaseVertex(Mode,Count,Type,Indices,Primcount,Basevertex) when is_integer(Indices) -> cast(5688, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Primcount:?GLsizei,Basevertex:?GLint>>); @@ -14259,29 +6667,7 @@ drawElementsInstancedBaseVertex(Mode,Count,Type,Indices,Primcount,Basevertex) -> %% as the `provoking vertex' and ``gl:provokingVertex'' specifies which vertex is %% to be used as the source of data for flat shaded varyings. %% -%% `ProvokeMode' must be either `?GL_FIRST_VERTEX_CONVENTION' or `?GL_LAST_VERTEX_CONVENTION' -%% , and controls the selection of the vertex whose values are assigned to flatshaded varying -%% outputs. The interpretation of these values for the supported primitive types is: <table><tbody> -%% <tr><td>` Primitive Type of Polygon '`i'</td><td>` First Vertex Convention ' -%% </td><td>` Last Vertex Convention '</td></tr><tr><td> point </td><td>`i'</td><td> -%% `i'</td></tr><tr><td> independent line </td><td> 2`i' - 1 </td><td> 2`i'</td> -%% </tr><tr><td> line loop </td><td>`i'</td><td> -%% -%% `i' + 1, if `i' < `n' -%% -%% 1, if `i' = `n'</td></tr><tr><td> line strip </td><td>`i'</td><td>`i' -%% + 1 </td></tr><tr><td> independent triangle </td><td> 3`i' - 2 </td><td> 3`i'</td> -%% </tr><tr><td> triangle strip </td><td>`i'</td><td>`i' + 2 </td></tr><tr><td> -%% triangle fan </td><td>`i' + 1 </td><td>`i' + 2 </td></tr><tr><td> line adjacency -%% </td><td> 4`i' - 2 </td><td> 4`i' - 1 </td></tr><tr><td> line strip adjacency </td> -%% <td>`i' + 1 </td><td>`i' + 2 </td></tr><tr><td> triangle adjacency </td><td> 6`i' -%% - 5 </td><td> 6`i' - 1 </td></tr><tr><td> triangle strip adjacency </td><td> 2`i' -%% - 1 </td><td> 2`i' + 3 </td></tr></tbody></table> -%% -%% If a vertex or geometry shader is active, user-defined varying outputs may be flatshaded -%% by using the flat qualifier when declaring the output. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProvokingVertex.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glProvokingVertex.xhtml">external</a> documentation. -spec provokingVertex(Mode) -> 'ok' when Mode :: enum(). provokingVertex(Mode) -> cast(5690, <<Mode:?GLenum>>). @@ -14292,20 +6678,7 @@ provokingVertex(Mode) -> %% command stream and associates it with that sync object, and returns a non-zero name corresponding %% to the sync object. %% -%% When the specified `Condition' of the sync object is satisfied by the fence command, -%% the sync object is signaled by the GL, causing any {@link gl:waitSync/3} , {@link gl:clientWaitSync/3} -%% commands blocking in `Sync' to `unblock'. No other state is affected by ``gl:fenceSync'' -%% or by the execution of the associated fence command. -%% -%% `Condition' must be `?GL_SYNC_GPU_COMMANDS_COMPLETE'. This condition is satisfied -%% by completion of the fence command corresponding to the sync object and all preceding -%% commands in the same command stream. The sync object will not be signaled until all effects -%% from these commands on GL client and server state and the framebuffer are fully realized. -%% Note that completion of the fence command occurs once the state of the corresponding sync -%% object has been changed, but commands waiting on that sync object may not be unblocked -%% until after the fence command completes. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glFenceSync.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glFenceSync.xhtml">external</a> documentation. -spec fenceSync(Condition, Flags) -> integer() when Condition :: enum(),Flags :: integer(). fenceSync(Condition,Flags) -> call(5691, <<Condition:?GLenum,Flags:?GLbitfield>>). @@ -14316,7 +6689,7 @@ fenceSync(Condition,Flags) -> %% object. If `Sync' is not the name of a sync object, or if an error occurs, ``gl:isSync'' %% returns `?GL_FALSE'. Note that zero is not the name of a sync object. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsSync.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsSync.xhtml">external</a> documentation. -spec isSync(Sync) -> 0|1 when Sync :: integer(). isSync(Sync) -> call(5692, <<Sync:?GLsync>>). @@ -14331,9 +6704,7 @@ isSync(Sync) -> %% or {@link gl:clientWaitSync/3} command. In either case, after ``gl:deleteSync'' returns, %% the name `Sync' is invalid and can no longer be used to refer to the sync object. %% -%% ``gl:deleteSync'' will silently ignore a `Sync' value of zero. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteSync.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteSync.xhtml">external</a> documentation. -spec deleteSync(Sync) -> 'ok' when Sync :: integer(). deleteSync(Sync) -> cast(5693, <<Sync:?GLsync>>). @@ -14345,21 +6716,7 @@ deleteSync(Sync) -> %% is called, ``gl:clientWaitSync'' returns immediately, otherwise it will block and wait %% for up to `Timeout' nanoseconds for `Sync' to become signaled. %% -%% The return value is one of four status values: -%% -%% `?GL_ALREADY_SIGNALED' indicates that `Sync' was signaled at the time that ``gl:clientWaitSync'' -%% was called. -%% -%% `?GL_TIMEOUT_EXPIRED' indicates that at least `Timeout' nanoseconds passed and `Sync' -%% did not become signaled. -%% -%% `?GL_CONDITION_SATISFIED' indicates that `Sync' was signaled before the timeout -%% expired. -%% -%% `?GL_WAIT_FAILED' indicates that an error occurred. Additionally, an OpenGL error -%% will be generated. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClientWaitSync.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glClientWaitSync.xhtml">external</a> documentation. -spec clientWaitSync(Sync, Flags, Timeout) -> enum() when Sync :: integer(),Flags :: integer(),Timeout :: integer(). clientWaitSync(Sync,Flags,Timeout) -> call(5694, <<Sync:?GLsync,Flags:?GLbitfield,0:32,Timeout:?GLuint64>>). @@ -14373,15 +6730,9 @@ clientWaitSync(Sync,Flags,Timeout) -> %% %% `Flags' and `Timeout' are placeholders for anticipated future extensions of %% sync object capabilities. They must have these reserved values in order that existing -%% code calling ``gl:waitSync'' operate properly in the presence of such extensions.. ``gl:waitSync'' -%% will always wait no longer than an implementation-dependent timeout. The duration of -%% this timeout in nanoseconds may be queried by calling {@link gl:getBooleanv/1} with the parameter `?GL_MAX_SERVER_WAIT_TIMEOUT' -%% . There is currently no way to determine whether ``gl:waitSync'' unblocked because the -%% timeout expired or because the sync object being waited on was signaled. -%% -%% If an error occurs, ``gl:waitSync'' does not cause the GL server to block. +%% code calling ``gl:waitSync'' operate properly in the presence of such extensions. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glWaitSync.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glWaitSync.xhtml">external</a> documentation. -spec waitSync(Sync, Flags, Timeout) -> 'ok' when Sync :: integer(),Flags :: integer(),Timeout :: integer(). waitSync(Sync,Flags,Timeout) -> cast(5695, <<Sync:?GLsync,Flags:?GLbitfield,0:32,Timeout:?GLuint64>>). @@ -14397,32 +6748,7 @@ getInteger64v(Pname) -> %% ``gl:getSynciv'' retrieves properties of a sync object. `Sync' specifies the name %% of the sync object whose properties to retrieve. %% -%% On success, ``gl:getSynciv'' replaces up to `BufSize' integers in `Values' -%% with the corresponding property values of the object being queried. The actual number -%% of integers replaced is returned in the variable whose address is specified in `Length' -%% . If `Length' is NULL, no length is returned. -%% -%% If `Pname' is `?GL_OBJECT_TYPE', a single value representing the specific type -%% of the sync object is placed in `Values' . The only type supported is `?GL_SYNC_FENCE' -%% . -%% -%% If `Pname' is `?GL_SYNC_STATUS', a single value representing the status of -%% the sync object (`?GL_SIGNALED' or `?GL_UNSIGNALED') is placed in `Values' . -%% -%% -%% If `Pname' is `?GL_SYNC_CONDITION', a single value representing the condition -%% of the sync object is placed in `Values' . The only condition supported is `?GL_SYNC_GPU_COMMANDS_COMPLETE' -%% . -%% -%% If `Pname' is `?GL_SYNC_FLAGS', a single value representing the flags with -%% which the sync object was created is placed in `Values' . No flags are currently supported -%% -%% -%% `Flags' is expected to be used in future extensions to the sync objects.. -%% -%% If an error occurs, nothing will be written to `Values' or `Length' . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSync.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetSync.xhtml">external</a> documentation. -spec getSynciv(Sync, Pname, BufSize) -> [integer()] when Sync :: integer(),Pname :: enum(),BufSize :: integer(). getSynciv(Sync,Pname,BufSize) -> call(5697, <<Sync:?GLsync,Pname:?GLenum,BufSize:?GLsizei>>). @@ -14432,25 +6758,7 @@ getSynciv(Sync,Pname,BufSize) -> %% ``gl:texImage2DMultisample'' establishes the data storage, format, dimensions and number %% of samples of a multisample texture's image. %% -%% `Target' must be `?GL_TEXTURE_2D_MULTISAMPLE' or `?GL_PROXY_TEXTURE_2D_MULTISAMPLE' -%% . `Width' and `Height' are the dimensions in texels of the texture, and must -%% be in the range zero to `?GL_MAX_TEXTURE_SIZE' - 1. `Samples' specifies the -%% number of samples in the image and must be in the range zero to `?GL_MAX_SAMPLES' -%% - 1. -%% -%% `Internalformat' must be a color-renderable, depth-renderable, or stencil-renderable -%% format. -%% -%% If `Fixedsamplelocations' is `?GL_TRUE', the image will use identical sample -%% locations and the same number of samples for all texels in the image, and the sample locations -%% will not depend on the internal format or size of the image. -%% -%% When a multisample texture is accessed in a shader, the access takes one vector of integers -%% describing which texel to fetch and an integer corresponding to the sample numbers describing -%% which sample within the texel to fetch. No standard sampling instructions are allowed -%% on the multisample texture targets. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2DMultisample.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2DMultisample.xhtml">external</a> documentation. -spec texImage2DMultisample(Target, Samples, Internalformat, Width, Height, Fixedsamplelocations) -> 'ok' when Target :: enum(),Samples :: integer(),Internalformat :: integer(),Width :: integer(),Height :: integer(),Fixedsamplelocations :: 0|1. texImage2DMultisample(Target,Samples,Internalformat,Width,Height,Fixedsamplelocations) -> cast(5698, <<Target:?GLenum,Samples:?GLsizei,Internalformat:?GLint,Width:?GLsizei,Height:?GLsizei,Fixedsamplelocations:?GLboolean>>). @@ -14460,25 +6768,7 @@ texImage2DMultisample(Target,Samples,Internalformat,Width,Height,Fixedsampleloca %% ``gl:texImage3DMultisample'' establishes the data storage, format, dimensions and number %% of samples of a multisample texture's image. %% -%% `Target' must be `?GL_TEXTURE_2D_MULTISAMPLE_ARRAY' or `?GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY' -%% . `Width' and `Height' are the dimensions in texels of the texture, and must -%% be in the range zero to `?GL_MAX_TEXTURE_SIZE' - 1. `Depth' is the number of -%% array slices in the array texture's image. `Samples' specifies the number of samples -%% in the image and must be in the range zero to `?GL_MAX_SAMPLES' - 1. -%% -%% `Internalformat' must be a color-renderable, depth-renderable, or stencil-renderable -%% format. -%% -%% If `Fixedsamplelocations' is `?GL_TRUE', the image will use identical sample -%% locations and the same number of samples for all texels in the image, and the sample locations -%% will not depend on the internal format or size of the image. -%% -%% When a multisample texture is accessed in a shader, the access takes one vector of integers -%% describing which texel to fetch and an integer corresponding to the sample numbers describing -%% which sample within the texel to fetch. No standard sampling instructions are allowed -%% on the multisample texture targets. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexImage3DMultisample.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage3DMultisample.xhtml">external</a> documentation. -spec texImage3DMultisample(Target, Samples, Internalformat, Width, Height, Depth, Fixedsamplelocations) -> 'ok' when Target :: enum(),Samples :: integer(),Internalformat :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Fixedsamplelocations :: 0|1. texImage3DMultisample(Target,Samples,Internalformat,Width,Height,Depth,Fixedsamplelocations) -> cast(5699, <<Target:?GLenum,Samples:?GLsizei,Internalformat:?GLint,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei,Fixedsamplelocations:?GLboolean>>). @@ -14493,10 +6783,7 @@ texImage3DMultisample(Target,Samples,Internalformat,Width,Height,Depth,Fixedsamp %% space of that sample. (0.5, 0.5) this corresponds to the pixel center. `Index' must %% be between zero and the value of `?GL_SAMPLES' - 1. %% -%% If the multisample mode does not have fixed sample locations, the returned values may -%% only reflect the locations of samples within some pixels. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetMultisample.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetMultisample.xhtml">external</a> documentation. -spec getMultisamplefv(Pname, Index) -> {float(),float()} when Pname :: enum(),Index :: integer(). getMultisamplefv(Pname,Index) -> call(5700, <<Pname:?GLenum,Index:?GLuint>>). @@ -14506,19 +6793,14 @@ getMultisamplefv(Pname,Index) -> %% ``gl:sampleMaski'' sets one 32-bit sub-word of the multi-word sample mask, `?GL_SAMPLE_MASK_VALUE' %% . %% -%% `MaskIndex' specifies which 32-bit sub-word of the sample mask to update, and `Mask' -%% specifies the new value to use for that sub-word. `MaskIndex' must be less than -%% the value of `?GL_MAX_SAMPLE_MASK_WORDS'. Bit `B' of mask word `M' corresponds -%% to sample 32 x `M' + `B'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSampleMaski.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glSampleMaski.xhtml">external</a> documentation. -spec sampleMaski(Index, Mask) -> 'ok' when Index :: integer(),Mask :: integer(). sampleMaski(Index,Mask) -> cast(5701, <<Index:?GLuint,Mask:?GLbitfield>>). %% @doc glNamedStringARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glNamedStringARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec namedStringARB(Type, Name, String) -> 'ok' when Type :: enum(),Name :: string(),String :: string(). namedStringARB(Type,Name,String) -> NameLen = length(Name), @@ -14527,7 +6809,7 @@ namedStringARB(Type,Name,String) -> %% @doc glDeleteNamedStringARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteNamedStringARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec deleteNamedStringARB(Name) -> 'ok' when Name :: string(). deleteNamedStringARB(Name) -> NameLen = length(Name), @@ -14535,7 +6817,7 @@ deleteNamedStringARB(Name) -> %% @doc glCompileShaderIncludeARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCompileShaderIncludeARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec compileShaderIncludeARB(Shader, Path) -> 'ok' when Shader :: integer(),Path :: iolist(). compileShaderIncludeARB(Shader,Path) -> PathTemp = list_to_binary([[Str|[0]] || Str <- Path ]), @@ -14544,7 +6826,7 @@ compileShaderIncludeARB(Shader,Path) -> %% @doc glIsNamedStringARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsNamedStringARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec isNamedStringARB(Name) -> 0|1 when Name :: string(). isNamedStringARB(Name) -> NameLen = length(Name), @@ -14552,7 +6834,7 @@ isNamedStringARB(Name) -> %% @doc glGetNamedStringARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetNamedStringARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getNamedStringARB(Name, BufSize) -> string() when Name :: string(),BufSize :: integer(). getNamedStringARB(Name,BufSize) -> NameLen = length(Name), @@ -14560,7 +6842,7 @@ getNamedStringARB(Name,BufSize) -> %% @doc glGetNamedStringARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetNamedStringARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getNamedStringivARB(Name, Pname) -> integer() when Name :: string(),Pname :: enum(). getNamedStringivARB(Name,Pname) -> NameLen = length(Name), @@ -14568,7 +6850,7 @@ getNamedStringivARB(Name,Pname) -> %% @doc glBindFragDataLocationIndexe %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindFragDataLocationIndexe.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec bindFragDataLocationIndexed(Program, ColorNumber, Index, Name) -> 'ok' when Program :: integer(),ColorNumber :: integer(),Index :: integer(),Name :: string(). bindFragDataLocationIndexed(Program,ColorNumber,Index,Name) -> NameLen = length(Name), @@ -14580,7 +6862,7 @@ bindFragDataLocationIndexed(Program,ColorNumber,Index,Name) -> %% was bound when the program object `Program' was last linked. If `Name' is not %% a varying out variable of `Program' , or if an error occurs, -1 will be returned. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetFragDataIndex.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetFragDataIndex.xhtml">external</a> documentation. -spec getFragDataIndex(Program, Name) -> integer() when Program :: integer(),Name :: string(). getFragDataIndex(Program,Name) -> NameLen = length(Name), @@ -14593,13 +6875,7 @@ getFragDataIndex(Program,Name) -> %% that none of the returned names was in use immediately before the call to ``gl:genSamplers'' %% . %% -%% Sampler object names returned by a call to ``gl:genSamplers'' are not returned by subsequent -%% calls, unless they are first deleted with {@link gl:deleteSamplers/1} . -%% -%% The names returned in `Samplers' are marked as used, for the purposes of ``gl:genSamplers'' -%% only, but they acquire state and type only when they are first bound. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenSamplers.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenSamplers.xhtml">external</a> documentation. -spec genSamplers(Count) -> [integer()] when Count :: integer(). genSamplers(Count) -> call(5710, <<Count:?GLsizei>>). @@ -14612,7 +6888,7 @@ genSamplers(Count) -> %% is called with unit set to the unit the sampler is bound to and sampler zero. Unused %% names in samplers are silently ignored, as is the reserved name zero. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteSamplers.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteSamplers.xhtml">external</a> documentation. -spec deleteSamplers(Samplers) -> 'ok' when Samplers :: [integer()]. deleteSamplers(Samplers) -> SamplersLen = length(Samplers), @@ -14625,9 +6901,7 @@ deleteSamplers(Samplers) -> %% object. If `Id' is zero, or is a non-zero value that is not currently the name of %% a sampler object, or if an error occurs, ``gl:isSampler'' returns `?GL_FALSE'. %% -%% A name returned by {@link gl:genSamplers/1} , is the name of a sampler object. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsSampler.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsSampler.xhtml">external</a> documentation. -spec isSampler(Sampler) -> 0|1 when Sampler :: integer(). isSampler(Sampler) -> call(5712, <<Sampler:?GLuint>>). @@ -14639,12 +6913,7 @@ isSampler(Sampler) -> %% . `Unit' must be less than the value of `?GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS'. %% %% -%% When a sampler object is bound to a texture unit, its state supersedes that of the texture -%% object bound to that texture unit. If the sampler name zero is bound to a texture unit, -%% the currently bound texture's sampler state becomes active. A single sampler object may -%% be bound to multiple texture units simultaneously. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindSampler.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindSampler.xhtml">external</a> documentation. -spec bindSampler(Unit, Sampler) -> 'ok' when Unit :: integer(),Sampler :: integer(). bindSampler(Unit,Sampler) -> cast(5713, <<Unit:?GLuint,Sampler:?GLuint>>). @@ -14656,141 +6925,7 @@ bindSampler(Unit,Sampler) -> %% modified, and must be the name of a sampler object previously returned from a call to {@link gl:genSamplers/1} %% . The following symbols are accepted in `Pname' : %% -%% `?GL_TEXTURE_MIN_FILTER': The texture minifying function is used whenever the pixel -%% being textured maps to an area greater than one texture element. There are six defined -%% minifying functions. Two of them use the nearest one or nearest four texture elements -%% to compute the texture value. The other four use mipmaps. -%% -%% A mipmap is an ordered set of arrays representing the same image at progressively lower -%% resolutions. If the texture has dimensions 2 n×2 m, there are max(n m)+1 mipmaps. The first -%% mipmap is the original texture, with dimensions 2 n×2 m. Each subsequent mipmap has -%% dimensions 2(k-1)×2(l-1), where 2 k×2 l are the dimensions of the previous mipmap, until either -%% k=0 or l=0. At that point, subsequent mipmaps have dimension 1×2(l-1) or 2(k-1)×1 until -%% the final mipmap, which has dimension 1×1. To define the mipmaps, call {@link gl:texImage1D/8} -%% , {@link gl:texImage2D/9} , {@link gl:texImage3D/10} , {@link gl:copyTexImage1D/7} , or {@link gl:copyTexImage2D/8} -%% with the `level' argument indicating the order of the mipmaps. Level 0 is the original -%% texture; level max(n m) is the final 1×1 mipmap. -%% -%% `Params' supplies a function for minifying the texture as one of the following: -%% -%% `?GL_NEAREST': Returns the value of the texture element that is nearest (in Manhattan -%% distance) to the center of the pixel being textured. -%% -%% `?GL_LINEAR': Returns the weighted average of the four texture elements that are -%% closest to the center of the pixel being textured. These can include border texture elements, -%% depending on the values of `?GL_TEXTURE_WRAP_S' and `?GL_TEXTURE_WRAP_T', and -%% on the exact mapping. -%% -%% `?GL_NEAREST_MIPMAP_NEAREST': Chooses the mipmap that most closely matches the size -%% of the pixel being textured and uses the `?GL_NEAREST' criterion (the texture element -%% nearest to the center of the pixel) to produce a texture value. -%% -%% `?GL_LINEAR_MIPMAP_NEAREST': Chooses the mipmap that most closely matches the size -%% of the pixel being textured and uses the `?GL_LINEAR' criterion (a weighted average -%% of the four texture elements that are closest to the center of the pixel) to produce a -%% texture value. -%% -%% `?GL_NEAREST_MIPMAP_LINEAR': Chooses the two mipmaps that most closely match the -%% size of the pixel being textured and uses the `?GL_NEAREST' criterion (the texture -%% element nearest to the center of the pixel) to produce a texture value from each mipmap. -%% The final texture value is a weighted average of those two values. -%% -%% `?GL_LINEAR_MIPMAP_LINEAR': Chooses the two mipmaps that most closely match the -%% size of the pixel being textured and uses the `?GL_LINEAR' criterion (a weighted -%% average of the four texture elements that are closest to the center of the pixel) to produce -%% a texture value from each mipmap. The final texture value is a weighted average of those -%% two values. -%% -%% As more texture elements are sampled in the minification process, fewer aliasing artifacts -%% will be apparent. While the `?GL_NEAREST' and `?GL_LINEAR' minification functions -%% can be faster than the other four, they sample only one or four texture elements to determine -%% the texture value of the pixel being rendered and can produce moire patterns or ragged -%% transitions. The initial value of `?GL_TEXTURE_MIN_FILTER' is `?GL_NEAREST_MIPMAP_LINEAR' -%% . -%% -%% `?GL_TEXTURE_MAG_FILTER': The texture magnification function is used when the pixel -%% being textured maps to an area less than or equal to one texture element. It sets the -%% texture magnification function to either `?GL_NEAREST' or `?GL_LINEAR' (see -%% below). `?GL_NEAREST' is generally faster than `?GL_LINEAR', but it can produce -%% textured images with sharper edges because the transition between texture elements is -%% not as smooth. The initial value of `?GL_TEXTURE_MAG_FILTER' is `?GL_LINEAR'. -%% -%% `?GL_NEAREST': Returns the value of the texture element that is nearest (in Manhattan -%% distance) to the center of the pixel being textured. -%% -%% `?GL_LINEAR': Returns the weighted average of the four texture elements that are -%% closest to the center of the pixel being textured. These can include border texture elements, -%% depending on the values of `?GL_TEXTURE_WRAP_S' and `?GL_TEXTURE_WRAP_T', and -%% on the exact mapping. -%% -%% -%% -%% `?GL_TEXTURE_MIN_LOD': Sets the minimum level-of-detail parameter. This floating-point -%% value limits the selection of highest resolution mipmap (lowest mipmap level). The initial -%% value is -1000. -%% -%% -%% -%% `?GL_TEXTURE_MAX_LOD': Sets the maximum level-of-detail parameter. This floating-point -%% value limits the selection of the lowest resolution mipmap (highest mipmap level). The -%% initial value is 1000. -%% -%% -%% -%% `?GL_TEXTURE_WRAP_S': Sets the wrap parameter for texture coordinate s to either `?GL_CLAMP_TO_EDGE' -%% , `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. `?GL_CLAMP_TO_BORDER' causes -%% the s coordinate to be clamped to the range [(-1 2/N) 1+(1 2/N)], where N is the size of the texture in -%% the direction of clamping.`?GL_CLAMP_TO_EDGE' causes s coordinates to be clamped -%% to the range [(1 2/N) 1-(1 2/N)], where N is the size of the texture in the direction of clamping. `?GL_REPEAT' -%% causes the integer part of the s coordinate to be ignored; the GL uses only the fractional -%% part, thereby creating a repeating pattern. `?GL_MIRRORED_REPEAT' causes the s -%% coordinate to be set to the fractional part of the texture coordinate if the integer part -%% of s is even; if the integer part of s is odd, then the s texture coordinate is -%% set to 1-frac(s), where frac(s) represents the fractional part of s. Initially, `?GL_TEXTURE_WRAP_S' -%% is set to `?GL_REPEAT'. -%% -%% -%% -%% `?GL_TEXTURE_WRAP_T': Sets the wrap parameter for texture coordinate t to either `?GL_CLAMP_TO_EDGE' -%% , `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. See the discussion under `?GL_TEXTURE_WRAP_S' -%% . Initially, `?GL_TEXTURE_WRAP_T' is set to `?GL_REPEAT'. -%% -%% `?GL_TEXTURE_WRAP_R': Sets the wrap parameter for texture coordinate r to either `?GL_CLAMP_TO_EDGE' -%% , `?GL_MIRRORED_REPEAT', or `?GL_REPEAT'. See the discussion under `?GL_TEXTURE_WRAP_S' -%% . Initially, `?GL_TEXTURE_WRAP_R' is set to `?GL_REPEAT'. -%% -%% `?GL_TEXTURE_BORDER_COLOR': The data in `Params' specifies four values that -%% define the border values that should be used for border texels. If a texel is sampled -%% from the border of the texture, the values of `?GL_TEXTURE_BORDER_COLOR' are interpreted -%% as an RGBA color to match the texture's internal format and substituted for the non-existent -%% texel data. If the texture contains depth components, the first component of `?GL_TEXTURE_BORDER_COLOR' -%% is interpreted as a depth value. The initial value is (0.0, 0.0, 0.0, 0.0). -%% -%% `?GL_TEXTURE_COMPARE_MODE': Specifies the texture comparison mode for currently -%% bound textures. That is, a texture whose internal format is `?GL_DEPTH_COMPONENT_*'; -%% see {@link gl:texImage2D/9} ) Permissible values are: -%% -%% `?GL_COMPARE_REF_TO_TEXTURE': Specifies that the interpolated and clamped r texture -%% coordinate should be compared to the value in the currently bound texture. See the discussion -%% of `?GL_TEXTURE_COMPARE_FUNC' for details of how the comparison is evaluated. The -%% result of the comparison is assigned to the red channel. -%% -%% `?GL_NONE': Specifies that the red channel should be assigned the appropriate value -%% from the currently bound texture. -%% -%% `?GL_TEXTURE_COMPARE_FUNC': Specifies the comparison operator used when `?GL_TEXTURE_COMPARE_MODE' -%% is set to `?GL_COMPARE_REF_TO_TEXTURE'. Permissible values are: <table><tbody><tr><td> -%% ` Texture Comparison Function '</td><td>` Computed result '</td></tr></tbody><tbody> -%% <tr><td>`?GL_LEQUAL'</td><td> result={1.0 0.0 r<=(D t) r>(D t))</td></tr><tr><td>`?GL_GEQUAL'</td><td> -%% result={1.0 0.0 r>=(D t) r<(D t))</td></tr><tr><td>`?GL_LESS'</td><td> result={1.0 0.0 r<(D t) r>=(D t))</td></tr><tr><td>`?GL_GREATER' -%% </td><td> result={1.0 0.0 r>(D t) r<=(D t))</td></tr><tr><td>`?GL_EQUAL'</td><td> result={1.0 0.0 r=(D t) r&ne; -%% (D t))</td></tr><tr><td>`?GL_NOTEQUAL' -%% </td><td> result={1.0 0.0 r&ne;(D t) r=(D t))</td></tr><tr><td>`?GL_ALWAYS'</td><td> result=1.0</td></tr><tr><td> -%% `?GL_NEVER'</td><td> result=0.0</td></tr></tbody></table> where r is the current -%% interpolated texture coordinate, and D t is the texture value sampled from the currently -%% bound texture. result is assigned to R t. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSamplerParameter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glSamplerParameter.xhtml">external</a> documentation. -spec samplerParameteri(Sampler, Pname, Param) -> 'ok' when Sampler :: integer(),Pname :: enum(),Param :: integer(). samplerParameteri(Sampler,Pname,Param) -> cast(5714, <<Sampler:?GLuint,Pname:?GLenum,Param:?GLint>>). @@ -14827,7 +6962,7 @@ samplerParameterIiv(Sampler,Pname,Param) -> %% @doc glSamplerParameterI %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glSamplerParameterI.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec samplerParameterIuiv(Sampler, Pname, Param) -> 'ok' when Sampler :: integer(),Pname :: enum(),Param :: [integer()]. samplerParameterIuiv(Sampler,Pname,Param) -> ParamLen = length(Param), @@ -14842,41 +6977,7 @@ samplerParameterIuiv(Sampler,Pname,Param) -> %% . `Pname' accepts the same symbols as {@link gl:samplerParameteri/3} , with the same %% interpretations: %% -%% `?GL_TEXTURE_MAG_FILTER': Returns the single-valued texture magnification filter, -%% a symbolic constant. The initial value is `?GL_LINEAR'. -%% -%% `?GL_TEXTURE_MIN_FILTER': Returns the single-valued texture minification filter, -%% a symbolic constant. The initial value is `?GL_NEAREST_MIPMAP_LINEAR'. -%% -%% `?GL_TEXTURE_MIN_LOD': Returns the single-valued texture minimum level-of-detail -%% value. The initial value is -1000. -%% -%% `?GL_TEXTURE_MAX_LOD': Returns the single-valued texture maximum level-of-detail -%% value. The initial value is 1000. -%% -%% `?GL_TEXTURE_WRAP_S': Returns the single-valued wrapping function for texture coordinate -%% s, a symbolic constant. The initial value is `?GL_REPEAT'. -%% -%% `?GL_TEXTURE_WRAP_T': Returns the single-valued wrapping function for texture coordinate -%% t, a symbolic constant. The initial value is `?GL_REPEAT'. -%% -%% `?GL_TEXTURE_WRAP_R': Returns the single-valued wrapping function for texture coordinate -%% r, a symbolic constant. The initial value is `?GL_REPEAT'. -%% -%% `?GL_TEXTURE_BORDER_COLOR': Returns four integer or floating-point numbers that -%% comprise the RGBA color of the texture border. Floating-point values are returned in the -%% range [0 1]. Integer values are returned as a linear mapping of the internal floating-point -%% representation such that 1.0 maps to the most positive representable integer and -1.0 -%% maps to the most negative representable integer. The initial value is (0, 0, 0, 0). -%% -%% `?GL_TEXTURE_COMPARE_MODE': Returns a single-valued texture comparison mode, a symbolic -%% constant. The initial value is `?GL_NONE'. See {@link gl:samplerParameteri/3} . -%% -%% `?GL_TEXTURE_COMPARE_FUNC': Returns a single-valued texture comparison function, -%% a symbolic constant. The initial value is `?GL_LEQUAL'. See {@link gl:samplerParameteri/3} -%% . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSamplerParameter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetSamplerParameter.xhtml">external</a> documentation. -spec getSamplerParameteriv(Sampler, Pname) -> [integer()] when Sampler :: integer(),Pname :: enum(). getSamplerParameteriv(Sampler,Pname) -> call(5720, <<Sampler:?GLuint,Pname:?GLenum>>). @@ -14895,7 +6996,7 @@ getSamplerParameterfv(Sampler,Pname) -> %% @doc glGetSamplerParameterI %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSamplerParameterI.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getSamplerParameterIuiv(Sampler, Pname) -> [integer()] when Sampler :: integer(),Pname :: enum(). getSamplerParameterIuiv(Sampler,Pname) -> call(5723, <<Sampler:?GLuint,Pname:?GLenum>>). @@ -14910,21 +7011,21 @@ getSamplerParameterIuiv(Sampler,Pname) -> %% block where the target is `?GL_TIME_ELAPSED' and it does not affect the result of %% that query object. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glQueryCounter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glQueryCounter.xhtml">external</a> documentation. -spec queryCounter(Id, Target) -> 'ok' when Id :: integer(),Target :: enum(). queryCounter(Id,Target) -> cast(5724, <<Id:?GLuint,Target:?GLenum>>). %% @doc glGetQueryObjecti64v %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryObjecti64v.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getQueryObjecti64v(Id, Pname) -> integer() when Id :: integer(),Pname :: enum(). getQueryObjecti64v(Id,Pname) -> call(5725, <<Id:?GLuint,Pname:?GLenum>>). %% @doc glGetQueryObjectui64v %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryObjectui64v.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getQueryObjectui64v(Id, Pname) -> integer() when Id :: integer(),Pname :: enum(). getQueryObjectui64v(Id,Pname) -> call(5726, <<Id:?GLuint,Pname:?GLenum>>). @@ -14936,25 +7037,7 @@ getQueryObjectui64v(Id,Pname) -> %% , execept that the parameters to {@link gl:drawArraysInstancedBaseInstance/5} are stored %% in memory at the address given by `Indirect' . %% -%% The parameters addressed by `Indirect' are packed into a structure that takes the -%% form (in C): typedef struct { uint count; uint primCount; uint first; uint baseInstance; -%% } DrawArraysIndirectCommand; const DrawArraysIndirectCommand *cmd = (const DrawArraysIndirectCommand -%% *)indirect; glDrawArraysInstancedBaseInstance(mode, cmd->first, cmd->count, cmd->primCount, -%% cmd->baseInstance); -%% -%% If a buffer is bound to the `?GL_DRAW_INDIRECT_BUFFER' binding at the time of a -%% call to ``gl:drawArraysIndirect'', `Indirect' is interpreted as an offset, in basic -%% machine units, into that buffer and the parameter data is read from the buffer rather -%% than from client memory. -%% -%% In contrast to {@link gl:drawArraysInstancedBaseInstance/5} , the first member of the parameter -%% structure is unsigned, and out-of-range indices do not generate an error. -%% -%% Vertex attributes that are modified by ``gl:drawArraysIndirect'' have an unspecified -%% value after ``gl:drawArraysIndirect'' returns. Attributes that aren't modified remain -%% well defined. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawArraysIndirect.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawArraysIndirect.xhtml">external</a> documentation. -spec drawArraysIndirect(Mode, Indirect) -> 'ok' when Mode :: enum(),Indirect :: offset()|mem(). drawArraysIndirect(Mode,Indirect) when is_integer(Indirect) -> cast(5727, <<Mode:?GLenum,Indirect:?GLuint>>); @@ -14969,32 +7052,7 @@ drawArraysIndirect(Mode,Indirect) -> %% , execpt that the parameters to {@link gl:drawElementsInstancedBaseVertexBaseInstance/7} %% are stored in memory at the address given by `Indirect' . %% -%% The parameters addressed by `Indirect' are packed into a structure that takes the -%% form (in C): typedef struct { uint count; uint primCount; uint firstIndex; uint baseVertex; -%% uint baseInstance; } DrawElementsIndirectCommand; -%% -%% ``gl:drawElementsIndirect'' is equivalent to: void glDrawElementsIndirect(GLenum mode, -%% GLenum type, const void * indirect) { const DrawElementsIndirectCommand *cmd = (const -%% DrawElementsIndirectCommand *)indirect; glDrawElementsInstancedBaseVertexBaseInstance(mode, -%% cmd->count, type, cmd->firstIndex + size-of-type, cmd->primCount, cmd->baseVertex, -%% cmd->baseInstance); } -%% -%% If a buffer is bound to the `?GL_DRAW_INDIRECT_BUFFER' binding at the time of a -%% call to ``gl:drawElementsIndirect'', `Indirect' is interpreted as an offset, in -%% basic machine units, into that buffer and the parameter data is read from the buffer rather -%% than from client memory. -%% -%% Note that indices stored in client memory are not supported. If no buffer is bound to -%% the `?GL_ELEMENT_ARRAY_BUFFER' binding, an error will be generated. -%% -%% The results of the operation are undefined if the reservedMustBeZero member of the parameter -%% structure is non-zero. However, no error is generated in this case. -%% -%% Vertex attributes that are modified by ``gl:drawElementsIndirect'' have an unspecified -%% value after ``gl:drawElementsIndirect'' returns. Attributes that aren't modified remain -%% well defined. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsIndirect.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElementsIndirect.xhtml">external</a> documentation. -spec drawElementsIndirect(Mode, Type, Indirect) -> 'ok' when Mode :: enum(),Type :: enum(),Indirect :: offset()|mem(). drawElementsIndirect(Mode,Type,Indirect) when is_integer(Indirect) -> cast(5729, <<Mode:?GLenum,Type:?GLenum,Indirect:?GLuint>>); @@ -15142,15 +7200,7 @@ getUniformdv(Program,Location) -> %% `Name' in the shader stage of type `Shadertype' attached to `Program' , %% with behavior otherwise identical to {@link gl:getUniformLocation/2} . %% -%% If `Name' is not the name of a subroutine uniform in the shader stage, -1 is returned, -%% but no error is generated. If `Name' is the name of a subroutine uniform in the shader -%% stage, a value between zero and the value of `?GL_ACTIVE_SUBROUTINE_LOCATIONS' minus -%% one will be returned. Subroutine locations are assigned using consecutive integers in -%% the range from zero to the value of `?GL_ACTIVE_SUBROUTINE_LOCATIONS' minus one for -%% the shader stage. For active subroutine uniforms declared as arrays, the declared array -%% elements are assigned consecutive locations. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSubroutineUniformLocation.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetSubroutineUniformLocation.xhtml">external</a> documentation. -spec getSubroutineUniformLocation(Program, Shadertype, Name) -> integer() when Program :: integer(),Shadertype :: enum(),Name :: string(). getSubroutineUniformLocation(Program,Shadertype,Name) -> NameLen = length(Name), @@ -15164,14 +7214,7 @@ getSubroutineUniformLocation(Program,Shadertype,Name) -> %% shader subroutine index. `Name' contains the null-terminated name of the subroutine %% uniform whose name to query. %% -%% If `Name' is not the name of a subroutine uniform in the shader stage, `?GL_INVALID_INDEX' -%% is returned, but no error is generated. If `Name' is the name of a subroutine uniform -%% in the shader stage, a value between zero and the value of `?GL_ACTIVE_SUBROUTINES' -%% minus one will be returned. Subroutine indices are assigned using consecutive integers -%% in the range from zero to the value of `?GL_ACTIVE_SUBROUTINES' minus one for the -%% shader stage. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetSubroutineIndex.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetSubroutineIndex.xhtml">external</a> documentation. -spec getSubroutineIndex(Program, Shadertype, Name) -> integer() when Program :: integer(),Shadertype :: enum(),Name :: string(). getSubroutineIndex(Program,Shadertype,Name) -> NameLen = length(Name), @@ -15185,15 +7228,7 @@ getSubroutineIndex(Program,Shadertype,Name) -> %% `Index' must be between zero and the value of `?GL_ACTIVE_SUBROUTINE_UNIFORMS' %% minus one for the shader stage. %% -%% The uniform name is returned as a null-terminated string in `Name' . The actual number -%% of characters written into `Name' , excluding the null terminator is returned in `Length' -%% . If `Length' is `?NULL', no length is returned. The maximum number of characters -%% that may be written into `Name' , including the null terminator, is specified by `Bufsize' -%% . The length of the longest subroutine uniform name in `Program' and `Shadertype' -%% is given by the value of `?GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH', which can be -%% queried with {@link gl:getProgramStageiv/3} . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveSubroutineUniformName.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveSubroutineUniformName.xhtml">external</a> documentation. -spec getActiveSubroutineUniformName(Program, Shadertype, Index, Bufsize) -> string() when Program :: integer(),Shadertype :: enum(),Index :: integer(),Bufsize :: integer(). getActiveSubroutineUniformName(Program,Shadertype,Index,Bufsize) -> call(5751, <<Program:?GLuint,Shadertype:?GLenum,Index:?GLuint,Bufsize:?GLsizei>>). @@ -15205,13 +7240,7 @@ getActiveSubroutineUniformName(Program,Shadertype,Index,Bufsize) -> %% shader subroutine uniform within the shader stage given by `Stage' , and must between %% zero and the value of `?GL_ACTIVE_SUBROUTINES' minus one for the shader stage. %% -%% The name of the selected subroutine is returned as a null-terminated string in `Name' -%% . The actual number of characters written into `Name' , not including the null-terminator, -%% is is returned in `Length' . If `Length' is `?NULL', no length is returned. -%% The maximum number of characters that may be written into `Name' , including the null-terminator, -%% is given in `Bufsize' . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveSubroutineName.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetActiveSubroutineName.xhtml">external</a> documentation. -spec getActiveSubroutineName(Program, Shadertype, Index, Bufsize) -> string() when Program :: integer(),Shadertype :: enum(),Index :: integer(),Bufsize :: integer(). getActiveSubroutineName(Program,Shadertype,Index,Bufsize) -> call(5752, <<Program:?GLuint,Shadertype:?GLenum,Index:?GLuint,Bufsize:?GLsizei>>). @@ -15225,7 +7254,7 @@ getActiveSubroutineName(Program,Shadertype,Index,Bufsize) -> %% values in `Indices' must be less than the value of `?GL_ACTIVE_SUBROUTINES' %% for the shader stage. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUniformSubroutines.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUniformSubroutines.xhtml">external</a> documentation. -spec uniformSubroutinesuiv(Shadertype, Indices) -> 'ok' when Shadertype :: enum(),Indices :: [integer()]. uniformSubroutinesuiv(Shadertype,Indices) -> IndicesLen = length(Indices), @@ -15240,7 +7269,7 @@ uniformSubroutinesuiv(Shadertype,Indices) -> %% in use at shader stage `Shadertype' . The value of the subroutine uniform is returned %% in `Values' . %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetUniformSubroutine.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetUniformSubroutine.xhtml">external</a> documentation. -spec getUniformSubroutineuiv(Shadertype, Location) -> {integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer(),integer()} when Shadertype :: enum(),Location :: integer(). getUniformSubroutineuiv(Shadertype,Location) -> call(5754, <<Shadertype:?GLenum,Location:?GLint>>). @@ -15253,26 +7282,7 @@ getUniformSubroutineuiv(Shadertype,Location) -> %% should be queried. The value or values of the parameter to be queried is returned in the %% variable whose address is given in `Values' . %% -%% If `Pname' is `?GL_ACTIVE_SUBROUTINE_UNIFORMS', the number of active subroutine -%% variables in the stage is returned in `Values' . -%% -%% If `Pname' is `?GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS', the number of active -%% subroutine variable locations in the stage is returned in `Values' . -%% -%% If `Pname' is `?GL_ACTIVE_SUBROUTINES', the number of active subroutines in -%% the stage is returned in `Values' . -%% -%% If `Pname' is `?GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH', the length of the -%% longest subroutine uniform for the stage is returned in `Values' . -%% -%% If `Pname' is `?GL_ACTIVE_SUBROUTINE_MAX_LENGTH', the length of the longest -%% subroutine name for the stage is returned in `Values' . The returned name length includes -%% space for the null-terminator. -%% -%% If there is no shader present of type `Shadertype' , the returned value will be consistent -%% with a shader containing no subroutines or subroutine uniforms. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramStage.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetProgramStage.xhtml">external</a> documentation. -spec getProgramStageiv(Program, Shadertype, Pname) -> integer() when Program :: integer(),Shadertype :: enum(),Pname :: enum(). getProgramStageiv(Program,Shadertype,Pname) -> call(5755, <<Program:?GLuint,Shadertype:?GLenum,Pname:?GLenum>>). @@ -15286,20 +7296,7 @@ getProgramStageiv(Program,Shadertype,Pname) -> %% `Values' specifies the address of an array containing the new values for the parameter %% specified by `Pname' . %% -%% When `Pname' is `?GL_PATCH_VERTICES', `Value' specifies the number of -%% vertices that will be used to make up a single patch primitive. Patch primitives are consumed -%% by the tessellation control shader (if present) and subsequently used for tessellation. -%% When primitives are specified using {@link gl:drawArrays/3} or a similar function, each -%% patch will be made from `Parameter' control points, each represented by a vertex -%% taken from the enabeld vertex arrays. `Parameter' must be greater than zero, and -%% less than or equal to the value of `?GL_MAX_PATCH_VERTICES'. -%% -%% When `Pname' is `?GL_PATCH_DEFAULT_OUTER_LEVEL' or `?GL_PATCH_DEFAULT_INNER_LEVEL' -%% , `Values' contains the address of an array contiaining the default outer or inner -%% tessellation levels, respectively, to be used when no tessellation control shader is present. -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPatchParameter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPatchParameter.xhtml">external</a> documentation. -spec patchParameteri(Pname, Value) -> 'ok' when Pname :: enum(),Value :: integer(). patchParameteri(Pname,Value) -> cast(5756, <<Pname:?GLenum,Value:?GLint>>). @@ -15319,18 +7316,7 @@ patchParameterfv(Pname,Values) -> %% . If `Id' has not previously been bound, a new transform feedback object with name `Id' %% and initialized with with the default transform state vector is created. %% -%% In the initial state, a default transform feedback object is bound and treated as a transform -%% feedback object with a name of zero. If the name zero is subsequently bound, the default -%% transform feedback object is again bound to the GL state. -%% -%% While a transform feedback buffer object is bound, GL operations on the target to which -%% it is bound affect the bound transform feedback object, and queries of the target to which -%% a transform feedback object is bound return state from the bound object. When buffer objects -%% are bound for transform feedback, they are attached to the currently bound transform feedback -%% object. Buffer objects are used for trans- form feedback only if they are attached to -%% the currently bound transform feedback object. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindTransformFeedback.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindTransformFeedback.xhtml">external</a> documentation. -spec bindTransformFeedback(Target, Id) -> 'ok' when Target :: enum(),Id :: integer(). bindTransformFeedback(Target,Id) -> cast(5758, <<Target:?GLenum,Id:?GLuint>>). @@ -15343,7 +7329,7 @@ bindTransformFeedback(Target,Id) -> %% and it has no contents. If an active transform feedback object is deleted, its name immediately %% becomes unused, but the underlying object is not deleted until it is no longer active. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteTransformFeedbacks.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteTransformFeedbacks.xhtml">external</a> documentation. -spec deleteTransformFeedbacks(Ids) -> 'ok' when Ids :: [integer()]. deleteTransformFeedbacks(Ids) -> IdsLen = length(Ids), @@ -15356,7 +7342,7 @@ deleteTransformFeedbacks(Ids) -> %% names in `Ids' . These names are marked as used, for the purposes of ``gl:genTransformFeedbacks'' %% only, but they acquire transform feedback state only when they are first bound. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenTransformFeedbacks.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenTransformFeedbacks.xhtml">external</a> documentation. -spec genTransformFeedbacks(N) -> [integer()] when N :: integer(). genTransformFeedbacks(N) -> call(5760, <<N:?GLsizei>>). @@ -15371,7 +7357,7 @@ genTransformFeedbacks(N) -> %% the name is not a transform feedback object and ``gl:isTransformFeedback'' returns `?GL_FALSE' %% . %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsTransformFeedback.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsTransformFeedback.xhtml">external</a> documentation. -spec isTransformFeedback(Id) -> 0|1 when Id :: integer(). isTransformFeedback(Id) -> call(5761, <<Id:?GLuint>>). @@ -15384,7 +7370,7 @@ isTransformFeedback(Id) -> %% to the object results in an error. However, a new transform feedback object may be bound %% while transform feedback is paused. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glPauseTransformFeedback.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPauseTransformFeedback.xhtml">external</a> documentation. -spec pauseTransformFeedback() -> 'ok'. pauseTransformFeedback() -> cast(5762, <<>>). @@ -15397,7 +7383,7 @@ pauseTransformFeedback() -> %% to the object results in an error. However, a new transform feedback object may be bound %% while transform feedback is paused. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glResumeTransformFeedback.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glResumeTransformFeedback.xhtml">external</a> documentation. -spec resumeTransformFeedback() -> 'ok'. resumeTransformFeedback() -> cast(5763, <<>>). @@ -15411,7 +7397,7 @@ resumeTransformFeedback() -> %% zero the last time transform feedback was active on the transform feedback object named %% by `Id' . %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawTransformFeedback.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawTransformFeedback.xhtml">external</a> documentation. -spec drawTransformFeedback(Mode, Id) -> 'ok' when Mode :: enum(),Id :: integer(). drawTransformFeedback(Mode,Id) -> cast(5764, <<Mode:?GLenum,Id:?GLuint>>). @@ -15426,17 +7412,14 @@ drawTransformFeedback(Mode,Id) -> %% the last time transform feedback was active on the transform feedback object named by `Id' %% . %% -%% Calling {@link gl:drawTransformFeedback/2} is equivalent to calling ``gl:drawTransformFeedbackStream'' -%% with `Stream' set to zero. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawTransformFeedbackStream.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawTransformFeedbackStream.xhtml">external</a> documentation. -spec drawTransformFeedbackStream(Mode, Id, Stream) -> 'ok' when Mode :: enum(),Id :: integer(),Stream :: integer(). drawTransformFeedbackStream(Mode,Id,Stream) -> cast(5765, <<Mode:?GLenum,Id:?GLuint,Stream:?GLuint>>). %% @doc glBeginQueryIndexe %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginQueryIndexe.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec beginQueryIndexed(Target, Index, Id) -> 'ok' when Target :: enum(),Index :: integer(),Id :: integer(). beginQueryIndexed(Target,Index,Id) -> cast(5766, <<Target:?GLenum,Index:?GLuint,Id:?GLuint>>). @@ -15450,70 +7433,7 @@ beginQueryIndexed(Target,Index,Id) -> %% , `?GL_PRIMITIVES_GENERATED', `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN', or `?GL_TIME_ELAPSED' %% . The behavior of the query object depends on its type and is as follows. %% -%% `Index' specifies the index of the query target and must be between a `Target' -specific -%% maximum. -%% -%% If `Target' is `?GL_SAMPLES_PASSED', `Id' must be an unused name, or the -%% name of an existing occlusion query object. When ``gl:beginQueryIndexed'' is executed, -%% the query object's samples-passed counter is reset to 0. Subsequent rendering will increment -%% the counter for every sample that passes the depth test. If the value of `?GL_SAMPLE_BUFFERS' -%% is 0, then the samples-passed count is incremented by 1 for each fragment. If the value -%% of `?GL_SAMPLE_BUFFERS' is 1, then the samples-passed count is incremented by the -%% number of samples whose coverage bit is set. However, implementations, at their discression -%% may instead increase the samples-passed count by the value of `?GL_SAMPLES' if any -%% sample in the fragment is covered. When ``gl:endQueryIndexed'' is executed, the samples-passed -%% counter is assigned to the query object's result value. This value can be queried by calling -%% {@link gl:getQueryObjectiv/2} with `Pname' `?GL_QUERY_RESULT'. When `Target' -%% is `?GL_SAMPLES_PASSED', `Index' must be zero. -%% -%% If `Target' is `?GL_ANY_SAMPLES_PASSED', `Id' must be an unused name, -%% or the name of an existing boolean occlusion query object. When ``gl:beginQueryIndexed'' -%% is executed, the query object's samples-passed flag is reset to `?GL_FALSE'. Subsequent -%% rendering causes the flag to be set to `?GL_TRUE' if any sample passes the depth -%% test. When ``gl:endQueryIndexed'' is executed, the samples-passed flag is assigned to -%% the query object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2} -%% with `Pname' `?GL_QUERY_RESULT'. When `Target' is `?GL_ANY_SAMPLES_PASSED' -%% , `Index' must be zero. -%% -%% If `Target' is `?GL_PRIMITIVES_GENERATED', `Id' must be an unused name, -%% or the name of an existing primitive query object previously bound to the `?GL_PRIMITIVES_GENERATED' -%% query binding. When ``gl:beginQueryIndexed'' is executed, the query object's primitives-generated -%% counter is reset to 0. Subsequent rendering will increment the counter once for every -%% vertex that is emitted from the geometry shader to the stream given by `Index' , or -%% from the vertex shader if `Index' is zero and no geometry shader is present. When ``gl:endQueryIndexed'' -%% is executed, the primitives-generated counter for stream `Index' is assigned to -%% the query object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2} -%% with `Pname' `?GL_QUERY_RESULT'. When `Target' is `?GL_PRIMITIVES_GENERATED' -%% , `Index' must be less than the value of `?GL_MAX_VERTEX_STREAMS'. -%% -%% If `Target' is `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN', `Id' must -%% be an unused name, or the name of an existing primitive query object previously bound -%% to the `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN' query binding. When ``gl:beginQueryIndexed'' -%% is executed, the query object's primitives-written counter for the stream specified by `Index' -%% is reset to 0. Subsequent rendering will increment the counter once for every vertex -%% that is written into the bound transform feedback buffer(s) for stream `Index' . If -%% transform feedback mode is not activated between the call to ``gl:beginQueryIndexed'' -%% and ``gl:endQueryIndexed'', the counter will not be incremented. When ``gl:endQueryIndexed'' -%% is executed, the primitives-written counter for stream `Index' is assigned to the -%% query object's result value. This value can be queried by calling {@link gl:getQueryObjectiv/2} -%% with `Pname' `?GL_QUERY_RESULT'. When `Target' is `?GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN' -%% , `Index' must be less than the value of `?GL_MAX_VERTEX_STREAMS'. -%% -%% If `Target' is `?GL_TIME_ELAPSED', `Id' must be an unused name, or the -%% name of an existing timer query object previously bound to the `?GL_TIME_ELAPSED' -%% query binding. When ``gl:beginQueryIndexed'' is executed, the query object's time counter -%% is reset to 0. When ``gl:endQueryIndexed'' is executed, the elapsed server time that -%% has passed since the call to ``gl:beginQueryIndexed'' is written into the query object's -%% time counter. This value can be queried by calling {@link gl:getQueryObjectiv/2} with `Pname' -%% `?GL_QUERY_RESULT'. When `Target' is `?GL_TIME_ELAPSED', `Index' must -%% be zero. -%% -%% Querying the `?GL_QUERY_RESULT' implicitly flushes the GL pipeline until the rendering -%% delimited by the query object has completed and the result is available. `?GL_QUERY_RESULT_AVAILABLE' -%% can be queried to determine if the result is immediately available or if the rendering -%% is not yet complete. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBeginQueryIndexed.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBeginQueryIndexed.xhtml">external</a> documentation. -spec endQueryIndexed(Target, Index) -> 'ok' when Target :: enum(),Index :: integer(). endQueryIndexed(Target,Index) -> cast(5767, <<Target:?GLenum,Index:?GLuint>>). @@ -15525,13 +7445,7 @@ endQueryIndexed(Target,Index) -> %% the index of the query object target and must be between zero and a target-specific maxiumum. %% %% -%% `Pname' names a specific query object target parameter. When `Pname' is `?GL_CURRENT_QUERY' -%% , the name of the currently active query for the specified `Index' of `Target' , -%% or zero if no query is active, will be placed in `Params' . If `Pname' is `?GL_QUERY_COUNTER_BITS' -%% , the implementation-dependent number of bits used to hold the result of queries for `Target' -%% is returned in `Params' . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetQueryIndexed.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetQueryIndexed.xhtml">external</a> documentation. -spec getQueryIndexediv(Target, Index, Pname) -> integer() when Target :: enum(),Index :: integer(),Pname :: enum(). getQueryIndexediv(Target,Index,Pname) -> call(5768, <<Target:?GLenum,Index:?GLuint,Pname:?GLenum>>). @@ -15543,7 +7457,7 @@ getQueryIndexediv(Target,Index,Pname) -> %% subsequently be called and the implementation may at that time reallocate resources previously %% freed by the call to ``gl:releaseShaderCompiler''. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glReleaseShaderCompiler.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glReleaseShaderCompiler.xhtml">external</a> documentation. -spec releaseShaderCompiler() -> 'ok'. releaseShaderCompiler() -> cast(5769, <<>>). @@ -15555,17 +7469,7 @@ releaseShaderCompiler() -> %% bytes of binary shader code stored in client memory. `BinaryFormat' specifies the %% format of the pre-compiled code. %% -%% The binary image contained in `Binary' will be decoded according to the extension -%% specification defining the specified `BinaryFormat' token. OpenGL does not define -%% any specific binary formats, but it does provide a mechanism to obtain token vaues for -%% such formats provided by such extensions. -%% -%% Depending on the types of the shader objects in `Shaders' , ``gl:shaderBinary'' -%% will individually load binary vertex or fragment shaders, or load an executable binary -%% that contains an optimized pair of vertex and fragment shaders stored in the same binary. -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glShaderBinary.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glShaderBinary.xhtml">external</a> documentation. -spec shaderBinary(Shaders, Binaryformat, Binary) -> 'ok' when Shaders :: [integer()],Binaryformat :: enum(),Binary :: binary(). shaderBinary(Shaders,Binaryformat,Binary) -> ShadersLen = length(Shaders), @@ -15583,17 +7487,7 @@ shaderBinary(Shaders,Binaryformat,Binary) -> %% `?GL_HIGH_FLOAT', `?GL_LOW_INT', `?GL_MEDIUM_INT', or `?GL_HIGH_INT'. %% %% -%% `Range' points to an array of two integers into which the format's numeric range -%% will be returned. If min and max are the smallest values representable in the format, -%% then the values returned are defined to be: `Range' [0] = floor(log2(|min|)) and `Range' -%% [1] = floor(log2(|max|)). -%% -%% `Precision' specifies the address of an integer into which will be written the log2 -%% value of the number of bits of precision of the format. If the smallest representable -%% value greater than 1 is 1 + `eps', then the integer addressed by `Precision' -%% will contain floor(-log2(eps)). -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetShaderPrecisionFormat.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetShaderPrecisionFormat.xhtml">external</a> documentation. -spec getShaderPrecisionFormat(Shadertype, Precisiontype) -> {Range :: {integer(),integer()},Precision :: integer()} when Shadertype :: enum(),Precisiontype :: enum(). getShaderPrecisionFormat(Shadertype,Precisiontype) -> call(5771, <<Shadertype:?GLenum,Precisiontype:?GLenum>>). @@ -15606,7 +7500,7 @@ depthRangef(N,F) -> %% @doc glClearDepthf %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glClearDepthf.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec clearDepthf(D) -> 'ok' when D :: clamp(). clearDepthf(D) -> cast(5773, <<D:?GLclampf>>). @@ -15621,13 +7515,7 @@ clearDepthf(D) -> %% in the variable whose address is given by `Length' . If `Length' is `?NULL', %% then no length is returned. %% -%% The format of the program binary written into `Binary' is returned in the variable -%% whose address is given by `BinaryFormat' , and may be implementation dependent. The -%% binary produced by the GL may subsequently be returned to the GL by calling {@link gl:programBinary/3} -%% , with `BinaryFormat' and `Length' set to the values returned by ``gl:getProgramBinary'' -%% , and passing the returned binary data in the `Binary' parameter. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramBinary.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetProgramBinary.xhtml">external</a> documentation. -spec getProgramBinary(Program, BufSize) -> {BinaryFormat :: enum(),Binary :: binary()} when Program :: integer(),BufSize :: integer(). getProgramBinary(Program,BufSize) -> call(5774, <<Program:?GLuint,BufSize:?GLsizei>>). @@ -15642,19 +7530,7 @@ getProgramBinary(Program,BufSize) -> %% are not met, loading the program binary will fail and `Program' 's `?GL_LINK_STATUS' %% will be set to `?GL_FALSE'. %% -%% A program object's program binary is replaced by calls to {@link gl:linkProgram/1} or ``gl:programBinary'' -%% . When linking success or failure is concerned, ``gl:programBinary'' can be considered -%% to perform an implicit linking operation. {@link gl:linkProgram/1} and ``gl:programBinary'' -%% both set the program object's `?GL_LINK_STATUS' to `?GL_TRUE' or `?GL_FALSE' -%% . -%% -%% A successful call to ``gl:programBinary'' will reset all uniform variables to their -%% initial values. The initial value is either the value of the variable's initializer as -%% specified in the original shader source, or zero if no initializer was present. Additionally, -%% all vertex shader input and fragment shader output assignments that were in effect when -%% the program was linked before saving are restored with ``gl:programBinary'' is called. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramBinary.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glProgramBinary.xhtml">external</a> documentation. -spec programBinary(Program, BinaryFormat, Binary) -> 'ok' when Program :: integer(),BinaryFormat :: enum(),Binary :: binary(). programBinary(Program,BinaryFormat,Binary) -> send_bin(Binary), @@ -15665,22 +7541,7 @@ programBinary(Program,BinaryFormat,Binary) -> %% ``gl:programParameter'' specifies a new value for the parameter nameed by `Pname' %% for the program object `Program' . %% -%% If `Pname' is `?GL_PROGRAM_BINARY_RETRIEVABLE_HINT', `Value' should be `?GL_FALSE' -%% or `?GL_TRUE' to indicate to the implementation the intention of the application -%% to retrieve the program's binary representation with {@link gl:getProgramBinary/2} . The -%% implementation may use this information to store information that may be useful for a -%% future query of the program's binary. It is recommended to set `?GL_PROGRAM_BINARY_RETRIEVABLE_HINT' -%% for the program to `?GL_TRUE' before calling {@link gl:linkProgram/1} , and using -%% the program at run-time if the binary is to be retrieved later. -%% -%% If `Pname' is `?GL_PROGRAM_SEPARABLE', `Value' must be `?GL_TRUE' -%% or `?GL_FALSE' and indicates whether `Program' can be bound to individual pipeline -%% stages via {@link gl:useProgramStages/3} . A program's `?GL_PROGRAM_SEPARABLE' parameter -%% must be set to `?GL_TRUE'`before' {@link gl:linkProgram/1} is called in order -%% for it to be usable with a program pipeline object. The initial state of `?GL_PROGRAM_SEPARABLE' -%% is `?GL_FALSE'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramParameter.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glProgramParameter.xhtml">external</a> documentation. -spec programParameteri(Program, Pname, Value) -> 'ok' when Program :: integer(),Pname :: enum(),Value :: integer(). programParameteri(Program,Pname,Value) -> cast(5776, <<Program:?GLuint,Pname:?GLenum,Value:?GLint>>). @@ -15697,15 +7558,7 @@ programParameteri(Program,Pname,Value) -> %% special value `?GL_ALL_SHADER_BITS' may be specified to indicate that all executables %% contained in `Program' should be installed in `Pipeline' . %% -%% If `Program' refers to a program object with a valid shader attached for an indicated -%% shader stage, ``gl:useProgramStages'' installs the executable code for that stage in -%% the indicated program pipeline object `Pipeline' . If `Program' is zero, or refers -%% to a program object with no valid shader executable for a given stage, it is as if the -%% pipeline object has no programmable stage configured for the indicated shader stages. If `Stages' -%% contains bits other than those listed above, and is not equal to `?GL_ALL_SHADER_BITS' -%% , an error is generated. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glUseProgramStages.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUseProgramStages.xhtml">external</a> documentation. -spec useProgramStages(Pipeline, Stages, Program) -> 'ok' when Pipeline :: integer(),Stages :: integer(),Program :: integer(). useProgramStages(Pipeline,Stages,Program) -> cast(5777, <<Pipeline:?GLuint,Stages:?GLbitfield,Program:?GLuint>>). @@ -15717,14 +7570,14 @@ useProgramStages(Pipeline,Stages,Program) -> %% the active program pipeline object is the target of calls to {@link gl:uniform1f/2} when %% no program has been made current through a call to {@link gl:useProgram/1} . %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glActiveShaderProgram.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glActiveShaderProgram.xhtml">external</a> documentation. -spec activeShaderProgram(Pipeline, Program) -> 'ok' when Pipeline :: integer(),Program :: integer(). activeShaderProgram(Pipeline,Program) -> cast(5778, <<Pipeline:?GLuint,Program:?GLuint>>). %% @doc glCreateShaderProgramv %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glCreateShaderProgramv.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec createShaderProgramv(Type, Strings) -> integer() when Type :: enum(),Strings :: iolist(). createShaderProgramv(Type,Strings) -> StringsTemp = list_to_binary([[Str|[0]] || Str <- Strings ]), @@ -15738,17 +7591,7 @@ createShaderProgramv(Type,Strings) -> %% no program pipeline exists with name `Pipeline' then a new pipeline object is created %% with that name and initialized to the default state vector. %% -%% When a program pipeline object is bound using ``gl:bindProgramPipeline'', any previous -%% binding is broken and is replaced with a binding to the specified pipeline object. If `Pipeline' -%% is zero, the previous binding is broken and is not replaced, leaving no pipeline object -%% bound. If no current program object has been established by {@link gl:useProgram/1} , the -%% program objects used for each stage and for uniform updates are taken from the bound program -%% pipeline object, if any. If there is a current program object established by {@link gl:useProgram/1} -%% , the bound program pipeline object has no effect on rendering or uniform updates. When -%% a bound program pipeline object is used for rendering, individual shader executables are -%% taken from its program objects. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindProgramPipeline.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindProgramPipeline.xhtml">external</a> documentation. -spec bindProgramPipeline(Pipeline) -> 'ok' when Pipeline :: integer(). bindProgramPipeline(Pipeline) -> cast(5780, <<Pipeline:?GLuint>>). @@ -15762,7 +7605,7 @@ bindProgramPipeline(Pipeline) -> %% the binding for that object reverts to zero and no program pipeline object becomes current. %% %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDeleteProgramPipelines.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDeleteProgramPipelines.xhtml">external</a> documentation. -spec deleteProgramPipelines(Pipelines) -> 'ok' when Pipelines :: [integer()]. deleteProgramPipelines(Pipelines) -> PipelinesLen = length(Pipelines), @@ -15775,7 +7618,7 @@ deleteProgramPipelines(Pipelines) -> %% names in `Pipelines' . These names are marked as used, for the purposes of ``gl:genProgramPipelines'' %% only, but they acquire program pipeline state only when they are first bound. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGenProgramPipelines.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGenProgramPipelines.xhtml">external</a> documentation. -spec genProgramPipelines(N) -> [integer()] when N :: integer(). genProgramPipelines(N) -> call(5782, <<N:?GLsizei>>). @@ -15790,7 +7633,7 @@ genProgramPipelines(N) -> %% the name is not a program pipeline object and ``gl:isProgramPipeline'' returns `?GL_FALSE' %% . %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glIsProgramPipeline.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glIsProgramPipeline.xhtml">external</a> documentation. -spec isProgramPipeline(Pipeline) -> 0|1 when Pipeline :: integer(). isProgramPipeline(Pipeline) -> call(5783, <<Pipeline:?GLuint>>). @@ -15802,33 +7645,7 @@ isProgramPipeline(Pipeline) -> %% retrieve. The value of the parameter is written to the variable whose address is given %% by `Params' . %% -%% If `Pname' is `?GL_ACTIVE_PROGRAM', the name of the active program object of -%% the program pipeline object is returned in `Params' . -%% -%% If `Pname' is `?GL_VERTEX_SHADER', the name of the current program object for -%% the vertex shader type of the program pipeline object is returned in `Params' . -%% -%% If `Pname' is `?GL_TESS_CONTROL_SHADER', the name of the current program object -%% for the tessellation control shader type of the program pipeline object is returned in `Params' -%% . -%% -%% If `Pname' is `?GL_TESS_EVALUATION_SHADER', the name of the current program -%% object for the tessellation evaluation shader type of the program pipeline object is returned -%% in `Params' . -%% -%% If `Pname' is `?GL_GEOMETRY_SHADER', the name of the current program object -%% for the geometry shader type of the program pipeline object is returned in `Params' . -%% -%% -%% If `Pname' is `?GL_FRAGMENT_SHADER', the name of the current program object -%% for the fragment shader type of the program pipeline object is returned in `Params' . -%% -%% -%% If `Pname' is `?GL_INFO_LOG_LENGTH', the length of the info log, including -%% the null terminator, is returned in `Params' . If there is no info log, zero is returned. -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramPipeline.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetProgramPipeline.xhtml">external</a> documentation. -spec getProgramPipelineiv(Pipeline, Pname) -> integer() when Pipeline :: integer(),Pname :: enum(). getProgramPipelineiv(Pipeline,Pname) -> call(5784, <<Pipeline:?GLuint,Pname:?GLenum>>). @@ -15840,62 +7657,7 @@ getProgramPipelineiv(Pipeline,Pname) -> %% which should be a value returned by {@link gl:getUniformLocation/2} . ``gl:programUniform'' %% operates on the program object specified by `Program' . %% -%% The commands ``gl:programUniform{1|2|3|4}{f|i|ui}'' are used to change the value of -%% the uniform variable specified by `Location' using the values passed as arguments. -%% The number specified in the command should match the number of components in the data -%% type of the specified uniform variable (e.g., `1' for float, int, unsigned int, bool; -%% `2' for vec2, ivec2, uvec2, bvec2, etc.). The suffix `f' indicates that floating-point -%% values are being passed; the suffix `i' indicates that integer values are being passed; -%% the suffix `ui' indicates that unsigned integer values are being passed, and this -%% type should also match the data type of the specified uniform variable. The `i' variants -%% of this function should be used to provide values for uniform variables defined as int, ivec2 -%% , ivec3, ivec4, or arrays of these. The `ui' variants of this function should be -%% used to provide values for uniform variables defined as unsigned int, uvec2, uvec3, uvec4, -%% or arrays of these. The `f' variants should be used to provide values for uniform -%% variables of type float, vec2, vec3, vec4, or arrays of these. Either the `i', `ui' -%% or `f' variants may be used to provide values for uniform variables of type bool, bvec2 -%% , bvec3, bvec4, or arrays of these. The uniform variable will be set to false if the input -%% value is 0 or 0.0f, and it will be set to true otherwise. -%% -%% All active uniform variables defined in a program object are initialized to 0 when the -%% program object is linked successfully. They retain the values assigned to them by a call -%% to ``gl:programUniform'' until the next successful link operation occurs on the program -%% object, when they are once again initialized to 0. -%% -%% The commands ``gl:programUniform{1|2|3|4}{f|i|ui}v'' can be used to modify a single -%% uniform variable or a uniform variable array. These commands pass a count and a pointer -%% to the values to be loaded into a uniform variable or a uniform variable array. A count -%% of 1 should be used if modifying the value of a single uniform variable, and a count of -%% 1 or greater can be used to modify an entire array or part of an array. When loading `n' -%% elements starting at an arbitrary position `m' in a uniform variable array, elements -%% `m' + `n' - 1 in the array will be replaced with the new values. If `M' + `N' -%% - 1 is larger than the size of the uniform variable array, values for all array elements -%% beyond the end of the array will be ignored. The number specified in the name of the command -%% indicates the number of components for each element in `Value' , and it should match -%% the number of components in the data type of the specified uniform variable (e.g., `1' -%% for float, int, bool; `2' for vec2, ivec2, bvec2, etc.). The data type specified -%% in the name of the command must match the data type for the specified uniform variable -%% as described previously for ``gl:programUniform{1|2|3|4}{f|i|ui}''. -%% -%% For uniform variable arrays, each element of the array is considered to be of the type -%% indicated in the name of the command (e.g., ``gl:programUniform3f'' or ``gl:programUniform3fv'' -%% can be used to load a uniform variable array of type vec3). The number of elements of -%% the uniform variable array to be modified is specified by `Count' -%% -%% The commands ``gl:programUniformMatrix{2|3|4|2x3|3x2|2x4|4x2|3x4|4x3}fv'' are used -%% to modify a matrix or an array of matrices. The numbers in the command name are interpreted -%% as the dimensionality of the matrix. The number `2' indicates a 2 × 2 matrix (i.e., -%% 4 values), the number `3' indicates a 3 × 3 matrix (i.e., 9 values), and the number `4' -%% indicates a 4 × 4 matrix (i.e., 16 values). Non-square matrix dimensionality is explicit, -%% with the first number representing the number of columns and the second number representing -%% the number of rows. For example, `2x4' indicates a 2 × 4 matrix with 2 columns and -%% 4 rows (i.e., 8 values). If `Transpose' is `?GL_FALSE', each matrix is assumed -%% to be supplied in column major order. If `Transpose' is `?GL_TRUE', each matrix -%% is assumed to be supplied in row major order. The `Count' argument indicates the -%% number of matrices to be passed. A count of 1 should be used if modifying the value of -%% a single matrix, and a count greater than 1 can be used to modify an array of matrices. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glProgramUniform.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glProgramUniform.xhtml">external</a> documentation. -spec programUniform1i(Program, Location, V0) -> 'ok' when Program :: integer(),Location :: integer(),V0 :: integer(). programUniform1i(Program,Location,V0) -> cast(5785, <<Program:?GLuint,Location:?GLint,V0:?GLint>>). @@ -16269,15 +8031,7 @@ programUniformMatrix4x3dv(Program,Location,Transpose,Value) -> %% this as an opportunity to perform any internal shader modifications that may be required %% to ensure correct operation of the installed shaders given the current GL state. %% -%% After a program pipeline has been validated, its validation status is set to `?GL_TRUE' -%% . The validation status of a program pipeline object may be queried by calling {@link gl:getProgramPipelineiv/2} -%% with parameter `?GL_VALIDATE_STATUS'. -%% -%% If `Pipeline' is a name previously returned from a call to {@link gl:genProgramPipelines/1} -%% but that has not yet been bound by a call to {@link gl:bindProgramPipeline/1} , a new program -%% pipeline object is created with name `Pipeline' and the default state vector. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glValidateProgramPipeline.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glValidateProgramPipeline.xhtml">external</a> documentation. -spec validateProgramPipeline(Pipeline) -> 'ok' when Pipeline :: integer(). validateProgramPipeline(Pipeline) -> cast(5835, <<Pipeline:?GLuint>>). @@ -16291,38 +8045,35 @@ validateProgramPipeline(Pipeline) -> %% of characters written into `InfoLog' is returned in the integer whose address is %% given by `Length' . If `Length' is `?NULL', no length is returned. %% -%% The actual length of the info log for the program pipeline may be determined by calling {@link gl:getProgramPipelineiv/2} -%% with `Pname' set to `?GL_INFO_LOG_LENGTH'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetProgramPipelineInfoLog.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetProgramPipelineInfoLog.xhtml">external</a> documentation. -spec getProgramPipelineInfoLog(Pipeline, BufSize) -> string() when Pipeline :: integer(),BufSize :: integer(). getProgramPipelineInfoLog(Pipeline,BufSize) -> call(5836, <<Pipeline:?GLuint,BufSize:?GLsizei>>). %% @doc glVertexAttribL %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribL.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec vertexAttribL1d(Index, X) -> 'ok' when Index :: integer(),X :: float(). vertexAttribL1d(Index,X) -> cast(5837, <<Index:?GLuint,0:32,X:?GLdouble>>). %% @doc glVertexAttribL %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribL.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec vertexAttribL2d(Index, X, Y) -> 'ok' when Index :: integer(),X :: float(),Y :: float(). vertexAttribL2d(Index,X,Y) -> cast(5838, <<Index:?GLuint,0:32,X:?GLdouble,Y:?GLdouble>>). %% @doc glVertexAttribL %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribL.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec vertexAttribL3d(Index, X, Y, Z) -> 'ok' when Index :: integer(),X :: float(),Y :: float(),Z :: float(). vertexAttribL3d(Index,X,Y,Z) -> cast(5839, <<Index:?GLuint,0:32,X:?GLdouble,Y:?GLdouble,Z:?GLdouble>>). %% @doc glVertexAttribL %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribL.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec vertexAttribL4d(Index, X, Y, Z, W) -> 'ok' when Index :: integer(),X :: float(),Y :: float(),Z :: float(),W :: float(). vertexAttribL4d(Index,X,Y,Z,W) -> cast(5840, <<Index:?GLuint,0:32,X:?GLdouble,Y:?GLdouble,Z:?GLdouble,W:?GLdouble>>). @@ -16345,7 +8096,7 @@ vertexAttribL4dv(Index,{X,Y,Z,W}) -> vertexAttribL4d(Index,X,Y,Z,W). %% @doc glVertexAttribLPointer %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribLPointer.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec vertexAttribLPointer(Index, Size, Type, Stride, Pointer) -> 'ok' when Index :: integer(),Size :: integer(),Type :: enum(),Stride :: integer(),Pointer :: offset()|mem(). vertexAttribLPointer(Index,Size,Type,Stride,Pointer) when is_integer(Pointer) -> cast(5841, <<Index:?GLuint,Size:?GLint,Type:?GLenum,Stride:?GLsizei,Pointer:?GLuint>>); @@ -16355,14 +8106,14 @@ vertexAttribLPointer(Index,Size,Type,Stride,Pointer) -> %% @doc glGetVertexAttribL %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetVertexAttribL.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getVertexAttribLdv(Index, Pname) -> {float(),float(),float(),float()} when Index :: integer(),Pname :: enum(). getVertexAttribLdv(Index,Pname) -> call(5843, <<Index:?GLuint,Pname:?GLenum>>). %% @doc glViewportArrayv %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glViewportArrayv.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec viewportArrayv(First, V) -> 'ok' when First :: integer(),V :: [{float(),float(),float(),float()}]. viewportArrayv(First,V) -> VLen = length(V), @@ -16383,27 +8134,7 @@ viewportArrayv(First,V) -> %% coordinates to window coordinates. Let (x nd y nd) be normalized device coordinates. Then the window %% coordinates (x w y w) are computed as follows: %% -%% x w=(x nd+1) (width/2)+x -%% -%% y w=(y nd+1) (height/2)+y -%% -%% The location of the viewport's bottom left corner, given by ( x, y) is clamped to be -%% within the implementaiton-dependent viewport bounds range. The viewport bounds range [ -%% min, max] can be determined by calling {@link gl:getBooleanv/1} with argument `?GL_VIEWPORT_BOUNDS_RANGE' -%% . Viewport width and height are silently clamped to a range that depends on the implementation. -%% To query this range, call {@link gl:getBooleanv/1} with argument `?GL_MAX_VIEWPORT_DIMS'. -%% -%% The precision with which the GL interprets the floating point viewport bounds is implementation-dependent -%% and may be determined by querying the impementation-defined constant `?GL_VIEWPORT_SUBPIXEL_BITS' -%% . -%% -%% Calling ``gl:viewportIndexedfv'' is equivalent to calling see `glViewportArray' -%% with `First' set to `Index' , `Count' set to 1 and `V' passsed directly. -%% ``gl:viewportIndexedf'' is equivalent to: void glViewportIndexedf(GLuint index, GLfloat -%% x, GLfloat y, GLfloat w, GLfloat h) { const float v[4] = { x, y, w, h }; glViewportArrayv(index, -%% 1, v); } -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glViewportIndexed.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glViewportIndexed.xhtml">external</a> documentation. -spec viewportIndexedf(Index, X, Y, W, H) -> 'ok' when Index :: integer(),X :: float(),Y :: float(),W :: float(),H :: float(). viewportIndexedf(Index,X,Y,W,H) -> cast(5845, <<Index:?GLuint,X:?GLfloat,Y:?GLfloat,W:?GLfloat,H:?GLfloat>>). @@ -16416,7 +8147,7 @@ viewportIndexedfv(Index,{V1,V2,V3,V4}) -> %% @doc glScissorArrayv %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScissorArrayv.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec scissorArrayv(First, V) -> 'ok' when First :: integer(),V :: [{integer(),integer(),integer(),integer()}]. scissorArrayv(First,V) -> VLen = length(V), @@ -16425,21 +8156,21 @@ scissorArrayv(First,V) -> %% @doc glScissorIndexe %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScissorIndexe.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec scissorIndexed(Index, Left, Bottom, Width, Height) -> 'ok' when Index :: integer(),Left :: integer(),Bottom :: integer(),Width :: integer(),Height :: integer(). scissorIndexed(Index,Left,Bottom,Width,Height) -> cast(5848, <<Index:?GLuint,Left:?GLint,Bottom:?GLint,Width:?GLsizei,Height:?GLsizei>>). %% @doc glScissorIndexe %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glScissorIndexe.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec scissorIndexedv(Index, V) -> 'ok' when Index :: integer(),V :: {integer(),integer(),integer(),integer()}. scissorIndexedv(Index,{V1,V2,V3,V4}) -> cast(5849, <<Index:?GLuint,V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>>). %% @doc glDepthRangeArrayv %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthRangeArrayv.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec depthRangeArrayv(First, V) -> 'ok' when First :: integer(),V :: [{clamp(),clamp()}]. depthRangeArrayv(First,V) -> VLen = length(V), @@ -16448,7 +8179,7 @@ depthRangeArrayv(First,V) -> %% @doc glDepthRangeIndexe %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthRangeIndexe.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec depthRangeIndexed(Index, N, F) -> 'ok' when Index :: integer(),N :: clamp(),F :: clamp(). depthRangeIndexed(Index,N,F) -> cast(5851, <<Index:?GLuint,0:32,N:?GLclampd,F:?GLclampd>>). @@ -16467,7 +8198,7 @@ getDoublei_v(Target,Index) -> %% @doc glDebugMessageControlARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDebugMessageControlARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec debugMessageControlARB(Source, Type, Severity, Ids, Enabled) -> 'ok' when Source :: enum(),Type :: enum(),Severity :: enum(),Ids :: [integer()],Enabled :: 0|1. debugMessageControlARB(Source,Type,Severity,Ids,Enabled) -> IdsLen = length(Ids), @@ -16476,7 +8207,7 @@ debugMessageControlARB(Source,Type,Severity,Ids,Enabled) -> %% @doc glDebugMessageInsertARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDebugMessageInsertARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec debugMessageInsertARB(Source, Type, Id, Severity, Buf) -> 'ok' when Source :: enum(),Type :: enum(),Id :: integer(),Severity :: enum(),Buf :: string(). debugMessageInsertARB(Source,Type,Id,Severity,Buf) -> BufLen = length(Buf), @@ -16484,14 +8215,14 @@ debugMessageInsertARB(Source,Type,Id,Severity,Buf) -> %% @doc glGetDebugMessageLogARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetDebugMessageLogARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getDebugMessageLogARB(Count, Bufsize) -> {integer(),Sources :: [enum()],Types :: [enum()],Ids :: [integer()],Severities :: [enum()],MessageLog :: [string()]} when Count :: integer(),Bufsize :: integer(). getDebugMessageLogARB(Count,Bufsize) -> call(5856, <<Count:?GLuint,Bufsize:?GLsizei>>). %% @doc glGetGraphicsResetStatusARB %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetGraphicsResetStatusARB.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getGraphicsResetStatusARB() -> enum(). getGraphicsResetStatusARB() -> call(5857, <<>>). @@ -16504,17 +8235,7 @@ getGraphicsResetStatusARB() -> %% is an internal 32-bit integer counter that may be read by a vertex shader as `?gl_InstanceID' %% . %% -%% ``gl:drawArraysInstancedBaseInstance'' has the same effect as: if ( mode or count is -%% invalid ) generate appropriate error else { for (int i = 0; i < primcount ; i++) { -%% instanceID = i; glDrawArrays(mode, first, count); } instanceID = 0; } -%% -%% Specific vertex attributes may be classified as `instanced' through the use of {@link gl:vertexAttribDivisor/2} -%% . Instanced vertex attributes supply per-instance vertex data to the vertex shader. The -%% index of the vertex fetched from the enabled instanced vertex attribute arrays is calculated -%% as: |gl_ InstanceID/divisor|&plus; baseInstance. Note that `Baseinstance' does not affect the shader-visible -%% value of `?gl_InstanceID'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawArraysInstancedBaseInstance.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawArraysInstancedBaseInstance.xhtml">external</a> documentation. -spec drawArraysInstancedBaseInstance(Mode, First, Count, Primcount, Baseinstance) -> 'ok' when Mode :: enum(),First :: integer(),Count :: integer(),Primcount :: integer(),Baseinstance :: integer(). drawArraysInstancedBaseInstance(Mode,First,Count,Primcount,Baseinstance) -> cast(5858, <<Mode:?GLenum,First:?GLint,Count:?GLsizei,Primcount:?GLsizei,Baseinstance:?GLuint>>). @@ -16527,17 +8248,7 @@ drawArraysInstancedBaseInstance(Mode,First,Count,Primcount,Baseinstance) -> %% is an internal 32-bit integer counter that may be read by a vertex shader as `?gl_InstanceID' %% . %% -%% ``gl:drawElementsInstancedBaseInstance'' has the same effect as: if (mode, count, or -%% type is invalid ) generate appropriate error else { for (int i = 0; i < primcount ; -%% i++) { instanceID = i; glDrawElements(mode, count, type, indices); } instanceID = 0; } -%% -%% Specific vertex attributes may be classified as `instanced' through the use of {@link gl:vertexAttribDivisor/2} -%% . Instanced vertex attributes supply per-instance vertex data to the vertex shader. The -%% index of the vertex fetched from the enabled instanced vertex attribute arrays is calculated -%% as |gl_ InstanceID/divisor|&plus; baseInstance. Note that `Baseinstance' does not affect the shader-visible -%% value of `?gl_InstanceID'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsInstancedBaseInstance.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElementsInstancedBaseInstance.xhtml">external</a> documentation. -spec drawElementsInstancedBaseInstance(Mode, Count, Type, Indices, Primcount, Baseinstance) -> 'ok' when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Primcount :: integer(),Baseinstance :: integer(). drawElementsInstancedBaseInstance(Mode,Count,Type,Indices,Primcount,Baseinstance) when is_integer(Indices) -> cast(5859, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Primcount:?GLsizei,Baseinstance:?GLuint>>); @@ -16555,13 +8266,7 @@ drawElementsInstancedBaseInstance(Mode,Count,Type,Indices,Primcount,Baseinstance %% conditions). The operation is undefined if the sum would be negative. The `Basevertex' %% has no effect on the shader-visible value of `?gl_VertexID'. %% -%% Specific vertex attributes may be classified as `instanced' through the use of {@link gl:vertexAttribDivisor/2} -%% . Instanced vertex attributes supply per-instance vertex data to the vertex shader. The -%% index of the vertex fetched from the enabled instanced vertex attribute arrays is calculated -%% as |gl_ InstanceID/divisor|&plus; baseInstance. Note that `Baseinstance' does not affect the shader-visible -%% value of `?gl_InstanceID'. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawElementsInstancedBaseVertexBaseInstance.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDrawElementsInstancedBaseVertexBaseInstance.xhtml">external</a> documentation. -spec drawElementsInstancedBaseVertexBaseInstance(Mode, Count, Type, Indices, Primcount, Basevertex, Baseinstance) -> 'ok' when Mode :: enum(),Count :: integer(),Type :: enum(),Indices :: offset()|mem(),Primcount :: integer(),Basevertex :: integer(),Baseinstance :: integer(). drawElementsInstancedBaseVertexBaseInstance(Mode,Count,Type,Indices,Primcount,Basevertex,Baseinstance) when is_integer(Indices) -> cast(5861, <<Mode:?GLenum,Count:?GLsizei,Type:?GLenum,Indices:?GLuint,Primcount:?GLsizei,Basevertex:?GLint,Baseinstance:?GLuint>>); @@ -16571,21 +8276,21 @@ drawElementsInstancedBaseVertexBaseInstance(Mode,Count,Type,Indices,Primcount,Ba %% @doc glDrawTransformFeedbackInstance %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawTransformFeedbackInstance.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec drawTransformFeedbackInstanced(Mode, Id, Primcount) -> 'ok' when Mode :: enum(),Id :: integer(),Primcount :: integer(). drawTransformFeedbackInstanced(Mode,Id,Primcount) -> cast(5863, <<Mode:?GLenum,Id:?GLuint,Primcount:?GLsizei>>). %% @doc glDrawTransformFeedbackStreamInstance %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDrawTransformFeedbackStreamInstance.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec drawTransformFeedbackStreamInstanced(Mode, Id, Stream, Primcount) -> 'ok' when Mode :: enum(),Id :: integer(),Stream :: integer(),Primcount :: integer(). drawTransformFeedbackStreamInstanced(Mode,Id,Stream,Primcount) -> cast(5864, <<Mode:?GLenum,Id:?GLuint,Stream:?GLuint,Primcount:?GLsizei>>). %% @doc glGetInternalformat %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glGetInternalformat.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec getInternalformativ(Target, Internalformat, Pname, BufSize) -> [integer()] when Target :: enum(),Internalformat :: enum(),Pname :: enum(),BufSize :: integer(). getInternalformativ(Target,Internalformat,Pname,BufSize) -> call(5865, <<Target:?GLenum,Internalformat:?GLenum,Pname:?GLenum,BufSize:?GLsizei>>). @@ -16599,55 +8304,7 @@ getInternalformativ(Target,Internalformat,Pname,BufSize) -> %% any existing binding to the image unit is broken. `Level' specifies the level of %% the texture to bind to the image unit. %% -%% If `Texture' is the name of a one-, two-, or three-dimensional array texture, a -%% cube map or cube map array texture, or a two-dimensional multisample array texture, then -%% it is possible to bind either the entire array, or only a single layer of the array to -%% the image unit. In such cases, if `Layered' is `?GL_TRUE', the entire array -%% is attached to the image unit and `Layer' is ignored. However, if `Layered' is `?GL_FALSE' -%% then `Layer' specifies the layer of the array to attach to the image unit. -%% -%% `Access' specifies the access types to be performed by shaders and may be set to `?GL_READ_ONLY' -%% , `?GL_WRITE_ONLY', or `?GL_READ_WRITE' to indicate read-only, write-only or -%% read-write access, respectively. Violation of the access type specified in `Access' -%% (for example, if a shader writes to an image bound with `Access' set to `?GL_READ_ONLY' -%% ) will lead to undefined results, possibly including program termination. -%% -%% `Format' specifies the format that is to be used when performing formatted stores -%% into the image from shaders. `Format' must be compatible with the texture's internal -%% format and must be one of the formats listed in the following table. -%% -%% <table><tbody><tr><td>` Image Unit Format '</td><td>` Format Qualifier '</td></tr> -%% </tbody><tbody><tr><td>`?GL_RGBA32F'</td><td>rgba32f</td></tr><tr><td>`?GL_RGBA16F' -%% </td><td>rgba16f</td></tr><tr><td>`?GL_RG32F'</td><td>rg32f</td></tr><tr><td>`?GL_RG16F' -%% </td><td>rg16f</td></tr><tr><td>`?GL_R11F_G11F_B10F'</td><td>r11f_g11f_b10f</td></tr> -%% <tr><td>`?GL_R32F'</td><td>r32f</td></tr><tr><td>`?GL_R16F'</td><td>r16f</td></tr> -%% <tr><td>`?GL_RGBA32UI'</td><td>rgba32ui</td></tr><tr><td>`?GL_RGBA16UI'</td><td> -%% rgba16ui</td></tr><tr><td>`?GL_RGB10_A2UI'</td><td>rgb10_a2ui</td></tr><tr><td>`?GL_RGBA8UI' -%% </td><td>rgba8ui</td></tr><tr><td>`?GL_RG32UI'</td><td>rg32ui</td></tr><tr><td>`?GL_RG16UI' -%% </td><td>rg16ui</td></tr><tr><td>`?GL_RG8UI'</td><td>rg8ui</td></tr><tr><td>`?GL_R32UI' -%% </td><td>r32ui</td></tr><tr><td>`?GL_R16UI'</td><td>r16ui</td></tr><tr><td>`?GL_R8UI' -%% </td><td>r8ui</td></tr><tr><td>`?GL_RGBA32I'</td><td>rgba32i</td></tr><tr><td>`?GL_RGBA16I' -%% </td><td>rgba16i</td></tr><tr><td>`?GL_RGBA8I'</td><td>rgba8i</td></tr><tr><td>`?GL_RG32I' -%% </td><td>rg32i</td></tr><tr><td>`?GL_RG16I'</td><td>rg16i</td></tr><tr><td>`?GL_RG8I' -%% </td><td>rg8i</td></tr><tr><td>`?GL_R32I'</td><td>r32i</td></tr><tr><td>`?GL_R16I' -%% </td><td>r16i</td></tr><tr><td>`?GL_R8I'</td><td>r8i</td></tr><tr><td>`?GL_RGBA16' -%% </td><td>rgba16</td></tr><tr><td>`?GL_RGB10_A2'</td><td>rgb10_a2</td></tr><tr><td>`?GL_RGBA8' -%% </td><td>rgba8</td></tr><tr><td>`?GL_RG16'</td><td>rg16</td></tr><tr><td>`?GL_RG8' -%% </td><td>rg8</td></tr><tr><td>`?GL_R16'</td><td>r16</td></tr><tr><td>`?GL_R8'</td> -%% <td>r8</td></tr><tr><td>`?GL_RGBA16_SNORM'</td><td>rgba16_snorm</td></tr><tr><td>`?GL_RGBA8_SNORM' -%% </td><td>rgba8_snorm</td></tr><tr><td>`?GL_RG16_SNORM'</td><td>rg16_snorm</td></tr><tr> -%% <td>`?GL_RG8_SNORM'</td><td>rg8_snorm</td></tr><tr><td>`?GL_R16_SNORM'</td><td>r16_snorm -%% </td></tr><tr><td>`?GL_R8_SNORM'</td><td>r8_snorm</td></tr></tbody></table> -%% -%% When a texture is bound to an image unit, the `Format' parameter for the image unit -%% need not exactly match the texture internal format as long as the formats are considered -%% compatible as defined in the OpenGL Specification. The matching criterion used for a given -%% texture may be determined by calling {@link gl:getTexParameterfv/2} with `Value' set -%% to `?GL_IMAGE_FORMAT_COMPATIBILITY_TYPE', with return values of `?GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE' -%% and `?GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS', specifying matches by size and class, -%% respectively. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glBindImageTexture.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBindImageTexture.xhtml">external</a> documentation. -spec bindImageTexture(Unit, Texture, Level, Layered, Layer, Access, Format) -> 'ok' when Unit :: integer(),Texture :: integer(),Level :: integer(),Layered :: 0|1,Layer :: integer(),Access :: enum(),Format :: enum(). bindImageTexture(Unit,Texture,Level,Layered,Layer,Access,Format) -> cast(5866, <<Unit:?GLuint,Texture:?GLuint,Level:?GLint,Layered:?GLboolean,0:24,Layer:?GLint,Access:?GLenum,Format:?GLenum>>). @@ -16661,120 +8318,7 @@ bindImageTexture(Unit,Texture,Level,Layered,Layer,Access,Format) -> %% the set of operations that are synchronized with shader stores; the bits used in `Barriers' %% are as follows: %% -%% -%% -%% `?GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT': If set, vertex data sourced from buffer objects -%% after the barrier will reflect data written by shaders prior to the barrier. The set of -%% buffer objects affected by this bit is derived from the buffer object bindings used for -%% generic vertex attributes derived from the `?GL_VERTEX_ATTRIB_ARRAY_BUFFER' bindings. -%% -%% -%% `?GL_ELEMENT_ARRAY_BARRIER_BIT': If set, vertex array indices sourced from buffer -%% objects after the barrier will reflect data written by shaders prior to the barrier. The -%% buffer objects affected by this bit are derived from the `?GL_ELEMENT_ARRAY_BUFFER' -%% binding. -%% -%% `?GL_UNIFORM_BARRIER_BIT': Shader uniforms sourced from buffer objects after the -%% barrier will reflect data written by shaders prior to the barrier. -%% -%% `?GL_TEXTURE_FETCH_BARRIER_BIT': Texture fetches from shaders, including fetches -%% from buffer object memory via buffer textures, after the barrier will reflect data written -%% by shaders prior to the barrier. -%% -%% `?GL_SHADER_IMAGE_ACCESS_BARRIER_BIT': Memory accesses using shader image load, -%% store, and atomic built-in functions issued after the barrier will reflect data written -%% by shaders prior to the barrier. Additionally, image stores and atomics issued after the -%% barrier will not execute until all memory accesses (e.g., loads, stores, texture fetches, -%% vertex fetches) initiated prior to the barrier complete. -%% -%% `?GL_COMMAND_BARRIER_BIT': Command data sourced from buffer objects by Draw*Indirect -%% commands after the barrier will reflect data written by shaders prior to the barrier. -%% The buffer objects affected by this bit are derived from the `?GL_DRAW_INDIRECT_BUFFER' -%% binding. -%% -%% `?GL_PIXEL_BUFFER_BARRIER_BIT': Reads and writes of buffer objects via the `?GL_PIXEL_PACK_BUFFER' -%% and `?GL_PIXEL_UNPACK_BUFFER' bindings (via {@link gl:readPixels/7} , {@link gl:texSubImage1D/7} -%% , etc.) after the barrier will reflect data written by shaders prior to the barrier. Additionally, -%% buffer object writes issued after the barrier will wait on the completion of all shader -%% writes initiated prior to the barrier. -%% -%% `?GL_TEXTURE_UPDATE_BARRIER_BIT': Writes to a texture via ``gl:tex(Sub)Image*'', ``gl:copyTex(Sub)Image*'' -%% , ``gl:compressedTex(Sub)Image*'', and reads via {@link gl:getTexImage/5} after the barrier -%% will reflect data written by shaders prior to the barrier. Additionally, texture writes -%% from these commands issued after the barrier will not execute until all shader writes -%% initiated prior to the barrier complete. -%% -%% `?GL_BUFFER_UPDATE_BARRIER_BIT': Reads or writes via {@link gl:bufferSubData/4} , {@link gl:copyBufferSubData/5} -%% , or {@link gl:getBufferSubData/4} , or to buffer object memory mapped by see `glMapBuffer' -%% or see `glMapBufferRange' after the barrier will reflect data written by shaders -%% prior to the barrier. Additionally, writes via these commands issued after the barrier -%% will wait on the completion of any shader writes to the same memory initiated prior to -%% the barrier. -%% -%% `?GL_FRAMEBUFFER_BARRIER_BIT': Reads and writes via framebuffer object attachments -%% after the barrier will reflect data written by shaders prior to the barrier. Additionally, -%% framebuffer writes issued after the barrier will wait on the completion of all shader -%% writes issued prior to the barrier. -%% -%% `?GL_TRANSFORM_FEEDBACK_BARRIER_BIT': Writes via transform feedback bindings after -%% the barrier will reflect data written by shaders prior to the barrier. Additionally, transform -%% feedback writes issued after the barrier will wait on the completion of all shader writes -%% issued prior to the barrier. -%% -%% `?GL_ATOMIC_COUNTER_BARRIER_BIT': Accesses to atomic counters after the barrier -%% will reflect writes prior to the barrier. -%% -%% If `Barriers' is `?GL_ALL_BARRIER_BITS', shader memory accesses will be synchronized -%% relative to all the operations described above. -%% -%% Implementations may cache buffer object and texture image memory that could be written -%% by shaders in multiple caches; for example, there may be separate caches for texture, -%% vertex fetching, and one or more caches for shader memory accesses. Implementations are -%% not required to keep these caches coherent with shader memory writes. Stores issued by -%% one invocation may not be immediately observable by other pipeline stages or other shader -%% invocations because the value stored may remain in a cache local to the processor executing -%% the store, or because data overwritten by the store is still in a cache elsewhere in the -%% system. When ``gl:memoryBarrier'' is called, the GL flushes and/or invalidates any caches -%% relevant to the operations specified by the `Barriers' parameter to ensure consistent -%% ordering of operations across the barrier. -%% -%% To allow for independent shader invocations to communicate by reads and writes to a common -%% memory address, image variables in the OpenGL Shading Language may be declared as "coherent". -%% Buffer object or texture image memory accessed through such variables may be cached only -%% if caches are automatically updated due to stores issued by any other shader invocation. -%% If the same address is accessed using both coherent and non-coherent variables, the accesses -%% using variables declared as coherent will observe the results stored using coherent variables -%% in other invocations. Using variables declared as "coherent" guarantees only that the -%% results of stores will be immediately visible to shader invocations using similarly-declared -%% variables; calling ``gl:memoryBarrier'' is required to ensure that the stores are visible -%% to other operations. -%% -%% The following guidelines may be helpful in choosing when to use coherent memory accesses -%% and when to use barriers. -%% -%% Data that are read-only or constant may be accessed without using coherent variables or -%% calling MemoryBarrier(). Updates to the read-only data via API calls such as BufferSubData -%% will invalidate shader caches implicitly as required. -%% -%% Data that are shared between shader invocations at a fine granularity (e.g., written by -%% one invocation, consumed by another invocation) should use coherent variables to read -%% and write the shared data. -%% -%% Data written by one shader invocation and consumed by other shader invocations launched -%% as a result of its execution ("dependent invocations") should use coherent variables in -%% the producing shader invocation and call memoryBarrier() after the last write. The consuming -%% shader invocation should also use coherent variables. -%% -%% Data written to image variables in one rendering pass and read by the shader in a later -%% pass need not use coherent variables or memoryBarrier(). Calling MemoryBarrier() with -%% the SHADER_IMAGE_ACCESS_BARRIER_BIT set in `Barriers' between passes is necessary. -%% -%% Data written by the shader in one rendering pass and read by another mechanism (e.g., -%% vertex or index buffer pulling) in a later pass need not use coherent variables or memoryBarrier(). -%% Calling ``gl:memoryBarrier'' with the appropriate bits set in `Barriers' between -%% passes is necessary. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glMemoryBarrier.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glMemoryBarrier.xhtml">external</a> documentation. -spec memoryBarrier(Barriers) -> 'ok' when Barriers :: integer(). memoryBarrier(Barriers) -> cast(5867, <<Barriers:?GLbitfield>>). @@ -16787,27 +8331,7 @@ memoryBarrier(Barriers) -> %% the image may still be modified, however, its storage requirements may not change. Such %% a texture is referred to as an `immutable-format' texture. %% -%% Calling ``gl:texStorage1D'' is equivalent, assuming no errors are generated, to executing -%% the following pseudo-code: for (i = 0; i < levels; i++) { glTexImage1D(target, i, -%% internalformat, width, 0, format, type, NULL); width = max(1, (width / 2)); } -%% -%% Since no texture data is actually provided, the values used in the pseudo-code for `Format' -%% and `Type' are irrelevant and may be considered to be any values that are legal -%% for the chosen `Internalformat' enumerant. `Internalformat' must be one of the -%% sized internal formats given in Table 1 below, one of the sized depth-component formats `?GL_DEPTH_COMPONENT32F' -%% , `?GL_DEPTH_COMPONENT24', or `?GL_DEPTH_COMPONENT16', or one of the combined -%% depth-stencil formats, `?GL_DEPTH32F_STENCIL8', or `?GL_DEPTH24_STENCIL8'. Upon -%% success, the value of `?GL_TEXTURE_IMMUTABLE_FORMAT' becomes `?GL_TRUE'. The -%% value of `?GL_TEXTURE_IMMUTABLE_FORMAT' may be discovered by calling {@link gl:getTexParameterfv/2} -%% with `Pname' set to `?GL_TEXTURE_IMMUTABLE_FORMAT'. No further changes to the -%% dimensions or format of the texture object may be made. Using any command that might alter -%% the dimensions or format of the texture object (such as {@link gl:texImage1D/8} or another -%% call to ``gl:texStorage1D'') will result in the generation of a `?GL_INVALID_OPERATION' -%% error, even if it would not, in fact, alter the dimensions or format of the object. -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexStorage1D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexStorage1D.xhtml">external</a> documentation. -spec texStorage1D(Target, Levels, Internalformat, Width) -> 'ok' when Target :: enum(),Levels :: integer(),Internalformat :: enum(),Width :: integer(). texStorage1D(Target,Levels,Internalformat,Width) -> cast(5868, <<Target:?GLenum,Levels:?GLsizei,Internalformat:?GLenum,Width:?GLsizei>>). @@ -16820,39 +8344,7 @@ texStorage1D(Target,Levels,Internalformat,Width) -> %% proxy texture. The contents of the image may still be modified, however, its storage requirements %% may not change. Such a texture is referred to as an `immutable-format' texture. %% -%% The behavior of ``gl:texStorage2D'' depends on the `Target' parameter. When `Target' -%% is `?GL_TEXTURE_2D', `?GL_PROXY_TEXTURE_2D', `?GL_TEXTURE_RECTANGLE', `?GL_PROXY_TEXTURE_RECTANGLE' -%% or `?GL_PROXY_TEXTURE_CUBE_MAP', calling ``gl:texStorage2D'' is equivalent, assuming -%% no errors are generated, to executing the following pseudo-code: for (i = 0; i < levels; -%% i++) { glTexImage2D(target, i, internalformat, width, height, 0, format, type, NULL); -%% width = max(1, (width / 2)); height = max(1, (height / 2)); } -%% -%% When `Target' is `?GL_TEXTURE_CUBE_MAP', ``gl:texStorage2D'' is equivalent -%% to: for (i = 0; i < levels; i++) { for (face in (+X, -X, +Y, -Y, +Z, -Z)) { glTexImage2D(face, -%% i, internalformat, width, height, 0, format, type, NULL); } width = max(1, (width / 2)); -%% height = max(1, (height / 2)); } -%% -%% When `Target' is `?GL_TEXTURE_1D' or `?GL_TEXTURE_1D_ARRAY', ``gl:texStorage2D'' -%% is equivalent to: for (i = 0; i < levels; i++) { glTexImage2D(target, i, internalformat, -%% width, height, 0, format, type, NULL); width = max(1, (width / 2)); } -%% -%% Since no texture data is actually provided, the values used in the pseudo-code for `Format' -%% and `Type' are irrelevant and may be considered to be any values that are legal -%% for the chosen `Internalformat' enumerant. `Internalformat' must be one of the -%% sized internal formats given in Table 1 below, one of the sized depth-component formats `?GL_DEPTH_COMPONENT32F' -%% , `?GL_DEPTH_COMPONENT24', or `?GL_DEPTH_COMPONENT16', or one of the combined -%% depth-stencil formats, `?GL_DEPTH32F_STENCIL8', or `?GL_DEPTH24_STENCIL8'. Upon -%% success, the value of `?GL_TEXTURE_IMMUTABLE_FORMAT' becomes `?GL_TRUE'. The -%% value of `?GL_TEXTURE_IMMUTABLE_FORMAT' may be discovered by calling {@link gl:getTexParameterfv/2} -%% with `Pname' set to `?GL_TEXTURE_IMMUTABLE_FORMAT'. No further changes to the -%% dimensions or format of the texture object may be made. Using any command that might alter -%% the dimensions or format of the texture object (such as {@link gl:texImage2D/9} or another -%% call to ``gl:texStorage2D'') will result in the generation of a `?GL_INVALID_OPERATION' -%% error, even if it would not, in fact, alter the dimensions or format of the object. -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexStorage2D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexStorage2D.xhtml">external</a> documentation. -spec texStorage2D(Target, Levels, Internalformat, Width, Height) -> 'ok' when Target :: enum(),Levels :: integer(),Internalformat :: enum(),Width :: integer(),Height :: integer(). texStorage2D(Target,Levels,Internalformat,Width,Height) -> cast(5869, <<Target:?GLenum,Levels:?GLsizei,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei>>). @@ -16866,50 +8358,21 @@ texStorage2D(Target,Levels,Internalformat,Width,Height) -> %% requirements may not change. Such a texture is referred to as an `immutable-format' %% texture. %% -%% The behavior of ``gl:texStorage3D'' depends on the `Target' parameter. When `Target' -%% is `?GL_TEXTURE_3D', or `?GL_PROXY_TEXTURE_3D', calling ``gl:texStorage3D'' -%% is equivalent, assuming no errors are generated, to executing the following pseudo-code: -%% for (i = 0; i < levels; i++) { glTexImage3D(target, i, internalformat, width, height, -%% depth, 0, format, type, NULL); width = max(1, (width / 2)); height = max(1, (height / -%% 2)); depth = max(1, (depth / 2)); } -%% -%% When `Target' is `?GL_TEXTURE_2D_ARRAY', `?GL_PROXY_TEXTURE_2D_ARRAY', `?GL_TEXTURE_CUBE_MAP_ARRAY' -%% , or `?GL_PROXY_TEXTURE_CUBE_MAP_ARRAY', ``gl:texStorage3D'' is equivalent to: -%% for (i = 0; i < levels; i++) { glTexImage3D(target, i, internalformat, width, height, -%% depth, 0, format, type, NULL); width = max(1, (width / 2)); height = max(1, (height / -%% 2)); } -%% -%% Since no texture data is actually provided, the values used in the pseudo-code for `Format' -%% and `Type' are irrelevant and may be considered to be any values that are legal -%% for the chosen `Internalformat' enumerant. `Internalformat' must be one of the -%% sized internal formats given in Table 1 below, one of the sized depth-component formats `?GL_DEPTH_COMPONENT32F' -%% , `?GL_DEPTH_COMPONENT24', or `?GL_DEPTH_COMPONENT16', or one of the combined -%% depth-stencil formats, `?GL_DEPTH32F_STENCIL8', or `?GL_DEPTH24_STENCIL8'. Upon -%% success, the value of `?GL_TEXTURE_IMMUTABLE_FORMAT' becomes `?GL_TRUE'. The -%% value of `?GL_TEXTURE_IMMUTABLE_FORMAT' may be discovered by calling {@link gl:getTexParameterfv/2} -%% with `Pname' set to `?GL_TEXTURE_IMMUTABLE_FORMAT'. No further changes to the -%% dimensions or format of the texture object may be made. Using any command that might alter -%% the dimensions or format of the texture object (such as {@link gl:texImage3D/10} or another -%% call to ``gl:texStorage3D'') will result in the generation of a `?GL_INVALID_OPERATION' -%% error, even if it would not, in fact, alter the dimensions or format of the object. -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glTexStorage3D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexStorage3D.xhtml">external</a> documentation. -spec texStorage3D(Target, Levels, Internalformat, Width, Height, Depth) -> 'ok' when Target :: enum(),Levels :: integer(),Internalformat :: enum(),Width :: integer(),Height :: integer(),Depth :: integer(). texStorage3D(Target,Levels,Internalformat,Width,Height,Depth) -> cast(5870, <<Target:?GLenum,Levels:?GLsizei,Internalformat:?GLenum,Width:?GLsizei,Height:?GLsizei,Depth:?GLsizei>>). %% @doc glDepthBoundsEXT %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glDepthBoundsEXT.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec depthBoundsEXT(Zmin, Zmax) -> 'ok' when Zmin :: clamp(),Zmax :: clamp(). depthBoundsEXT(Zmin,Zmax) -> cast(5871, <<Zmin:?GLclampd,Zmax:?GLclampd>>). %% @doc glStencilClearTagEXT %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/glStencilClearTagEXT.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">external</a> documentation. -spec stencilClearTagEXT(StencilTagBits, StencilClearTag) -> 'ok' when StencilTagBits :: integer(),StencilClearTag :: integer(). stencilClearTagEXT(StencilTagBits,StencilClearTag) -> cast(5872, <<StencilTagBits:?GLsizei,StencilClearTag:?GLuint>>). diff --git a/lib/wx/src/gen/glu.erl b/lib/wx/src/gen/glu.erl index f641f41262..5e5f01874f 100644 --- a/lib/wx/src/gen/glu.erl +++ b/lib/wx/src/gen/glu.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2016. All Rights Reserved. +%% Copyright Ericsson AB 2008-2017. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -22,7 +22,7 @@ %% This file is generated DO NOT EDIT %% @doc A part of the standard OpenGL Utility api. -%% See <a href="http://www.opengl.org/sdk/docs/man/">www.opengl.org</a> +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/">www.khronos.org</a> %% %% Booleans are represented by integers 0 and 1. @@ -92,29 +92,7 @@ tesselate({Nx,Ny,Nz}, Vs) -> %% of decreasing resolutions called a mipmap. This is used for the antialiasing of texture %% mapped primitives. %% -%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1} -%% ). -%% -%% A series of mipmap levels from `Base' to `Max' is built by decimating `Data' -%% in half until size 1×1 is reached. At each level, each texel in the halved mipmap -%% level is an average of the corresponding two texels in the larger mipmap level. {@link gl:texImage1D/8} -%% is called to load these mipmap levels from `Base' to `Max' . If `Max' is -%% larger than the highest mipmap level for the texture of the specified size, then a GLU -%% error code is returned (see {@link glu:errorString/1} ) and nothing is loaded. -%% -%% For example, if `Level' is 2 and `Width' is 16, the following levels are possible: -%% 16×1, 8×1, 4×1, 2×1, 1×1. These correspond to levels 2 through 6 respectively. -%% If `Base' is 3 and `Max' is 5, then only mipmap levels 8×1, 4×1 and 2×1 -%% are loaded. However, if `Max' is 7, then an error is returned and nothing is loaded -%% since `Max' is larger than the highest mipmap level which is, in this case, 6. -%% -%% The highest mipmap level can be derived from the formula log 2(width×2 level). -%% -%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values -%% for `Type' parameter. See the {@link gl:drawPixels/5} reference page for a description -%% of the acceptable values for `Level' parameter. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild1DMipmapLevels.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluBuild1DMipmapLevels.xml">external</a> documentation. -spec build1DMipmapLevels(Target, InternalFormat, Width, Format, Type, Level, Base, Max, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Format :: enum(),Type :: enum(),Level :: integer(),Base :: integer(),Max :: integer(),Data :: binary(). build1DMipmapLevels(Target,InternalFormat,Width,Format,Type,Level,Base,Max,Data) -> send_bin(Data), @@ -126,33 +104,7 @@ build1DMipmapLevels(Target,InternalFormat,Width,Format,Type,Level,Base,Max,Data) %% decreasing resolutions called a mipmap. This is used for the antialiasing of texture mapped %% primitives. %% -%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1} -%% ). -%% -%% Initially, the `Width' of `Data' is checked to see if it is a power of 2. If -%% not, a copy of `Data' is scaled up or down to the nearest power of 2. (If `Width' -%% is exactly between powers of 2, then the copy of `Data' will scale upwards.) This -%% copy will be used for subsequent mipmapping operations described below. For example, if `Width' -%% is 57, then a copy of `Data' will scale up to 64 before mipmapping takes place. -%% -%% Then, proxy textures (see {@link gl:texImage1D/8} ) are used to determine if the implementation -%% can fit the requested texture. If not, `Width' is continually halved until it fits. -%% -%% Next, a series of mipmap levels is built by decimating a copy of `Data' in half -%% until size 1×1 is reached. At each level, each texel in the halved mipmap level is an -%% average of the corresponding two texels in the larger mipmap level. -%% -%% {@link gl:texImage1D/8} is called to load each of these mipmap levels. Level 0 is a copy -%% of `Data' . The highest level is (log 2)(width). For example, if `Width' is 64 and the implementation -%% can store a texture of this size, the following mipmap levels are built: 64×1, 32×1, -%% 16×1, 8×1, 4×1, 2×1, and 1×1. These correspond to levels 0 through 6, respectively. -%% -%% -%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values -%% for the `Type' parameter. See the {@link gl:drawPixels/5} reference page for a description -%% of the acceptable values for the `Data' parameter. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild1DMipmaps.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluBuild1DMipmaps.xml">external</a> documentation. -spec build1DMipmaps(Target, InternalFormat, Width, Format, Type, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Format :: enum(),Type :: enum(),Data :: binary(). build1DMipmaps(Target,InternalFormat,Width,Format,Type,Data) -> send_bin(Data), @@ -164,32 +116,7 @@ build1DMipmaps(Target,InternalFormat,Width,Format,Type,Data) -> %% of decreasing resolutions called a mipmap. This is used for the antialiasing of texture %% mapped primitives. %% -%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1} -%% ). -%% -%% A series of mipmap levels from `Base' to `Max' is built by decimating `Data' -%% in half along both dimensions until size 1×1 is reached. At each level, each texel -%% in the halved mipmap level is an average of the corresponding four texels in the larger -%% mipmap level. (In the case of rectangular images, the decimation will ultimately reach -%% an N×1 or 1×N configuration. Here, two texels are averaged instead.) {@link gl:texImage2D/9} -%% is called to load these mipmap levels from `Base' to `Max' . If `Max' is -%% larger than the highest mipmap level for the texture of the specified size, then a GLU -%% error code is returned (see {@link glu:errorString/1} ) and nothing is loaded. -%% -%% For example, if `Level' is 2 and `Width' is 16 and `Height' is 8, the -%% following levels are possible: 16×8, 8×4, 4×2, 2×1, 1×1. These correspond to -%% levels 2 through 6 respectively. If `Base' is 3 and `Max' is 5, then only mipmap -%% levels 8×4, 4×2, and 2×1 are loaded. However, if `Max' is 7, then an error is -%% returned and nothing is loaded since `Max' is larger than the highest mipmap level -%% which is, in this case, 6. -%% -%% The highest mipmap level can be derived from the formula log 2(max(width height)×2 level). -%% -%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values -%% for `Format' parameter. See the {@link gl:drawPixels/5} reference page for a description -%% of the acceptable values for `Type' parameter. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild2DMipmapLevels.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluBuild2DMipmapLevels.xml">external</a> documentation. -spec build2DMipmapLevels(Target, InternalFormat, Width, Height, Format, Type, Level, Base, Max, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Level :: integer(),Base :: integer(),Max :: integer(),Data :: binary(). build2DMipmapLevels(Target,InternalFormat,Width,Height,Format,Type,Level,Base,Max,Data) -> send_bin(Data), @@ -201,40 +128,7 @@ build2DMipmapLevels(Target,InternalFormat,Width,Height,Format,Type,Level,Base,Ma %% decreasing resolutions called a mipmap. This is used for the antialiasing of texture-mapped %% primitives. %% -%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1} -%% ). -%% -%% Initially, the `Width' and `Height' of `Data' are checked to see if they -%% are a power of 2. If not, a copy of `Data' (not `Data' ), is scaled up or down -%% to the nearest power of 2. This copy will be used for subsequent mipmapping operations -%% described below. (If `Width' or `Height' is exactly between powers of 2, then -%% the copy of `Data' will scale upwards.) For example, if `Width' is 57 and `Height' -%% is 23, then a copy of `Data' will scale up to 64 in `Width' and down to 16 -%% in depth, before mipmapping takes place. -%% -%% Then, proxy textures (see {@link gl:texImage2D/9} ) are used to determine if the implementation -%% can fit the requested texture. If not, both dimensions are continually halved until it -%% fits. (If the OpenGL version is (<= 1.0, both maximum texture dimensions are clamped -%% to the value returned by {@link gl:getBooleanv/1} with the argument `?GLU_MAX_TEXTURE_SIZE' -%% .) -%% -%% Next, a series of mipmap levels is built by decimating a copy of `Data' in half -%% along both dimensions until size 1×1 is reached. At each level, each texel in the halved -%% mipmap level is an average of the corresponding four texels in the larger mipmap level. -%% (In the case of rectangular images, the decimation will ultimately reach an N×1 or 1×N -%% configuration. Here, two texels are averaged instead.) -%% -%% {@link gl:texImage2D/9} is called to load each of these mipmap levels. Level 0 is a copy -%% of `Data' . The highest level is (log 2)(max(width height)). For example, if `Width' is 64 and `Height' -%% is 16 and the implementation can store a texture of this size, the following mipmap levels -%% are built: 64×16, 32×8, 16×4, 8×2, 4×1, 2×1, and 1×1 These correspond to -%% levels 0 through 6, respectively. -%% -%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values -%% for `Format' parameter. See the {@link gl:drawPixels/5} reference page for a description -%% of the acceptable values for `Type' parameter. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild2DMipmaps.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluBuild2DMipmaps.xml">external</a> documentation. -spec build2DMipmaps(Target, InternalFormat, Width, Height, Format, Type, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Format :: enum(),Type :: enum(),Data :: binary(). build2DMipmaps(Target,InternalFormat,Width,Height,Format,Type,Data) -> send_bin(Data), @@ -246,32 +140,7 @@ build2DMipmaps(Target,InternalFormat,Width,Height,Format,Type,Data) -> %% maps of decreasing resolutions called a mipmap. This is used for the antialiasing of texture %% mapped primitives. %% -%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1} -%% ). -%% -%% A series of mipmap levels from `Base' to `Max' is built by decimating `Data' -%% in half along both dimensions until size 1×1×1 is reached. At each level, each texel -%% in the halved mipmap level is an average of the corresponding eight texels in the larger -%% mipmap level. (If exactly one of the dimensions is 1, four texels are averaged. If exactly -%% two of the dimensions are 1, two texels are averaged.) {@link gl:texImage3D/10} is called -%% to load these mipmap levels from `Base' to `Max' . If `Max' is larger than -%% the highest mipmap level for the texture of the specified size, then a GLU error code -%% is returned (see {@link glu:errorString/1} ) and nothing is loaded. -%% -%% For example, if `Level' is 2 and `Width' is 16, `Height' is 8 and `Depth' -%% is 4, the following levels are possible: 16×8×4, 8×4×2, 4×2×1, 2×1×1, 1×1×1. -%% These correspond to levels 2 through 6 respectively. If `Base' is 3 and `Max' -%% is 5, then only mipmap levels 8×4×2, 4×2×1, and 2×1×1 are loaded. However, if `Max' -%% is 7, then an error is returned and nothing is loaded, since `Max' is larger than -%% the highest mipmap level which is, in this case, 6. -%% -%% The highest mipmap level can be derived from the formula log 2(max(width height depth)×2 level). -%% -%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values -%% for `Format' parameter. See the {@link gl:drawPixels/5} reference page for a description -%% of the acceptable values for `Type' parameter. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild3DMipmapLevels.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluBuild3DMipmapLevels.xml">external</a> documentation. -spec build3DMipmapLevels(Target, InternalFormat, Width, Height, Depth, Format, Type, Level, Base, Max, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Format :: enum(),Type :: enum(),Level :: integer(),Base :: integer(),Max :: integer(),Data :: binary(). build3DMipmapLevels(Target,InternalFormat,Width,Height,Depth,Format,Type,Level,Base,Max,Data) -> send_bin(Data), @@ -283,39 +152,7 @@ build3DMipmapLevels(Target,InternalFormat,Width,Height,Depth,Format,Type,Level,B %% of decreasing resolutions called a mipmap. This is used for the antialiasing of texture-mapped %% primitives. %% -%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1} -%% ). -%% -%% Initially, the `Width' , `Height' and `Depth' of `Data' are checked -%% to see if they are a power of 2. If not, a copy of `Data' is made and scaled up or -%% down to the nearest power of 2. (If `Width' , `Height' , or `Depth' is exactly -%% between powers of 2, then the copy of `Data' will scale upwards.) This copy will -%% be used for subsequent mipmapping operations described below. For example, if `Width' -%% is 57, `Height' is 23, and `Depth' is 24, then a copy of `Data' will scale -%% up to 64 in width, down to 16 in height, and up to 32 in depth before mipmapping takes -%% place. -%% -%% Then, proxy textures (see {@link gl:texImage3D/10} ) are used to determine if the implementation -%% can fit the requested texture. If not, all three dimensions are continually halved until -%% it fits. -%% -%% Next, a series of mipmap levels is built by decimating a copy of `Data' in half -%% along all three dimensions until size 1×1×1 is reached. At each level, each texel in -%% the halved mipmap level is an average of the corresponding eight texels in the larger -%% mipmap level. (If exactly one of the dimensions is 1, four texels are averaged. If exactly -%% two of the dimensions are 1, two texels are averaged.) -%% -%% {@link gl:texImage3D/10} is called to load each of these mipmap levels. Level 0 is a copy -%% of `Data' . The highest level is (log 2)(max(width height depth)). For example, if `Width' is 64, `Height' -%% is 16, and `Depth' is 32, and the implementation can store a texture of this size, -%% the following mipmap levels are built: 64×16×32, 32×8×16, 16×4×8, 8×2×4, 4×1×2, -%% 2×1×1, and 1×1×1. These correspond to levels 0 through 6, respectively. -%% -%% See the {@link gl:texImage1D/8} reference page for a description of the acceptable values -%% for `Format' parameter. See the {@link gl:drawPixels/5} reference page for a description -%% of the acceptable values for `Type' parameter. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluBuild3DMipmaps.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluBuild3DMipmaps.xml">external</a> documentation. -spec build3DMipmaps(Target, InternalFormat, Width, Height, Depth, Format, Type, Data) -> integer() when Target :: enum(),InternalFormat :: integer(),Width :: integer(),Height :: integer(),Depth :: integer(),Format :: enum(),Type :: enum(),Data :: binary(). build3DMipmaps(Target,InternalFormat,Width,Height,Depth,Format,Type,Data) -> send_bin(Data), @@ -326,12 +163,7 @@ build3DMipmaps(Target,InternalFormat,Width,Height,Depth,Format,Type,Data) -> %% ``glu:checkExtension'' returns `?GLU_TRUE' if `ExtName' is supported otherwise %% `?GLU_FALSE' is returned. %% -%% This is used to check for the presence for OpenGL, GLU, or GLX extension names by passing -%% the extension strings returned by {@link gl:getString/1} , {@link glu:getString/1} , see `glXGetClientString' -%% , see `glXQueryExtensionsString', or see `glXQueryServerString', respectively, -%% as `ExtString' . -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluCheckExtension.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluCheckExtension.xml">external</a> documentation. -spec checkExtension(ExtName, ExtString) -> 0|1 when ExtName :: string(),ExtString :: string(). checkExtension(ExtName,ExtString) -> ExtNameLen = length(ExtName), @@ -345,19 +177,7 @@ checkExtension(ExtName,ExtString) -> %% is subdivided around the `z' axis into slices and along the `z' axis into stacks. %% %% -%% Note that if `Top' is set to 0.0, this routine generates a cone. -%% -%% If the orientation is set to `?GLU_OUTSIDE' (with {@link glu:quadricOrientation/2} ), -%% then any generated normals point away from the `z' axis. Otherwise, they point toward -%% the `z' axis. -%% -%% If texturing is turned on (with {@link glu:quadricTexture/2} ), then texture coordinates -%% are generated so that `t' ranges linearly from 0.0 at `z' = 0 to 1.0 at `z' -%% = `Height' , and `s' ranges from 0.0 at the +`y' axis, to 0.25 at the +`x' -%% axis, to 0.5 at the -`y' axis, to 0.75 at the -`x' axis, and back to 1.0 -%% at the +`y' axis. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluCylinder.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluCylinder.xml">external</a> documentation. -spec cylinder(Quad, Base, Top, Height, Slices, Stacks) -> 'ok' when Quad :: integer(),Base :: float(),Top :: float(),Height :: float(),Slices :: integer(),Stacks :: integer(). cylinder(Quad,Base,Top,Height,Slices,Stacks) -> cast(5017, <<Quad:?GLUquadric,Base:?GLdouble,Top:?GLdouble,Height:?GLdouble,Slices:?GLint,Stacks:?GLint>>). @@ -368,7 +188,7 @@ cylinder(Quad,Base,Top,Height,Slices,Stacks) -> %% and frees any memory it uses. Once ``glu:deleteQuadric'' has been called, `Quad' %% cannot be used again. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluDeleteQuadric.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluDeleteQuadric.xml">external</a> documentation. -spec deleteQuadric(Quad) -> 'ok' when Quad :: integer(). deleteQuadric(Quad) -> cast(5018, <<Quad:?GLUquadric>>). @@ -381,17 +201,7 @@ deleteQuadric(Quad) -> %% slices (like pizza slices) and also about the `z' axis into rings (as specified by `Slices' %% and `Loops' , respectively). %% -%% With respect to orientation, the +`z' side of the disk is considered to be ``outside'' -%% (see {@link glu:quadricOrientation/2} ). This means that if the orientation is set to `?GLU_OUTSIDE' -%% , then any normals generated point along the +`z' axis. Otherwise, they point along -%% the -`z' axis. -%% -%% If texturing has been turned on (with {@link glu:quadricTexture/2} ), texture coordinates -%% are generated linearly such that where r=outer, the value at (`r', 0, 0) is (1, -%% 0.5), at (0, `r', 0) it is (0.5, 1), at (-`r', 0, 0) it is (0, 0.5), and at -%% (0, -`r', 0) it is (0.5, 0). -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluDisk.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluDisk.xml">external</a> documentation. -spec disk(Quad, Inner, Outer, Slices, Loops) -> 'ok' when Quad :: integer(),Inner :: float(),Outer :: float(),Slices :: integer(),Loops :: integer(). disk(Quad,Inner,Outer,Slices,Loops) -> cast(5019, <<Quad:?GLUquadric,Inner:?GLdouble,Outer:?GLdouble,Slices:?GLint,Loops:?GLint>>). @@ -402,12 +212,7 @@ disk(Quad,Inner,Outer,Slices,Loops) -> %% is in ISO Latin 1 format. For example, ``glu:errorString''(`?GLU_OUT_OF_MEMORY') %% returns the string `out of memory'. %% -%% The standard GLU error codes are `?GLU_INVALID_ENUM', `?GLU_INVALID_VALUE', -%% and `?GLU_OUT_OF_MEMORY'. Certain other GLU functions can return specialized error -%% codes through callbacks. See the {@link gl:getError/0} reference page for the list of -%% GL error codes. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluErrorString.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluErrorString.xml">external</a> documentation. -spec errorString(Error) -> string() when Error :: enum(). errorString(Error) -> call(5020, <<Error:?GLenum>>). @@ -417,25 +222,7 @@ errorString(Error) -> %% ``glu:getString'' returns a pointer to a static string describing the GLU version or %% the GLU extensions that are supported. %% -%% The version number is one of the following forms: -%% -%% `major_number.minor_number'`major_number.minor_number.release_number'. -%% -%% The version string is of the following form: -%% -%% `version number<space>vendor-specific information' -%% -%% Vendor-specific information is optional. Its format and contents depend on the implementation. -%% -%% -%% The standard GLU contains a basic set of features and capabilities. If a company or group -%% of companies wish to support other features, these may be included as extensions to the -%% GLU. If `Name' is `?GLU_EXTENSIONS', then ``glu:getString'' returns a space-separated -%% list of names of supported GLU extensions. (Extension names never contain spaces.) -%% -%% All strings are null-terminated. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluGetString.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluGetString.xml">external</a> documentation. -spec getString(Name) -> string() when Name :: enum(). getString(Name) -> call(5021, <<Name:?GLenum>>). @@ -445,31 +232,7 @@ getString(Name) -> %% ``glu:lookAt'' creates a viewing matrix derived from an eye point, a reference point %% indicating the center of the scene, and an `UP' vector. %% -%% The matrix maps the reference point to the negative `z' axis and the eye point to -%% the origin. When a typical projection matrix is used, the center of the scene therefore -%% maps to the center of the viewport. Similarly, the direction described by the `UP' -%% vector projected onto the viewing plane is mapped to the positive `y' axis so that -%% it points upward in the viewport. The `UP' vector must not be parallel to the line -%% of sight from the eye point to the reference point. -%% -%% Let -%% -%% F=(centerX-eyeX centerY-eyeY centerZ-eyeZ) -%% -%% Let `UP' be the vector (upX upY upZ). -%% -%% Then normalize as follows: f=F/(||F||) -%% -%% UP"=UP/(||UP||) -%% -%% Finally, let s=f×UP", and u=s×f. -%% -%% M is then constructed as follows: M=(s[0] s[1] s[2] 0 u[0] u[1] u[2] 0-f[0]-f[1]-f[2] 0 0 0 0 1) -%% -%% and ``glu:lookAt'' is equivalent to glMultMatrixf(M); glTranslated(-eyex, -eyey, -%% -eyez); -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluLookAt.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluLookAt.xml">external</a> documentation. -spec lookAt(EyeX, EyeY, EyeZ, CenterX, CenterY, CenterZ, UpX, UpY, UpZ) -> 'ok' when EyeX :: float(),EyeY :: float(),EyeZ :: float(),CenterX :: float(),CenterY :: float(),CenterZ :: float(),UpX :: float(),UpY :: float(),UpZ :: float(). lookAt(EyeX,EyeY,EyeZ,CenterX,CenterY,CenterZ,UpX,UpY,UpZ) -> cast(5022, <<EyeX:?GLdouble,EyeY:?GLdouble,EyeZ:?GLdouble,CenterX:?GLdouble,CenterY:?GLdouble,CenterZ:?GLdouble,UpX:?GLdouble,UpY:?GLdouble,UpZ:?GLdouble>>). @@ -480,7 +243,7 @@ lookAt(EyeX,EyeY,EyeZ,CenterX,CenterY,CenterZ,UpX,UpY,UpZ) -> %% must be referred to when calling quadrics rendering and control functions. A return value %% of 0 means that there is not enough memory to allocate the object. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluNewQuadric.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluNewQuadric.xml">external</a> documentation. -spec newQuadric() -> integer(). newQuadric() -> call(5023, <<>>). @@ -490,7 +253,7 @@ newQuadric() -> %% ``glu:ortho2D'' sets up a two-dimensional orthographic viewing region. This is equivalent %% to calling {@link gl:ortho/6} with near=-1 and far=1. %% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluOrtho2D.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluOrtho2D.xml">external</a> documentation. -spec ortho2D(Left, Right, Bottom, Top) -> 'ok' when Left :: float(),Right :: float(),Bottom :: float(),Top :: float(). ortho2D(Left,Right,Bottom,Top) -> cast(5024, <<Left:?GLdouble,Right:?GLdouble,Bottom:?GLdouble,Top:?GLdouble>>). @@ -503,23 +266,7 @@ ortho2D(Left,Right,Bottom,Top) -> %% the +`x' axis, 180 degrees along the -`y' axis, and 270 degrees along the -`x' %% axis). %% -%% The partial disk has a radius of `Outer' and contains a concentric circular hole -%% with a radius of `Inner' . If `Inner' is 0, then no hole is generated. The partial -%% disk is subdivided around the `z' axis into slices (like pizza slices) and also about -%% the `z' axis into rings (as specified by `Slices' and `Loops' , respectively). -%% -%% -%% With respect to orientation, the +`z' side of the partial disk is considered to -%% be outside (see {@link glu:quadricOrientation/2} ). This means that if the orientation -%% is set to `?GLU_OUTSIDE', then any normals generated point along the +`z' axis. -%% Otherwise, they point along the -`z' axis. -%% -%% If texturing is turned on (with {@link glu:quadricTexture/2} ), texture coordinates are -%% generated linearly such that where r=outer, the value at (`r', 0, 0) is (1.0, -%% 0.5), at (0, `r', 0) it is (0.5, 1.0), at (-`r', 0, 0) it is (0.0, 0.5), and -%% at (0, -`r', 0) it is (0.5, 0.0). -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluPartialDisk.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPartialDisk.xml">external</a> documentation. -spec partialDisk(Quad, Inner, Outer, Slices, Loops, Start, Sweep) -> 'ok' when Quad :: integer(),Inner :: float(),Outer :: float(),Slices :: integer(),Loops :: integer(),Start :: float(),Sweep :: float(). partialDisk(Quad,Inner,Outer,Slices,Loops,Start,Sweep) -> cast(5025, <<Quad:?GLUquadric,Inner:?GLdouble,Outer:?GLdouble,Slices:?GLint,Loops:?GLint,Start:?GLdouble,Sweep:?GLdouble>>). @@ -532,18 +279,7 @@ partialDisk(Quad,Inner,Outer,Slices,Loops,Start,Sweep) -> %% as wide in `x' as it is in `y'. If the viewport is twice as wide as it is tall, %% it displays the image without distortion. %% -%% The matrix generated by ``glu:perspective'' is multipled by the current matrix, just -%% as if {@link gl:multMatrixd/1} were called with the generated matrix. To load the perspective -%% matrix onto the current matrix stack instead, precede the call to ``glu:perspective'' -%% with a call to {@link gl:loadIdentity/0} . -%% -%% Given `f' defined as follows: -%% -%% f=cotangent(fovy/2) The generated matrix is -%% -%% (f/aspect 0 0 0 0 f 0 0 0 0(zFar+zNear)/(zNear-zFar)(2×zFar×zNear)/(zNear-zFar) 0 0 -1 0) -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluPerspective.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml">external</a> documentation. -spec perspective(Fovy, Aspect, ZNear, ZFar) -> 'ok' when Fovy :: float(),Aspect :: float(),ZNear :: float(),ZFar :: float(). perspective(Fovy,Aspect,ZNear,ZFar) -> cast(5026, <<Fovy:?GLdouble,Aspect:?GLdouble,ZNear:?GLdouble,ZFar:?GLdouble>>). @@ -557,19 +293,7 @@ perspective(Fovy,Aspect,ZNear,ZFar) -> %% rerender the scene. All primitives that would have been drawn near the cursor are identified %% and stored in the selection buffer. %% -%% The matrix created by ``glu:pickMatrix'' is multiplied by the current matrix just as -%% if {@link gl:multMatrixd/1} is called with the generated matrix. To effectively use the -%% generated pick matrix for picking, first call {@link gl:loadIdentity/0} to load an identity -%% matrix onto the perspective matrix stack. Then call ``glu:pickMatrix'', and, finally, -%% call a command (such as {@link glu:perspective/4} ) to multiply the perspective matrix by -%% the pick matrix. -%% -%% When using ``glu:pickMatrix'' to pick NURBS, be careful to turn off the NURBS property -%% `?GLU_AUTO_LOAD_MATRIX'. If `?GLU_AUTO_LOAD_MATRIX' is not turned off, then -%% any NURBS surface rendered is subdivided differently with the pick matrix than the way -%% it was subdivided without the pick matrix. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluPickMatrix.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPickMatrix.xml">external</a> documentation. -spec pickMatrix(X, Y, DelX, DelY, Viewport) -> 'ok' when X :: float(),Y :: float(),DelX :: float(),DelY :: float(),Viewport :: {integer(),integer(),integer(),integer()}. pickMatrix(X,Y,DelX,DelY,{V1,V2,V3,V4}) -> cast(5027, <<X:?GLdouble,Y:?GLdouble,DelX:?GLdouble,DelY:?GLdouble,V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>>). @@ -581,25 +305,7 @@ pickMatrix(X,Y,DelX,DelY,{V1,V2,V3,V4}) -> %% , and `WinZ' . A return value of `?GLU_TRUE' indicates success, a return value %% of `?GLU_FALSE' indicates failure. %% -%% To compute the coordinates, let v=(objX objY objZ 1.0) represented as a matrix with 4 rows and 1 column. -%% Then ``glu:project'' computes v" as follows: -%% -%% v"=P×M×v -%% -%% where P is the current projection matrix `Proj' and M is the current modelview -%% matrix `Model' (both represented as 4×4 matrices in column-major order). -%% -%% The window coordinates are then computed as follows: -%% -%% winX=view(0)+view(2)×(v"(0)+1)/2 -%% -%% winY=view(1)+view(3)×(v"(1)+1)/2 -%% -%% winZ=(v"(2)+1)/2 -%% -%% -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluProject.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluProject.xml">external</a> documentation. -spec project(ObjX, ObjY, ObjZ, Model, Proj, View) -> {integer(),WinX :: float(),WinY :: float(),WinZ :: float()} when ObjX :: float(),ObjY :: float(),ObjZ :: float(),Model :: matrix(),Proj :: matrix(),View :: {integer(),integer(),integer(),integer()}. project(ObjX,ObjY,ObjZ,{M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16},{P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16},{V1,V2,V3,V4}) -> call(5028, <<ObjX:?GLdouble,ObjY:?GLdouble,ObjZ:?GLdouble,M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble,P1:?GLdouble,P2:?GLdouble,P3:?GLdouble,P4:?GLdouble,P5:?GLdouble,P6:?GLdouble,P7:?GLdouble,P8:?GLdouble,P9:?GLdouble,P10:?GLdouble,P11:?GLdouble,P12:?GLdouble,P13:?GLdouble,P14:?GLdouble,P15:?GLdouble,P16:?GLdouble,V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>>); @@ -611,18 +317,7 @@ project(ObjX,ObjY,ObjZ,{M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12},{P1,P2,P3,P4,P5, %% ``glu:quadricDrawStyle'' specifies the draw style for quadrics rendered with `Quad' . %% The legal values are as follows: %% -%% `?GLU_FILL': Quadrics are rendered with polygon primitives. The polygons are drawn -%% in a counterclockwise fashion with respect to their normals (as defined with {@link glu:quadricOrientation/2} -%% ). -%% -%% `?GLU_LINE': Quadrics are rendered as a set of lines. -%% -%% `?GLU_SILHOUETTE': Quadrics are rendered as a set of lines, except that edges separating -%% coplanar faces will not be drawn. -%% -%% `?GLU_POINT': Quadrics are rendered as a set of points. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricDrawStyle.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluQuadricDrawStyle.xml">external</a> documentation. -spec quadricDrawStyle(Quad, Draw) -> 'ok' when Quad :: integer(),Draw :: enum(). quadricDrawStyle(Quad,Draw) -> cast(5029, <<Quad:?GLUquadric,Draw:?GLenum>>). @@ -632,14 +327,7 @@ quadricDrawStyle(Quad,Draw) -> %% ``glu:quadricNormals'' specifies what kind of normals are desired for quadrics rendered %% with `Quad' . The legal values are as follows: %% -%% `?GLU_NONE': No normals are generated. -%% -%% `?GLU_FLAT': One normal is generated for every facet of a quadric. -%% -%% `?GLU_SMOOTH': One normal is generated for every vertex of a quadric. This is the -%% initial value. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricNormals.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluQuadricNormals.xml">external</a> documentation. -spec quadricNormals(Quad, Normal) -> 'ok' when Quad :: integer(),Normal :: enum(). quadricNormals(Quad,Normal) -> cast(5030, <<Quad:?GLUquadric,Normal:?GLenum>>). @@ -649,15 +337,7 @@ quadricNormals(Quad,Normal) -> %% ``glu:quadricOrientation'' specifies what kind of orientation is desired for quadrics %% rendered with `Quad' . The `Orientation' values are as follows: %% -%% `?GLU_OUTSIDE': Quadrics are drawn with normals pointing outward (the initial value). -%% -%% -%% `?GLU_INSIDE': Quadrics are drawn with normals pointing inward. -%% -%% Note that the interpretation of `outward' and `inward' depends on the quadric -%% being drawn. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricOrientation.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluQuadricOrientation.xml">external</a> documentation. -spec quadricOrientation(Quad, Orientation) -> 'ok' when Quad :: integer(),Orientation :: enum(). quadricOrientation(Quad,Orientation) -> cast(5031, <<Quad:?GLUquadric,Orientation:?GLenum>>). @@ -669,10 +349,7 @@ quadricOrientation(Quad,Orientation) -> %% coordinates are generated, and if `Texture' is `?GLU_FALSE', they are not. %% The initial value is `?GLU_FALSE'. %% -%% The manner in which texture coordinates are generated depends upon the specific quadric -%% rendered. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluQuadricTexture.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluQuadricTexture.xml">external</a> documentation. -spec quadricTexture(Quad, Texture) -> 'ok' when Quad :: integer(),Texture :: 0|1. quadricTexture(Quad,Texture) -> cast(5032, <<Quad:?GLUquadric,Texture:?GLboolean>>). @@ -682,17 +359,7 @@ quadricTexture(Quad,Texture) -> %% ``glu:scaleImage'' scales a pixel image using the appropriate pixel store modes to %% unpack data from the source image and pack data into the destination image. %% -%% When shrinking an image, ``glu:scaleImage'' uses a box filter to sample the source -%% image and create pixels for the destination image. When magnifying an image, the pixels -%% from the source image are linearly interpolated to create the destination image. -%% -%% A return value of zero indicates success, otherwise a GLU error code is returned (see {@link glu:errorString/1} -%% ). -%% -%% See the {@link gl:readPixels/7} reference page for a description of the acceptable values -%% for the `Format' , `TypeIn' , and `TypeOut' parameters. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluScaleImage.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluScaleImage.xml">external</a> documentation. -spec scaleImage(Format, WIn, HIn, TypeIn, DataIn, WOut, HOut, TypeOut, DataOut) -> integer() when Format :: enum(),WIn :: integer(),HIn :: integer(),TypeIn :: enum(),DataIn :: binary(),WOut :: integer(),HOut :: integer(),TypeOut :: enum(),DataOut :: mem(). scaleImage(Format,WIn,HIn,TypeIn,DataIn,WOut,HOut,TypeOut,DataOut) -> send_bin(DataIn), @@ -705,17 +372,7 @@ scaleImage(Format,WIn,HIn,TypeIn,DataIn,WOut,HOut,TypeOut,DataOut) -> %% is subdivided around the `z' axis into slices and along the `z' axis into %% stacks (similar to lines of longitude and latitude). %% -%% If the orientation is set to `?GLU_OUTSIDE' (with {@link glu:quadricOrientation/2} ), -%% then any normals generated point away from the center of the sphere. Otherwise, they -%% point toward the center of the sphere. -%% -%% If texturing is turned on (with {@link glu:quadricTexture/2} ), then texture coordinates -%% are generated so that `t' ranges from 0.0 at z=-radius to 1.0 at z=radius (`t' -%% increases linearly along longitudinal lines), and `s' ranges from 0.0 at the +`y' -%% axis, to 0.25 at the +`x' axis, to 0.5 at the -`y' axis, to 0.75 at the -`x' -%% axis, and back to 1.0 at the +`y' axis. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluSphere.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluSphere.xml">external</a> documentation. -spec sphere(Quad, Radius, Slices, Stacks) -> 'ok' when Quad :: integer(),Radius :: float(),Slices :: integer(),Stacks :: integer(). sphere(Quad,Radius,Slices,Stacks) -> cast(5034, <<Quad:?GLUquadric,Radius:?GLdouble,Slices:?GLint,Stacks:?GLint>>). @@ -727,13 +384,7 @@ sphere(Quad,Radius,Slices,Stacks) -> %% . A return value of `?GLU_TRUE' indicates success; a return value of `?GLU_FALSE' %% indicates failure. %% -%% To compute the coordinates (objX objY objZ), ``glu:unProject'' multiplies the normalized device coordinates -%% by the inverse of `Model' * `Proj' as follows: -%% -%% (objX objY objZ W)=INV(P M) ((2(winX-view[0]))/(view[2])-1(2(winY-view[1]))/(view[3])-1 2(winZ)-1 1) INV denotes matrix inversion. W is an unused variable, included for consistent -%% matrix notation. -%% -%% See <a href="http://www.opengl.org/sdk/docs/man/xhtml/gluUnProject.xml">external</a> documentation. +%% See <a href="https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluUnProject.xml">external</a> documentation. -spec unProject(WinX, WinY, WinZ, Model, Proj, View) -> {integer(),ObjX :: float(),ObjY :: float(),ObjZ :: float()} when WinX :: float(),WinY :: float(),WinZ :: float(),Model :: matrix(),Proj :: matrix(),View :: {integer(),integer(),integer(),integer()}. unProject(WinX,WinY,WinZ,{M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16},{P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16},{V1,V2,V3,V4}) -> call(5035, <<WinX:?GLdouble,WinY:?GLdouble,WinZ:?GLdouble,M1:?GLdouble,M2:?GLdouble,M3:?GLdouble,M4:?GLdouble,M5:?GLdouble,M6:?GLdouble,M7:?GLdouble,M8:?GLdouble,M9:?GLdouble,M10:?GLdouble,M11:?GLdouble,M12:?GLdouble,M13:?GLdouble,M14:?GLdouble,M15:?GLdouble,M16:?GLdouble,P1:?GLdouble,P2:?GLdouble,P3:?GLdouble,P4:?GLdouble,P5:?GLdouble,P6:?GLdouble,P7:?GLdouble,P8:?GLdouble,P9:?GLdouble,P10:?GLdouble,P11:?GLdouble,P12:?GLdouble,P13:?GLdouble,P14:?GLdouble,P15:?GLdouble,P16:?GLdouble,V1:?GLint,V2:?GLint,V3:?GLint,V4:?GLint>>); diff --git a/lib/wx/test/wx_app_SUITE.erl b/lib/wx/test/wx_app_SUITE.erl index 3fd5bf689d..a5202d8448 100644 --- a/lib/wx/test/wx_app_SUITE.erl +++ b/lib/wx/test/wx_app_SUITE.erl @@ -24,7 +24,12 @@ %%---------------------------------------------------------------------- -module(wx_app_SUITE). --compile(export_all). +-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, + init_per_suite/1, end_per_suite/1, + init_per_testcase/2, end_per_testcase/2]). + +-export([t/0, t/1, fields/1, modules/1, exportall/1, app_depend/1, + undef_funcs/0, undef_funcs/1, appup/1]). -include("wx_test_lib.hrl"). -include_lib("common_test/include/ct.hrl"). diff --git a/lib/wx/test/wx_basic_SUITE.erl b/lib/wx/test/wx_basic_SUITE.erl index d53bd3c15a..ad03a378de 100644 --- a/lib/wx/test/wx_basic_SUITE.erl +++ b/lib/wx/test/wx_basic_SUITE.erl @@ -28,7 +28,11 @@ init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2]). --compile(export_all). +-export([silent_start/1, create_window/1, several_apps/1, wx_api/1, wx_misc/1, + data_types/1, wx_object/1, undef_in_handle_info/1, undef_in_terminate/1, + undef_handle_event/1, undef_handle_call/1, undef_handle_cast/1, undef_handle_info/1, + undef_code_change/1, undef_terminate1/1, undef_terminate2/1 + ]). -include("wx_test_lib.hrl"). diff --git a/lib/wx/test/wx_class_SUITE.erl b/lib/wx/test/wx_class_SUITE.erl index 0a3c4659bf..6d314ab8fc 100644 --- a/lib/wx/test/wx_class_SUITE.erl +++ b/lib/wx/test/wx_class_SUITE.erl @@ -29,7 +29,10 @@ init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2]). --compile(export_all). +-export([calendarCtrl/1, treeCtrl/1, notebook/1, staticBoxSizer/1, + clipboard/1, helpFrame/1, htmlWindow/1, listCtrlSort/1, listCtrlVirtual/1, + radioBox/1, systemSettings/1, taskBarIcon/1, toolbar/1, popup/1, modal/1, + textCtrl/1, locale/1]). -include("wx_test_lib.hrl"). @@ -51,7 +54,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap,{minutes,2}}]. all() -> [calendarCtrl, treeCtrl, notebook, staticBoxSizer, clipboard, helpFrame, htmlWindow, listCtrlSort, listCtrlVirtual, - radioBox, systemSettings, taskBarIcon, toolbar, popup, modal]. + radioBox, systemSettings, taskBarIcon, toolbar, popup, modal, + textCtrl, locale]. groups() -> []. diff --git a/lib/wx/test/wx_event_SUITE.erl b/lib/wx/test/wx_event_SUITE.erl index 6512cedaf2..a564f89e58 100644 --- a/lib/wx/test/wx_event_SUITE.erl +++ b/lib/wx/test/wx_event_SUITE.erl @@ -27,7 +27,10 @@ init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2]). --compile(export_all). +-export([connect/1, disconnect/1, disconnect_cb/1, connect_msg_20/1, connect_cb_20/1, + mouse_on_grid/1, spin_event/1, connect_in_callback/1, recursive/1, + dialog/1, char_events/1, callback_clean/1, handler_clean/1 + ]). -include("wx_test_lib.hrl"). @@ -49,7 +52,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, {timetrap,{minutes,2}}]. all() -> [connect, disconnect, disconnect_cb, connect_msg_20, connect_cb_20, mouse_on_grid, spin_event, connect_in_callback, recursive, - dialog, char_events, callback_clean + dialog, char_events, callback_clean, handler_clean ]. groups() -> @@ -577,6 +580,7 @@ handler_clean(_Config) -> Frame1 = wx_obj_test:start([{init, Init}]), ?mt(wxFrame, Frame1), wxWindow:show(Frame1), + timer:sleep(500), ?m([_|_], lists:sort(wx_test_lib:flush())), ?m(ok, wx_obj_test:stop(Frame1)), ?m([{terminate,normal}], lists:sort(wx_test_lib:flush())), @@ -584,6 +588,7 @@ handler_clean(_Config) -> Terminate = fun({Frame,_}) -> wxWindow:destroy(Frame) end, Frame2 = wx_obj_test:start([{init, Init}, {terminate, Terminate}]), wxWindow:show(Frame2), + timer:sleep(500), ?m([_|_], lists:sort(wx_test_lib:flush())), ?m(ok, wx_obj_test:stop(Frame2)), ?m([{terminate,normal}], lists:sort(wx_test_lib:flush())), diff --git a/lib/wx/test/wx_oc_object.erl b/lib/wx/test/wx_oc_object.erl index 3924202410..bc9b7d48d0 100644 --- a/lib/wx/test/wx_oc_object.erl +++ b/lib/wx/test/wx_oc_object.erl @@ -20,9 +20,9 @@ -module(wx_oc_object). -include_lib("wx/include/wx.hrl"). --behaviour(wx_object). +%%-behaviour(wx_object). %% commented out avoid warnings -%% gen_server callbacks +%% wx_object callbacks -export([init/1]). -record(state, {}). diff --git a/lib/wx/test/wx_opengl_SUITE.erl b/lib/wx/test/wx_opengl_SUITE.erl index 3de9209fae..19ea731dfb 100644 --- a/lib/wx/test/wx_opengl_SUITE.erl +++ b/lib/wx/test/wx_opengl_SUITE.erl @@ -27,7 +27,7 @@ init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2]). --compile(export_all). +-export([canvas/1, glu_tesselation/1]). -include("wx_test_lib.hrl"). -include_lib("wx/include/gl.hrl"). diff --git a/lib/wx/test/wx_test_lib.erl b/lib/wx/test/wx_test_lib.erl index 9f26b8cb9d..af508ff490 100644 --- a/lib/wx/test/wx_test_lib.erl +++ b/lib/wx/test/wx_test_lib.erl @@ -24,7 +24,10 @@ %%% Created : 30 Oct 2008 by Dan Gudmundsson <[email protected]> %%%------------------------------------------------------------------- -module(wx_test_lib). --compile(export_all). +-export([init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2]). +-export([tc_info/1, log/2, log/4, verbose/4, error/4, + flush/0, pick_msg/0, user_available/1, wx_destroy/2, wx_close/2, wait_for_close/0, + run_test/2, run_test/3, test_case_evaluator/3]). -include("wx_test_lib.hrl"). @@ -182,11 +185,15 @@ run_test([], _Config) -> []. run_test(Module, all, Config) -> All = [{Module, Test} || Test <- Module:all()], run_test(All, Config); +run_test(Module, {group, Group}, Config) -> + {_, _, TCs} = lists:keyfind(Group, 1, Module:groups()), + All = [{Module, Test} || Test <- TCs], + run_test(All, Config); + run_test(Module, TestCase, Config) -> log("Eval test case: ~w~n", [{Module, TestCase}]), Sec = timer:seconds(1) * 1000, - {T, Res} = - timer:tc(?MODULE, eval_test_case, [Module, TestCase, Config]), + {T, Res} = timer:tc(fun() -> eval_test_case(Module, TestCase, Config) end), log("Tested ~w in ~w sec~n", [TestCase, T div Sec]), {T div Sec, Res}. diff --git a/lib/wx/test/wx_xtra_SUITE.erl b/lib/wx/test/wx_xtra_SUITE.erl index c6268a7f46..486843ec63 100644 --- a/lib/wx/test/wx_xtra_SUITE.erl +++ b/lib/wx/test/wx_xtra_SUITE.erl @@ -28,7 +28,8 @@ init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2]). --compile(export_all). +-export([destroy_app/1, multiple_add_in_sizer/1, app_dies/1, + menu_item_debug/1]). -include("wx_test_lib.hrl"). diff --git a/lib/wx/test/wxt.erl b/lib/wx/test/wxt.erl index 265cd5c981..2b380606d5 100644 --- a/lib/wx/test/wxt.erl +++ b/lib/wx/test/wxt.erl @@ -20,7 +20,7 @@ %% Description : Shortcuts for running tests with wx internal test_server %%------------------------------------------------------------------- -module(wxt). --compile(export_all). +-export([t/0, t/1, t/2, user/0, user/1,user/2]). %% Modules or suites can be shortcuts i.e. basic expands to wx_basic_SUITE. %% @@ -83,36 +83,6 @@ alias(Suite) when is_atom(Suite) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -config_fname() -> - "wx_test_case_config". - -%% Read default config file -read_config() -> - Fname = config_fname(), - wx_test_lib:log("Consulting file ~s...~n", [Fname]), - case file:consult(Fname) of - {ok, Config} -> - wx_test_lib:log("Read config ~w~n", [Config]), - Config; - _Error -> - Config = wx_test_lib:default_config(), - wx_test_lib:log("<>WARNING<> Using default config: ~w~n", [Config]), - Config - end. - -%% Write new default config file -write_config(Config) when is_list(Config) -> - Fname = config_fname(), - {ok, Fd} = file:open(Fname, write), - write_list(Fd, Config), - file:close(Fd). - -write_list(Fd, [H | T]) -> - ok = io:format(Fd, "~p.~n",[H]), - write_list(Fd, T); -write_list(_, []) -> - ok. - test_case_fname() -> "wx_test_case_info". diff --git a/lib/wx/vsn.mk b/lib/wx/vsn.mk index b9100e7c87..039fae322e 100644 --- a/lib/wx/vsn.mk +++ b/lib/wx/vsn.mk @@ -1 +1 @@ -WX_VSN = 1.8.1 +WX_VSN = 1.8.2 diff --git a/make/fakefop b/make/fakefop index 7beeddf0a5..7a34c4faf1 100755 --- a/make/fakefop +++ b/make/fakefop @@ -22,13 +22,13 @@ # Author: Tuncer Ayaz # -if [ $# -lt 6 ] +if [ $# -lt 8 ] then - echo "Usage: fakefop -c IGNORED -fo IGNORED -pdf OUTFILE" + echo "Usage: fakefop -c IGNORED -cache IGNORED -fo IGNORED -pdf OUTFILE" exit 1 fi -OUTFILE=$6 +OUTFILE=$8 echo -n -e '%PDF-1.4\n%\0342\0343\0317\0323\n\n' > $OUTFILE @@ -87,12 +87,12 @@ endobj xref 0 6 -0000000000 65536 f -0000000016 00000 n -0000000070 00000 n -0000000136 00000 n -0000000291 00000 n -0000000410 00000 n +0000000000 65536 f +0000000016 00000 n +0000000070 00000 n +0000000136 00000 n +0000000291 00000 n +0000000410 00000 n trailer << diff --git a/make/otp.mk.in b/make/otp.mk.in index 4232d37c2e..1d538fa528 100644 --- a/make/otp.mk.in +++ b/make/otp.mk.in @@ -139,7 +139,7 @@ endif # .PRECIOUS: %.erl %.fo -## Uncomment these lines and add .idl to suffixes above to have erlc +## Uncomment these lines and add .idl to suffixes above to have erlc ## eat IDL files ##$(EGEN)/%.erl: $(ESRC)/%.idl ## $(ERLC) $(IDL_FLAGS) $< @@ -239,7 +239,7 @@ ifeq ($(PDFCOLOR),) PDFCOLOR = \#960003 endif -# HTML & GIF files that always are generated and must be delivered +# HTML & GIF files that always are generated and must be delivered SGML_COLL_FILES = $(SGML_APPLICATION_FILES) $(SGML_PART_FILES) XML_COLL_FILES = $(XML_APPLICATION_FILES) $(XML_PART_FILES) DEFAULT_HTML_FILES = \ @@ -327,5 +327,4 @@ $(MAN9DIR)/%.9: %.xml escript $(DOCGEN)/priv/bin/codeline_preprocessing.escript $< $@ .fo.pdf: - $(FOP) -c $(FOP_CONFIG) -fo $< -pdf $@ - + $(FOP) -c $(FOP_CONFIG) -cache $(ERL_TOP)/make/$(TARGET)/fop-fonts.cache -fo $< -pdf $@ diff --git a/otp_versions.table b/otp_versions.table index b6527594da..c70a2c44d3 100644 --- a/otp_versions.table +++ b/otp_versions.table @@ -1,3 +1,4 @@ +OTP-20.1 : asn1-5.0.3 common_test-1.15.2 compiler-7.1.2 crypto-4.1 debugger-4.2.3 dialyzer-3.2.2 diameter-2.1 edoc-0.9.1 erl_docgen-0.7.1 erts-9.1 et-1.6.1 eunit-2.3.4 hipe-3.16.1 inets-6.4.2 kernel-5.4 mnesia-4.15.1 observer-2.5 os_mon-2.4.3 public_key-1.5 reltool-0.7.5 runtime_tools-1.12.2 sasl-3.1 snmp-5.2.7 ssh-4.6 ssl-8.2.1 stdlib-3.4.2 syntax_tools-2.1.3 tools-2.11 wx-1.8.2 # cosEvent-2.2.1 cosEventDomain-1.2.1 cosFileTransfer-1.2.1 cosNotification-1.2.2 cosProperty-1.2.2 cosTime-1.2.2 cosTransactions-1.3.2 eldap-1.2.2 erl_interface-3.10 ic-4.4.2 jinterface-1.8 megaco-3.18.2 odbc-2.12 orber-3.8.3 otp_mibs-1.1.1 parsetools-2.1.5 xmerl-1.3.15 : OTP-20.0.5 : erts-9.0.5 inets-6.4.1 # asn1-5.0.2 common_test-1.15.1 compiler-7.1.1 cosEvent-2.2.1 cosEventDomain-1.2.1 cosFileTransfer-1.2.1 cosNotification-1.2.2 cosProperty-1.2.2 cosTime-1.2.2 cosTransactions-1.3.2 crypto-4.0 debugger-4.2.2 dialyzer-3.2.1 diameter-2.0 edoc-0.9 eldap-1.2.2 erl_docgen-0.7 erl_interface-3.10 et-1.6 eunit-2.3.3 hipe-3.16 ic-4.4.2 jinterface-1.8 kernel-5.3.1 megaco-3.18.2 mnesia-4.15 observer-2.4 odbc-2.12 orber-3.8.3 os_mon-2.4.2 otp_mibs-1.1.1 parsetools-2.1.5 public_key-1.4.1 reltool-0.7.4 runtime_tools-1.12.1 sasl-3.0.4 snmp-5.2.6 ssh-4.5.1 ssl-8.2 stdlib-3.4.1 syntax_tools-2.1.2 tools-2.10.1 wx-1.8.1 xmerl-1.3.15 : OTP-20.0.4 : dialyzer-3.2.1 erts-9.0.4 # asn1-5.0.2 common_test-1.15.1 compiler-7.1.1 cosEvent-2.2.1 cosEventDomain-1.2.1 cosFileTransfer-1.2.1 cosNotification-1.2.2 cosProperty-1.2.2 cosTime-1.2.2 cosTransactions-1.3.2 crypto-4.0 debugger-4.2.2 diameter-2.0 edoc-0.9 eldap-1.2.2 erl_docgen-0.7 erl_interface-3.10 et-1.6 eunit-2.3.3 hipe-3.16 ic-4.4.2 inets-6.4 jinterface-1.8 kernel-5.3.1 megaco-3.18.2 mnesia-4.15 observer-2.4 odbc-2.12 orber-3.8.3 os_mon-2.4.2 otp_mibs-1.1.1 parsetools-2.1.5 public_key-1.4.1 reltool-0.7.4 runtime_tools-1.12.1 sasl-3.0.4 snmp-5.2.6 ssh-4.5.1 ssl-8.2 stdlib-3.4.1 syntax_tools-2.1.2 tools-2.10.1 wx-1.8.1 xmerl-1.3.15 : OTP-20.0.3 : asn1-5.0.2 compiler-7.1.1 erts-9.0.3 ssh-4.5.1 # common_test-1.15.1 cosEvent-2.2.1 cosEventDomain-1.2.1 cosFileTransfer-1.2.1 cosNotification-1.2.2 cosProperty-1.2.2 cosTime-1.2.2 cosTransactions-1.3.2 crypto-4.0 debugger-4.2.2 dialyzer-3.2 diameter-2.0 edoc-0.9 eldap-1.2.2 erl_docgen-0.7 erl_interface-3.10 et-1.6 eunit-2.3.3 hipe-3.16 ic-4.4.2 inets-6.4 jinterface-1.8 kernel-5.3.1 megaco-3.18.2 mnesia-4.15 observer-2.4 odbc-2.12 orber-3.8.3 os_mon-2.4.2 otp_mibs-1.1.1 parsetools-2.1.5 public_key-1.4.1 reltool-0.7.4 runtime_tools-1.12.1 sasl-3.0.4 snmp-5.2.6 ssl-8.2 stdlib-3.4.1 syntax_tools-2.1.2 tools-2.10.1 wx-1.8.1 xmerl-1.3.15 : diff --git a/scripts/pre-push b/scripts/pre-push new file mode 100755 index 0000000000..0349378056 --- /dev/null +++ b/scripts/pre-push @@ -0,0 +1,202 @@ +#!/bin/sh + +# This is a git pre-push hook script. +# It limits what you can push toward https://github.com/erlang/otp.git +# +# To activate, make a copy as .git/hooks/pre-push in your repo. + +# Called by "git push" +# after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# <local ref> <local sha1> <remote ref> <remote sha1> +# + +RELEASES="20 19 18 17 r16 r15 r14 r13" + +# First commit on master, not allowed in other branches +MASTER_ONLY=f52748254f17ba42e344798e8c787a1e3361fa33 + +# Number of commits and files allowed in one push by this script +NCOMMITS_MAX=100 +NFILES_MAX=100 + +remote="$1" +url="$2" + +null=0000000000000000000000000000000000000000 + +#echo "pre-push hook: remote=$remote" +#echo "pre-push hook: url=$url" + +if [ "$url" = 'https://github.com/erlang/otp.git' -o "$url" = '[email protected]:erlang/otp.git' ] +then + if [ $remote = "$url" ]; then + echo "$0 says:" + echo "***" + echo "*** Push to $url without using a named remote is NOT ALLOWED!!!!" + echo "***" + exit 1 + fi + IFS=' ' + while read local_ref local_sha remote_ref remote_sha + do + #echo "pre-push hook: local_ref=$local_ref" + #echo "pre-push hook: remote_ref=$remote_ref" + #echo "pre-push hook: local_sha=$local_sha" + #echo "pre-push hook: remote_sha=$remote_sha" + + if [ "$local_sha" = $null ] + then + echo "$0 says:" + echo "***" + echo "*** DELETE push to '$remote' NOT ALLOWED!!!!!" + echo "***" + exit 1 + fi + if [ "$local_ref" != "$remote_ref" ] + then + echo "$0 says:" + echo "***" + echo "*** RENAME push: $local_ref pushed as $remote_ref to '$remote' NOT ALLOWED!!!!" + echo "***" + exit 1 + fi + case "$remote_ref" in + refs/heads/master | refs/heads/maint | refs/heads/maint-[0-9][0-9] | refs/heads/maint-r[0-9][0-9]) + branch=${remote_ref#refs/heads/} + if [ "$remote_sha" = $null ] + then + echo "$0 says:" + echo "***" + echo "*** UNKNOWN BRANCH: '$branch' does not exist at '$remote'!!!!" + echo "***" + exit 1 + fi + if ! git log -1 --oneline $remote_sha > /dev/null 2>&1 + then + echo "$0 says:" + echo "***" + echo "*** The top of '$branch' at '$remote' ($remote_sha)" + echo "*** does not exist locally!!!" + echo "*** You probably need to refresh local '$branch' and redo merge." + echo "***" + exit 1 + fi + if ! git merge-base --is-ancestor $remote_sha $local_sha + then + echo "$0 says:" + echo "***" + echo "*** FORCE push branch to '$remote' NOT ALLOWED!!!" + echo "***" + exit 1 + fi + if [ $remote_ref != refs/heads/master -a "$MASTER_ONLY" ] && git merge-base --is-ancestor $MASTER_ONLY $local_sha + then + echo "$0 says:" + echo "***" + echo "*** INVALID MERGE: Commit $MASTER_ONLY should not be reachable from '$branch'!!!!" + echo "*** You have probably merged master into '$branch' by mistake" + echo "***" + exit 1 + fi + if [ ${remote_ref#refs/heads/maint-} != $remote_ref ] && git merge-base --is-ancestor refs/remotes/$remote/maint $local_sha + then + echo "$0 says:" + echo "***" + echo "*** INVALID MERGE: Branch maint should not be reachable from '$branch'!!!!" + echo "*** You have probably merged maint into '$branch' by mistake." + echo "***" + exit 1 + fi + if [ $remote_ref = refs/heads/maint -o $remote_ref = refs/heads/master ]; then + for x in $RELEASES; do + if ! git merge-base --is-ancestor refs/remotes/$remote/maint-$x $local_sha; then + echo "$0 says:" + echo "***" + echo "*** WARNING: Branch '$remote/maint-$x' is not reachable from '$branch'!!!!" + echo "*** Someone needs to merge 'maint-$x' forward and push." + echo "***" + fi + done + fi + if [ $remote_ref = refs/heads/master ] && ! git merge-base --is-ancestor refs/remotes/$remote/maint $local_sha + then + echo "$0 says:" + echo "***" + echo "*** INVALID PUSH: Branch '$remote/maint' is not reachable from master!!!!" + echo "*** Someone needs to merge maint forward to master and push." + echo "***" + exit 1 + fi + NCOMMITS=`git rev-list --count $remote_sha..$local_sha` + if [ $NCOMMITS -gt $NCOMMITS_MAX ] + then + echo "$0 says:" + echo "***" + echo "*** HUGE push: $NCOMMITS commits (> $NCOMMITS_MAX) to '$branch' at '$remote' NOT ALLOWED!!!!" + echo "***" + exit 1 + fi + NFILES=`git diff --name-only $remote_sha $local_sha | wc --lines` + if [ $NFILES -gt $NFILES_MAX ] + then + echo "$0 says:" + echo "***" + echo "*** HUGE push: $NFILES changed files (> $NFILES_MAX) to '$branch' at '$remote' NOT ALLOWED!!!!" + echo "***" + exit 1 + fi + ;; + refs/tags/OTP-20.* | refs/tags/OTP-19.* | refs/tags/OTP-18.* | refs/tags/OTP-17.*) + tag=${remote_ref#refs/tags/} + if [ "$remote_sha" != $null ] + then + echo "$0 says:" + echo "***" + echo "*** FORCE push tag to '$remote' NOT ALLOWED!!!" + echo "*** Tag '$tag' already exists at '$remote'." + echo "***" + exit 1 + fi + ;; + refs/heads/*) + branch=${remote_ref#refs/heads/} + echo "$0 says:" + echo "***" + echo "*** UNKNOWN branch name: '$branch' pushed to '$remote' NOT ALLOWED!!!!" + echo "***" + exit 1 + ;; + refs/tags/*) + tag=${remote_ref#refs/tags/} + echo "$0 says:" + echo "***" + echo "*** UNKNOWN tag name: '$tag' pushed to '$remote' NOT ALLOWED!!!!" + echo "***" + exit 1 + ;; + *) + echo "$0 says:" + echo "***" + echo "*** STRANGE ref: '$remote_ref' pushed to '$remote' NOT ALLOWED!!!!" + echo "***" + exit 1 + ;; + esac + done +else + echo "$0: No checks done for remote '$remote' at $url." +fi + +exit 0 diff --git a/system/doc/design_principles/des_princ.xml b/system/doc/design_principles/des_princ.xml index af5904ce78..e21f2a7f4e 100644 --- a/system/doc/design_principles/des_princ.xml +++ b/system/doc/design_principles/des_princ.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>1997</year><year>2016</year> + <year>1997</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/system/doc/oam/oam_intro.xml b/system/doc/oam/oam_intro.xml index b4142b3cc5..d3867f03ca 100644 --- a/system/doc/oam/oam_intro.xml +++ b/system/doc/oam/oam_intro.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>1997</year><year>2016</year> + <year>1997</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/system/doc/reference_manual/typespec.xml b/system/doc/reference_manual/typespec.xml index a0ea41cb3b..f6a19397c3 100644 --- a/system/doc/reference_manual/typespec.xml +++ b/system/doc/reference_manual/typespec.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2003</year><year>2016</year> + <year>2003</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -133,17 +133,17 @@ Map :: map() %% denotes a map of any size | #{} %% denotes the empty map - | #{PairList} + | #{AssociationList} Tuple :: tuple() %% denotes a tuple of any size | {} | {TList} - PairList :: Pair - | Pair, PairList + AssociationList :: Association + | Association, AssociationList - Pair :: Type := Type %% denotes a mandatory pair - | Type => Type %% denotes an optional pair + Association :: Type := Type %% denotes a mandatory association + | Type => Type %% denotes an optional association TList :: Type | Type, TList @@ -173,14 +173,17 @@ The notation <c>[]</c> specifies the singleton type for the empty list. </p> <p> - The general form of maps is <c>#{PairList}</c>. The key types in - <c>PairList</c> are allowed to overlap, and if they do, the - leftmost pair takes precedence. A map pair has a key in - <c>PairList</c> if it belongs to this type. A <c>PairList</c> may contain - both 'mandatory' and 'optional' pairs where 'mandatory' denotes that - a key type, and its associated value type, must be present. - In the case of an 'optional' pair it is not required for the key type to - be present. + The general form of map types is <c>#{AssociationList}</c>. + The key types in + <c>AssociationList</c> are allowed to overlap, and if they do, the + leftmost association takes precedence. A map association has a key in + <c>AssociationList</c> if it belongs to this type. + <c>AssociationList</c> can contain both mandatory and optional + association types. + If an association type is mandatory, an association with that type + is to be present. + In the case of an optional association type it is not required for + the key type to be present. </p> <p> Notice that the syntactic representation of <c>map()</c> is @@ -512,8 +515,8 @@ <p> Currently, the <c>::</c> constraint (read as «is a subtype of») is - the only guard constraint that can be used in the <c>'when'</c> - part of a <c>'-spec'</c> attribute. + the only guard constraint that can be used in the <c>when</c> + part of a <c>-spec</c> attribute. </p> <note> <p> |