I wrote trait wrapper boilerpalte codegen
This commit is contained in:
parent
9a9a5b1b0f
commit
8cb684d82e
@ -17,11 +17,9 @@ execute_process(
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
#add_compile_options("-I/nix/store/2hm4rjvywd00p417y43i9rzx8v793qi0-pipewire-1.4.5-dev/include/pipewire-0.3 -I/nix/store/2hm4rjvywd00p417y43i9rzx8v793qi0-pipewire-1.4.5-dev/include/spa-0.2")
|
||||
message(INFO ${LIBPIPEWIRE_CFLAGS})
|
||||
|
||||
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \
|
||||
# -I /nix/store/2hm4rjvywd00p417y43i9rzx8v793qi0-pipewire-1.4.5-dev/include/pipewire-0.3 \
|
||||
# -I /nix/store/2hm4rjvywd00p417y43i9rzx8v793qi0-pipewire-1.4.5-dev/include/spa-0.2 ")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBPIPEWIRE_CFLAGS}")
|
||||
|
||||
add_compile_definitions(_POSIX_C_SOURCE=200112L)
|
||||
add_compile_definitions(_GNU_SOURCE)
|
||||
@ -43,8 +41,12 @@ add_executable(codegen_l1_5 src/l1_5/anne/codegen.c)
|
||||
#add_executable(1_render_test src/l2/tests/r1/r1.c gen/l_wl_protocols/xdg-shell-private.c)
|
||||
#target_link_libraries(1_render_test -lwayland-client -lrt -lm -lxkbcommon)
|
||||
#
|
||||
#add_executable(2a_render_test src/l2/tests/r2/r2a.c gen/l_wl_protocols/xdg-shell-private.c)
|
||||
#target_link_libraries(2a_render_test ${LIBPIPEWIRE_LIBS} -lwayland-client -lrt -lm -lxkbcommon)
|
||||
add_executable(r2a src/l2/tests/r2/r2a.c gen/l_wl_protocols/xdg-shell-private.c)
|
||||
target_link_libraries(r2a ${LIBPIPEWIRE_LIBS} -lwayland-client -lrt -lm -lxkbcommon)
|
||||
|
||||
add_executable(r2c src/l2/tests/r2/r2c.c)
|
||||
target_link_libraries(r2c -lm)
|
||||
|
||||
#
|
||||
#add_executable(3_render_test src/l2/tests/r3/r3.c gen/l_wl_protocols/xdg-shell-private.c)
|
||||
#target_link_libraries(3_render_test -lwayland-client -lm -lvulkan -lxkbcommon)
|
||||
|
||||
@ -209,7 +209,7 @@ NODISCARD VecU8 VecU8_fmt(const char* fmt, ...) {
|
||||
}
|
||||
|
||||
// todo: generate a special span method to check equality of contents
|
||||
bool strings_in_spans_equal(SpanU8 a, SpanU8 b) {
|
||||
bool SpanU8_cont_equal(SpanU8 a, SpanU8 b) {
|
||||
if (a.len != b.len)
|
||||
return false;
|
||||
for (size_t i = 0; i < a.len; i++) {
|
||||
|
||||
@ -3,38 +3,38 @@
|
||||
int main(){
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%i", 0);
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("0")));
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("0")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%i%i%i%i", -1LL, 0LL, 44LL, -231LL);
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("-1044-231")));
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("-1044-231")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%i", 44LL);
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("44")));
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("44")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%u", 44ULL);
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("44")));
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("44")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%u %i", 18446744073709551615ULL, -1LL);
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("18446744073709551615 -1")));
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("18446744073709551615 -1")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 res = VecU8_fmt("%i %i", 9223372036854775807LL, -9223372036854775807LL-1);
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("9223372036854775807 -9223372036854775808")));
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("9223372036854775807 -9223372036854775808")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
{
|
||||
VecU8 vec2 = vcstr("vec2");
|
||||
VecU8 res = VecU8_fmt("%i %v %i", -1230LL, vec2, 1340LL);
|
||||
check(strings_in_spans_equal(VecU8_to_span(&res), cstr("-1230 vec2 1340")));
|
||||
check(SpanU8_cont_equal(VecU8_to_span(&res), cstr("-1230 vec2 1340")));
|
||||
VecU8_drop(res);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
int main() {
|
||||
mkdir_nofail("l1_5");
|
||||
mkdir_nofail("l1_5/eve");
|
||||
generate_l1_5_liza_headers();
|
||||
generate_l1_5_template_instantiation_for_base_types();
|
||||
generate_l1_5_template_instantiations_for_margaret();
|
||||
|
||||
@ -4,8 +4,30 @@
|
||||
#include "../codegen/trait_wrap_boil.h"
|
||||
|
||||
void generate_l1_5_liza_headers() {
|
||||
mkdir_nofail("l1_5/liza");
|
||||
// todo: use#include "../codegen/trait_wrap_boil.h"
|
||||
mkdir_nofail("l1_5/eve/liza");
|
||||
SpanU8 l = cstr("l1_5"), ns = cstr("liza");
|
||||
generate_trait_wrapper_templ_inst_eve_header(l, ns, (trait_wrapper_boil_options){
|
||||
.trait = {
|
||||
.name = cstr("LizaInstrument"),
|
||||
.methods = (SpanNamedMethodSignatureRecordRef){
|
||||
// todo: request options for instrument
|
||||
.data = (NamedMethodSignatureRecordRef[]){
|
||||
{
|
||||
.takes_self = true,
|
||||
.params = (SpanNamedVariableRecordRef){
|
||||
.data = (NamedVariableRecordRef[]){
|
||||
{.type = cstr("double"), .name = cstr("frequency") },
|
||||
{ .type = cstr("double"), .name = cstr("time") },
|
||||
}, .len = 2
|
||||
},
|
||||
.return_type = cstr("BoxLizaSound"),
|
||||
.name = cstr("ding"),
|
||||
}
|
||||
}, .len = 1
|
||||
}
|
||||
},
|
||||
.box = true, .ref = true, .mut_ref = true
|
||||
});
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -414,7 +414,8 @@ NODISCARD VecU8 generate_rbtree_Map_template_instantiation(map_instantiation_op
|
||||
return res;
|
||||
}
|
||||
|
||||
void generate_rbtree_Map_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, map_instantiation_op op, bool generate_node_struct) {
|
||||
void generate_rbtree_Map_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, map_instantiation_op op,
|
||||
bool generate_node_struct) {
|
||||
generate_SOME_templ_inst_eve_header(layer, bonus_ns,
|
||||
generate_rbtree_Map_template_instantiation(op, generate_node_struct), get_name_of_rbtree_map_structure(op));
|
||||
}
|
||||
|
||||
@ -11,6 +11,8 @@ typedef struct {
|
||||
#include "../../../gen/l1/eve/embassy_l1_5/SpanNamedVariableRecordRef.h"
|
||||
|
||||
typedef struct {
|
||||
bool takes_self;
|
||||
bool takes_mut_self;
|
||||
SpanNamedVariableRecordRef params;
|
||||
SpanU8 return_type;
|
||||
SpanU8 name;
|
||||
@ -20,24 +22,30 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
SpanNamedMethodSignatureRecordRef methods;
|
||||
bool drop_primitive;
|
||||
SpanU8 name;
|
||||
} NamedTraitDefRecordRef;
|
||||
|
||||
NODISCARD VecU8 generate_trait_table_structure(NamedTraitDefRecordRef trait){
|
||||
VecU8 res = VecU8_from_cstr("typedef struct {");
|
||||
// todo: add iteration macro
|
||||
VecU8 res = VecU8_from_cstr("typedef struct {\n");
|
||||
for (size_t i = 0; i < trait.methods.len; i++) {
|
||||
NamedMethodSignatureRecordRef method = *SpanNamedMethodSignatureRecordRef_at(trait.methods, i);
|
||||
VecU8_append_vec(&res, VecU8_fmt(SPACE "%s (*%s)(", method.return_type, method.name));
|
||||
if (method.takes_self) {
|
||||
VecU8_append_span(&res, method.takes_mut_self ? cstr("void*") : cstr("const void*"));
|
||||
}
|
||||
for (size_t p = 0; p < method.params.len; p++) {
|
||||
NamedVariableRecordRef param = *SpanNamedVariableRecordRef_at(method.params, p);
|
||||
if (p)
|
||||
if (p || method.takes_self)
|
||||
VecU8_append_span(&res, cstr(", "));
|
||||
VecU8_append_span(&res, param.type);
|
||||
}
|
||||
VecU8_append_span(&res, cstr(");\n"));
|
||||
}
|
||||
VecU8_append_vec(&res, VecU8_fmt("} %s;\n\n", trait.name));
|
||||
if (!trait.drop_primitive) {
|
||||
VecU8_append_span(&res, cstr(SPACE "void (*drop)(void*);\n"));
|
||||
}
|
||||
VecU8_append_vec(&res, VecU8_fmt("} %s_Table;\n\n", trait.name));
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -48,10 +56,114 @@ typedef struct {
|
||||
bool mut_ref;
|
||||
} trait_wrapper_boil_options;
|
||||
|
||||
/* (refkind, self_as_ptr) in {(Ref, false), (MutRef, false), (Box, true)} */
|
||||
void codegen_append_trait_wrapper_some_method_some_refkind(VecU8* res, SpanU8 trait_name,
|
||||
NamedMethodSignatureRecordRef method, SpanU8 refkind, bool self_as_ptr){
|
||||
VecU8_append_vec(res, VecU8_fmt(
|
||||
"%s %s%s_%s(%s%s%s self",
|
||||
/* return_type, refkind, trait.name, method.name, refkind, trait.name */
|
||||
method.return_type, refkind, trait_name, method.name, refkind, trait_name, self_as_ptr ? cstr("*") : cstr("")));
|
||||
for (size_t p = 0; p < method.params.len; p++) {
|
||||
NamedVariableRecordRef param = method.params.data[p];
|
||||
VecU8_append_vec(res, VecU8_fmt(", %s %s", param.type, param.name));
|
||||
}
|
||||
VecU8_append_span(res, cstr("){\n" SPACE));
|
||||
if (!SpanU8_cont_equal(method.return_type, cstr("void")))
|
||||
VecU8_append_span(res, cstr("return "));
|
||||
VecU8_append_vec(res, VecU8_fmt("self%s""t->%s(",
|
||||
self_as_ptr ? cstr("->") : cstr("."),
|
||||
method.name));
|
||||
if (method.takes_self) {
|
||||
VecU8_append_vec(res, VecU8_fmt("self%s""r", self_as_ptr ? cstr("->") : cstr(".")));
|
||||
}
|
||||
for (size_t p = 0; p < method.params.len; p++) {
|
||||
NamedVariableRecordRef param = method.params.data[p];
|
||||
if (p > 0 || method.takes_self)
|
||||
VecU8_append_span(res, cstr(", "));
|
||||
VecU8_append_span(res, param.name);
|
||||
}
|
||||
VecU8_append_span(res, cstr(");\n}\n\n"));
|
||||
}
|
||||
|
||||
NODISCARD VecU8 generate_trait_wrapper_boilerplate(trait_wrapper_boil_options op) {
|
||||
/* Checking */
|
||||
for (size_t i = 0; i < op.trait.methods.len; i++) {
|
||||
NamedMethodSignatureRecordRef method = op.trait.methods.data[i];
|
||||
assert(!method.takes_mut_self || method.takes_self);
|
||||
}
|
||||
|
||||
VecU8 res = VecU8_new();
|
||||
// todo: write it
|
||||
VecU8_append_vec(&res, generate_trait_table_structure(op.trait));
|
||||
if (op.ref) {
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"typedef struct {\n"
|
||||
SPACE "const void* r;\n"
|
||||
SPACE "const %s_Table* t;\n" /* op.trait.name */
|
||||
"} Ref%s;\n\n", /* op.trait.name */
|
||||
op.trait.name, op.trait.name));
|
||||
for (size_t i = 0; i < op.trait.methods.len; i++) {
|
||||
NamedMethodSignatureRecordRef method = op.trait.methods.data[i];
|
||||
if (method.takes_mut_self)
|
||||
continue;
|
||||
codegen_append_trait_wrapper_some_method_some_refkind(&res, op.trait.name, method, cstr("Ref"), false);
|
||||
}
|
||||
}
|
||||
if (op.mut_ref) {
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"typedef struct {\n"
|
||||
SPACE "void* r;\n"
|
||||
SPACE "const %s_Table* t;\n"
|
||||
"} MutRef%s;\n\n",
|
||||
op.trait.name, op.trait.name));
|
||||
for (size_t i = 0; i < op.trait.methods.len; i++) {
|
||||
NamedMethodSignatureRecordRef method = op.trait.methods.data[i];
|
||||
codegen_append_trait_wrapper_some_method_some_refkind(&res, op.trait.name, method, cstr("MutRef"), false);
|
||||
}
|
||||
}
|
||||
if (op.box) {
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"typedef struct {\n"
|
||||
SPACE "void* r;\n"
|
||||
SPACE "const %s_Table* t;\n"
|
||||
"} Box%s;\n\n",
|
||||
op.trait.name, op.trait.name));
|
||||
for (size_t i = 0; i < op.trait.methods.len; i++) {
|
||||
NamedMethodSignatureRecordRef method = op.trait.methods.data[i];
|
||||
codegen_append_trait_wrapper_some_method_some_refkind(&res, op.trait.name, method, cstr("Box"), true);
|
||||
}
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"void Box%s_drop(Box%s self){\n" /* trait.name, trait.name */
|
||||
"%s" /* epsilon / calling self.t->drop() */
|
||||
SPACE "free(self.r);\n"
|
||||
"}\n\n",
|
||||
op.trait.name, op.trait.name,
|
||||
op.trait.drop_primitive ? cstr("") : cstr(SPACE "self.t->drop(self.r);\n")));
|
||||
if (op.ref) {
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"Ref%s Box%s_ref(Box%s *self) {\n"
|
||||
SPACE "return (Ref%s){.r = self->r, .t = self->t};\n"
|
||||
"}\n\n", op.trait.name, op.trait.name, op.trait.name, op.trait.name));
|
||||
}
|
||||
if (op.mut_ref) {
|
||||
VecU8_append_vec(&res, VecU8_fmt(
|
||||
"MutRef%s Box%s_mut_ref(Box%s *self) {\n"
|
||||
SPACE "return (MutRef%s){.r = self->r, .t = self->t};\n"
|
||||
"}\n\n", op.trait.name, op.trait.name, op.trait.name, op.trait.name));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void generate_trait_wrapper_templ_inst_eve_header(SpanU8 layer, SpanU8 bonus_ns, trait_wrapper_boil_options op){
|
||||
generate_SOME_templ_inst_eve_header(layer, bonus_ns, generate_trait_wrapper_boilerplate(op),
|
||||
VecU8_from_span(op.trait.name));
|
||||
}
|
||||
|
||||
void generate_trait_wrapper_templ_inst_guarded_header(SpanU8 layer, SpanU8 bonus_ns, SpanU8 dependencies,
|
||||
trait_wrapper_boil_options op){
|
||||
generate_SOME_templ_inst_guarded_header(layer, bonus_ns,
|
||||
VecU8_fmt("#include <stdlib.h>\n%s", dependencies),
|
||||
generate_trait_wrapper_boilerplate(op), VecU8_from_span(op.trait.name));
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -29,7 +29,7 @@ bool string_contains_string_ignorecase(SpanU8 str1, SpanU8 str2) {
|
||||
|
||||
bool is_string_in_string_vec(SpanU8 a, const VecVecU8* B) {
|
||||
for (size_t i = 0; i < B->len; i++) {
|
||||
if (strings_in_spans_equal(a, VecU8_to_span(VecVecU8_at(B, i))))
|
||||
if (SpanU8_cont_equal(a, VecU8_to_span(VecVecU8_at(B, i))))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -2032,15 +2032,6 @@ void Alice_set_point_light(Alice* alice, int index, Pipeline0PointLight data){
|
||||
ubo->point_light_arr[index] = data;
|
||||
}
|
||||
|
||||
|
||||
void Alice_clear_screen_text(Alice* alice){
|
||||
LucyRenderer_clear(&alice->lucy_renderer);
|
||||
}
|
||||
|
||||
void Alice_add_screen_text(Alice* alice, RBTreeNodeLucyFaceFixedSize* ffs, vec4 color, SpanU8 text, ivec2 start_pos){
|
||||
LucyRenderer_add_text(&alice->lucy_renderer, ffs, color, 0, text, start_pos);
|
||||
}
|
||||
|
||||
/* This function actually consumes alice handler. Alice must not be used after */
|
||||
void Alice_mainloop(Alice* alice, const AliceCallbacks* callbacks) {
|
||||
alice->callbacks.on_wl_keyboard_key = callbacks->on_wl_keyboard_key;
|
||||
@ -2132,7 +2123,7 @@ void allie_alice_clear_text(Alice* alice){
|
||||
void allie_alice_add_text(Alice* alice, RBTreeNodeLucyFaceFixedSize* ffs,
|
||||
float color_x, float color_y, float color_z, float color_w, const U8* text_data, U64 text_len,
|
||||
S32 start_pos_x, S32 start_pos_y){
|
||||
LucyRenderer_add_text(&alice->lucy_renderer, ffs, (vec4){color_x, color_y, color_z, color_w}, 0,
|
||||
LucyRenderer_add_simple_label(&alice->lucy_renderer, ffs, (vec4){color_x, color_y, color_z, color_w}, 0,
|
||||
(SpanU8){text_data, text_len}, (ivec2){start_pos_x, start_pos_y});
|
||||
}
|
||||
|
||||
|
||||
@ -3,35 +3,7 @@
|
||||
|
||||
#include "playing_sound_loop.h"
|
||||
|
||||
// todo: rewrite with the help of l1_5
|
||||
|
||||
typedef struct {
|
||||
/* self (takes ownership) */
|
||||
void (*drop)(void*);
|
||||
/* self, frequency, time, returns: new sound box */
|
||||
BoxLizaSound (*ding)(const void*, double, double);
|
||||
// todo: request options for instrument
|
||||
} LizaInstrument_Table;
|
||||
|
||||
typedef struct {
|
||||
const void* r;
|
||||
const LizaInstrument_Table* t;
|
||||
} RefLizaInstrument;
|
||||
|
||||
typedef struct {
|
||||
void* r;
|
||||
const LizaInstrument_Table* t;
|
||||
} MutLizaInstrument;
|
||||
|
||||
typedef struct {
|
||||
void* m;
|
||||
const LizaInstrument_Table* t;
|
||||
} BoxLizaInstrument;
|
||||
|
||||
void BoxLizaInstrument_drop(BoxLizaInstrument self) {
|
||||
self.t->drop(self.m);
|
||||
}
|
||||
|
||||
#include "../../../gen/l1_5/eve/liza/LizaInstrument.h"
|
||||
#include "../../../gen/l1/eve/liza/VecBoxLizaInstrument.h"
|
||||
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
// todo: move loop here and rewrite with l1_5 help
|
||||
|
||||
#include "../../l1/core/int_primitives.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct {
|
||||
/* self (takes ownership) */
|
||||
|
||||
@ -6,12 +6,12 @@
|
||||
#include "../../../gen/l1/geom.h"
|
||||
|
||||
// todo: rewrite this crrp crap using instances
|
||||
typedef struct{
|
||||
vec4 color;
|
||||
vec2 pos;
|
||||
vec2 tex_cord;
|
||||
U32 tex_ind;
|
||||
} LucyVertex;
|
||||
// typedef struct{
|
||||
// vec4 color;
|
||||
// vec2 pos;
|
||||
// vec2 tex_cord;
|
||||
// U32 tex_ind;
|
||||
// } LucyVertex;
|
||||
|
||||
|
||||
typedef struct {
|
||||
@ -20,7 +20,8 @@ typedef struct {
|
||||
vec2 br_pos;
|
||||
vec2 lt_tex;
|
||||
vec2 br_tex;
|
||||
} LucyGlyphInstance;
|
||||
U32 tex_ind;
|
||||
} LucyRenderInstance;
|
||||
|
||||
typedef struct {
|
||||
MargaretEngineReference ve;
|
||||
@ -60,17 +61,21 @@ LucyRenderer LucyRenderer_new(
|
||||
.fragment_shader_code = read_file_by_path(VecU8_fmt("%s/gen/l_adele/lucy/frag.spv", root_dir)),
|
||||
.vertexBindingDescriptionCount = 1,
|
||||
.pVertexBindingDescriptions = (VkVertexInputBindingDescription[]){
|
||||
{ .binding = 0, .stride = sizeof(LucyVertex), .inputRate = VK_VERTEX_INPUT_RATE_VERTEX } },
|
||||
.vertexAttributeDescriptionCount = 4,
|
||||
{ .binding = 0, .stride = sizeof(LucyRenderInstance), .inputRate = VK_VERTEX_INPUT_RATE_INSTANCE } },
|
||||
.vertexAttributeDescriptionCount = 6,
|
||||
.pVertexAttributeDescriptions = (VkVertexInputAttributeDescription[]){
|
||||
{.location = 0, .binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT, .offset = offsetof(LucyVertex, color)},
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT, .offset = offsetof(LucyRenderInstance, color)},
|
||||
{.location = 1, .binding = 0,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(LucyVertex, pos)},
|
||||
.format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(LucyRenderInstance, lt_pos)},
|
||||
{.location = 2, .binding = 0,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(LucyVertex, tex_cord)},
|
||||
.format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(LucyRenderInstance, br_pos)},
|
||||
{.location = 3, .binding = 0,
|
||||
.format = VK_FORMAT_R32_UINT, .offset = offsetof(LucyVertex, tex_ind)},
|
||||
.format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(LucyRenderInstance, lt_tex)},
|
||||
{.location = 4, .binding = 0,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(LucyRenderInstance, br_tex)},
|
||||
{.location = 5, .binding = 0,
|
||||
.format = VK_FORMAT_R32_UINT, .offset = offsetof(LucyRenderInstance, tex_ind)},
|
||||
},
|
||||
.depthTestEnable = false, .depthWriteEnable = false, .blendEnable = true,
|
||||
});
|
||||
@ -88,10 +93,44 @@ void LucyRenderer_clear(LucyRenderer* self){
|
||||
self->glyphs_count = 0;
|
||||
}
|
||||
|
||||
void LucyRenderer_draw_char_glyph(LucyRenderer* self, vec4 color, ivec2 pos, LucyStoredGlyph* glyph){
|
||||
if (glyph->w > 0 && glyph->h > 0) {
|
||||
OptionLucyImage* img_slot = VecOptionLucyImage_mat(&self->cache->image_slots, glyph->img_slot_id);
|
||||
assert(img_slot->variant == Option_Some);
|
||||
LucyImage* img = &img_slot->some;
|
||||
float atlas_w = (float)img->img.width;
|
||||
float atlas_h = (float)img->img.height;
|
||||
ivec2 positioned = ivec2_add_ivec2(pos, glyph->bearing);
|
||||
|
||||
U64 needed_vbo_length = (self->glyphs_count + 1) * sizeof(LucyRenderInstance);
|
||||
if (self->staging_vbo.len < needed_vbo_length) {
|
||||
printf("LucyRenderer Staging Buffer: Gotta replace %lu with %lu\n",
|
||||
self->staging_vbo.len, needed_vbo_length);
|
||||
MargaretBufAllocator_expand_or_move_old_host_visible(
|
||||
self->ve.staging_buffers, &self->staging_vbo, needed_vbo_length);
|
||||
}
|
||||
|
||||
LucyRenderInstance* vbo_data = (LucyRenderInstance*)MargaretSubbuf_get_mapped(&self->staging_vbo);
|
||||
vbo_data[self->glyphs_count++] = (LucyRenderInstance){
|
||||
.color = color,
|
||||
.lt_pos = (vec2){(float)positioned.x, (float)positioned.y},
|
||||
.br_pos = (vec2){(float)(positioned.x + glyph->w), (float)(positioned.y + glyph->h)},
|
||||
.lt_tex = (vec2){
|
||||
(float)(glyph->pos_on_atlas.x) / atlas_w,
|
||||
(float)(glyph->pos_on_atlas.y) / atlas_h
|
||||
},
|
||||
.br_tex = (vec2){
|
||||
(float)(glyph->pos_on_atlas.x + glyph->w) / atlas_w,
|
||||
(float)(glyph->pos_on_atlas.y + glyph->h) / atlas_h
|
||||
}, .tex_ind = glyph->img_slot_id
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/* When another_frame starts, you are safe to call this function, but you also have to call it
|
||||
* before LucyRenderer_another_frame, because _another_frame method records transfer of data
|
||||
*/
|
||||
void LucyRenderer_add_text(
|
||||
void LucyRenderer_add_simple_label(
|
||||
LucyRenderer* self, RBTreeNodeLucyFaceFixedSize* ffs, vec4 color,
|
||||
U32 additional_y_advance, SpanU8 text, ivec2 start_pos
|
||||
){
|
||||
@ -114,70 +153,14 @@ void LucyRenderer_add_text(
|
||||
}
|
||||
assert(map_it > 0 && map_it < glyphs->tree.len);
|
||||
LucyStoredGlyph* glyph = &glyphs->el.buf[map_it - 1].value;
|
||||
if (glyph->w > 0 && glyph->h > 0) {
|
||||
OptionLucyImage* img_slot = VecOptionLucyImage_mat(&self->cache->image_slots, glyph->img_slot_id);
|
||||
assert(img_slot->variant == Option_Some);
|
||||
LucyImage* img = &img_slot->some;
|
||||
float atlas_w = (float)img->img.width;
|
||||
float atlas_h = (float)img->img.height;
|
||||
U32 desc_elem_id = glyph->img_slot_id;
|
||||
ivec2 positioned = ivec2_add_ivec2(pos, glyph->bearing);
|
||||
|
||||
U64 needed_vbo_length = (self->glyphs_count + 1) * 6 * sizeof(LucyVertex);
|
||||
if (self->staging_vbo.len < needed_vbo_length) {
|
||||
printf("LucyRenderer Staging Buffer: Gotta replace %lu with %lu\n",
|
||||
self->staging_vbo.len, needed_vbo_length);
|
||||
MargaretBufAllocator_expand_or_move_old_host_visible(
|
||||
self->ve.staging_buffers, &self->staging_vbo, needed_vbo_length);
|
||||
}
|
||||
|
||||
LucyVertex* vbo_data = (LucyVertex*)MargaretSubbuf_get_mapped(&self->staging_vbo);
|
||||
vbo_data += self->glyphs_count * 6;
|
||||
|
||||
LucyVertex v0 = {
|
||||
.color = color, .pos = (vec2){(float)positioned.x, (float)positioned.y},
|
||||
.tex_cord = (vec2){
|
||||
(float)(glyph->pos_on_atlas.x) / atlas_w,
|
||||
(float)(glyph->pos_on_atlas.y) / atlas_h
|
||||
}, .tex_ind = desc_elem_id
|
||||
};
|
||||
LucyVertex v1 = {
|
||||
.color = color, .pos = (vec2){(float)(positioned.x + glyph->w), (float)positioned.y},
|
||||
.tex_cord = (vec2){
|
||||
(float)(glyph->pos_on_atlas.x + glyph->w) / atlas_w,
|
||||
(float)(glyph->pos_on_atlas.y) / atlas_h
|
||||
}, .tex_ind = desc_elem_id
|
||||
};
|
||||
LucyVertex v2 = {
|
||||
.color = color, .pos = (vec2){(float)positioned.x, (float)(positioned.y + glyph->h)},
|
||||
.tex_cord = (vec2){
|
||||
(float)(glyph->pos_on_atlas.x) / atlas_w,
|
||||
(float)(glyph->pos_on_atlas.y + glyph->h) / atlas_h
|
||||
}, .tex_ind = desc_elem_id
|
||||
};
|
||||
LucyVertex v3 = {
|
||||
.color = color, .pos = (vec2){(float)(positioned.x + glyph->w), (float)(positioned.y + glyph->h)},
|
||||
.tex_cord = (vec2){
|
||||
(float)(glyph->pos_on_atlas.x + glyph->w) / atlas_w,
|
||||
(float)(glyph->pos_on_atlas.y + glyph->h) / atlas_h
|
||||
}, .tex_ind = desc_elem_id
|
||||
};
|
||||
*(vbo_data++) = v1;
|
||||
*(vbo_data++) = v0;
|
||||
*(vbo_data++) = v2;
|
||||
*(vbo_data++) = v1;
|
||||
*(vbo_data++) = v2;
|
||||
*(vbo_data++) = v3;
|
||||
|
||||
self->glyphs_count++;
|
||||
}
|
||||
LucyRenderer_draw_char_glyph(self, color, pos, glyph);
|
||||
pos.x += (S32)glyph->advance_x;
|
||||
}
|
||||
}
|
||||
|
||||
/* It only records transfer commands (transfer command buffer is passed in MargaretEngineReference object) */
|
||||
void LucyRenderer_another_frame(LucyRenderer* self){
|
||||
U64 needed_vbo_length = self->glyphs_count * 6 * sizeof(LucyVertex);
|
||||
U64 needed_vbo_length = self->glyphs_count * sizeof(LucyRenderInstance);
|
||||
if (self->vbo.len < needed_vbo_length) {
|
||||
MargaretBufAllocator_expand_or_free_old(self->ve.dev_local_buffers, &self->vbo, needed_vbo_length);
|
||||
}
|
||||
@ -201,7 +184,7 @@ void LucyRenderer_another_frame_rec_drawing(
|
||||
(VkBuffer[]){MargaretSubbuf_get_buffer(&self->vbo)}, (VkDeviceSize[]){self->vbo.start});
|
||||
vkCmdBindDescriptorSets(drawing_cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, self->pipeline_layout, 0,
|
||||
1, (VkDescriptorSet[]){self->cache->descriptor_set}, 0, NULL);
|
||||
vkCmdDraw(drawing_cmd_buf, self->glyphs_count * 6, 1, 0, 0);
|
||||
vkCmdDraw(drawing_cmd_buf, 6, self->glyphs_count, 0, 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -105,7 +105,7 @@ const LizaInstrument_Table LizaInstrument_Table_WeirdGuitar = {
|
||||
BoxLizaInstrument BoxLizaInstrument_from_WeirdGuitar(WeirdGuitar obj) {
|
||||
void* mem = safe_malloc(sizeof(WeirdGuitar));
|
||||
memcpy(mem, &obj, sizeof(WeirdGuitar));
|
||||
return (BoxLizaInstrument){.m = mem, .t = &LizaInstrument_Table_WeirdGuitar};
|
||||
return (BoxLizaInstrument){.r = mem, .t = &LizaInstrument_Table_WeirdGuitar};
|
||||
}
|
||||
|
||||
/* ElectroBlaster which produces AmplitudeModulationSound */
|
||||
@ -192,7 +192,7 @@ const LizaInstrument_Table LizaInstrument_Table_AMKeys = {
|
||||
BoxLizaInstrument BoxLizaInstrument_from_AMKeys(AMKeys obj) {
|
||||
void* mem = safe_malloc(sizeof(AMKeys));
|
||||
memcpy(mem, &obj, sizeof(AMKeys));
|
||||
return (BoxLizaInstrument){.m = mem, .t = &LizaInstrument_Table_AMKeys};
|
||||
return (BoxLizaInstrument){.r = mem, .t = &LizaInstrument_Table_AMKeys};
|
||||
}
|
||||
|
||||
/* FMKeys which produces FrequencyModulationSound */
|
||||
@ -278,7 +278,7 @@ const LizaInstrument_Table LizaInstrument_Table_FMKeys = {
|
||||
BoxLizaInstrument BoxLizaInstrument_from_FMKeys(FMKeys obj) {
|
||||
void* mem = safe_malloc(sizeof(FMKeys));
|
||||
memcpy(mem, &obj, sizeof(FMKeys));
|
||||
return (BoxLizaInstrument){.m = mem, .t = &LizaInstrument_Table_FMKeys};
|
||||
return (BoxLizaInstrument){.r = mem, .t = &LizaInstrument_Table_FMKeys};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -100,7 +100,8 @@ static void r2a_app_h_pw_stream_process(void *ug){
|
||||
return;
|
||||
}
|
||||
struct spa_buffer *buf = b->buffer;
|
||||
uint32_t stride = sizeof(int16_t) * DEFAULT_CHANNELS;
|
||||
assert(buf->n_datas >= 1);
|
||||
const uint32_t stride = sizeof(int16_t) * DEFAULT_CHANNELS;
|
||||
uint32_t n_frames = buf->datas[0].maxsize / stride;
|
||||
if (b->requested)
|
||||
n_frames = SPA_MIN(b->requested, n_frames);
|
||||
@ -515,12 +516,12 @@ static void r2a_app_h_wl_keyboard_key(
|
||||
};
|
||||
if (state->selected_instrument < state->instruments.len) {
|
||||
// todo: add box to ref and box to mref methods
|
||||
const BoxLizaInstrument* instrument = &VecMyInstrument_at(&state->instruments, state->selected_instrument)->liza;
|
||||
BoxLizaInstrument* instrument = &VecMyInstrument_mat(&state->instruments, state->selected_instrument)->liza;
|
||||
for (int i = 0; i < ARRAY_SIZE(octave); i++) {
|
||||
if (keysym == octave[i] && key_action == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
safe_pthread_mutex_lock(&state->audio_thread_bridge->mut);
|
||||
VecBoxLizaSound_append(&state->audio_thread_bridge->cmd.new_sounds,
|
||||
instrument->t->ding(instrument->m, 440 * pow(2, (double)i / 12), 0.9));
|
||||
BoxLizaInstrument_ding(instrument, 440 * pow(2, (double)i / 12), 0.9));
|
||||
safe_pthread_mutex_unlock(&state->audio_thread_bridge->mut);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -101,7 +101,7 @@ void BoxLizaSound_drop(BoxLizaSound self) {
|
||||
free(self.m);
|
||||
}
|
||||
|
||||
#include "../../../../gen/l2/eve/r2/VecBoxLizaSound.h"
|
||||
#include "../../../../gen/l1/eve/r2/VecBoxLizaSound.h"
|
||||
|
||||
typedef struct {
|
||||
bool stop;
|
||||
|
||||
232
src/l2/tests/r2/r2c.c
Normal file
232
src/l2/tests/r2/r2c.c
Normal file
@ -0,0 +1,232 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sound/asound.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define DESIRED_SAMPLE_RATE 44100
|
||||
#define DESIRED_CHANNELS 2 // Prefer stereo, as mono often not supported on hardware
|
||||
#define DESIRED_PERIOD_SIZE 1024
|
||||
#define DESIRED_PERIODS 4
|
||||
#define FORMAT SNDRV_PCM_FORMAT_S16_LE
|
||||
#define DURATION 5 // seconds
|
||||
#define BYTES_PER_SAMPLE 2
|
||||
|
||||
int main() {
|
||||
int card = -1, device = -1;
|
||||
FILE *proc = fopen("/proc/asound/pcm", "r");
|
||||
if (!proc) {
|
||||
perror("Failed to open /proc/asound/pcm");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Opened /proc/asound/pcm\n");
|
||||
|
||||
char line[256];
|
||||
while (fgets(line, sizeof(line), proc)) {
|
||||
if (strstr(line, "playback")) {
|
||||
sscanf(line, "%02d-%02d", &card, &device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(proc);
|
||||
|
||||
if (card < 0 || device < 0) {
|
||||
fprintf(stderr, "No playback devices found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char devname[64];
|
||||
snprintf(devname, sizeof(devname), "/dev/snd/pcmC%dD%dp", card, device);
|
||||
|
||||
int fd = open(devname, O_WRONLY);
|
||||
if (fd < 0) {
|
||||
perror("Failed to open PCM device");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Opened device\n");
|
||||
|
||||
struct snd_pcm_hw_params params;
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
||||
// Initialize to full possible ranges for refinement
|
||||
int i;
|
||||
for (i = SNDRV_PCM_HW_PARAM_FIRST_MASK; i <= SNDRV_PCM_HW_PARAM_LAST_MASK; i++) {
|
||||
struct snd_mask *mask = ¶ms.masks[i - SNDRV_PCM_HW_PARAM_FIRST_MASK];
|
||||
mask->bits[0] = ~0U;
|
||||
mask->bits[1] = ~0U;
|
||||
}
|
||||
for (i = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; i <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; i++) {
|
||||
struct snd_interval *interval = ¶ms.intervals[i - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
|
||||
interval->min = 0;
|
||||
interval->max = ~0U;
|
||||
interval->openmin = interval->openmax = 0;
|
||||
interval->integer = 0;
|
||||
}
|
||||
params.rmask = ~0U;
|
||||
params.cmask = 0;
|
||||
params.info = ~0U;
|
||||
|
||||
// Refine to hardware-supported ranges
|
||||
if (ioctl(fd, SNDRV_PCM_IOCTL_HW_REFINE, ¶ms) < 0) {
|
||||
perror("Failed initial HW_REFINE");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Refined hw params\n");
|
||||
|
||||
// Set access to RW_INTERLEAVED if supported
|
||||
struct snd_mask *access_mask = ¶ms.masks[SNDRV_PCM_HW_PARAM_ACCESS - SNDRV_PCM_HW_PARAM_FIRST_MASK];
|
||||
unsigned int access_bit = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
|
||||
if (!(access_mask->bits[access_bit / 32] & (1U << (access_bit % 32)))) {
|
||||
fprintf(stderr, "RW_INTERLEAVED access not supported\n");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
memset(access_mask, 0, sizeof(*access_mask));
|
||||
access_mask->bits[access_bit / 32] |= (1U << (access_bit % 32));
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_ACCESS);
|
||||
|
||||
// Set format to S16_LE if supported
|
||||
struct snd_mask *format_mask = ¶ms.masks[SNDRV_PCM_HW_PARAM_FORMAT - SNDRV_PCM_HW_PARAM_FIRST_MASK];
|
||||
unsigned int format_bit = FORMAT;
|
||||
if (!(format_mask->bits[format_bit / 32] & (1U << (format_bit % 32)))) {
|
||||
fprintf(stderr, "S16_LE format not supported\n");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
memset(format_mask, 0, sizeof(*format_mask));
|
||||
format_mask->bits[format_bit / 32] |= (1U << (format_bit % 32));
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_FORMAT);
|
||||
|
||||
// Set channels to nearest supported (prefer DESIRED_CHANNELS)
|
||||
struct snd_interval *channels_int = ¶ms.intervals[SNDRV_PCM_HW_PARAM_CHANNELS - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
|
||||
unsigned int channels = DESIRED_CHANNELS;
|
||||
if (channels < channels_int->min) channels = channels_int->min;
|
||||
if (channels > channels_int->max) channels = channels_int->max;
|
||||
if (channels != DESIRED_CHANNELS) {
|
||||
fprintf(stderr, "Adjusted channels to %u (hardware range: %u-%u)\n", channels, channels_int->min, channels_int->max);
|
||||
}
|
||||
channels_int->min = channels_int->max = channels;
|
||||
channels_int->integer = 1;
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_CHANNELS);
|
||||
|
||||
// Set sample rate to nearest supported
|
||||
struct snd_interval *rate_int = ¶ms.intervals[SNDRV_PCM_HW_PARAM_RATE - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
|
||||
unsigned int sample_rate = DESIRED_SAMPLE_RATE;
|
||||
if (sample_rate < rate_int->min) sample_rate = rate_int->min;
|
||||
if (sample_rate > rate_int->max) sample_rate = rate_int->max;
|
||||
if (sample_rate != DESIRED_SAMPLE_RATE) {
|
||||
fprintf(stderr, "Adjusted sample rate to %u Hz (hardware range: %u-%u)\n", sample_rate, rate_int->min, rate_int->max);
|
||||
}
|
||||
rate_int->min = rate_int->max = sample_rate;
|
||||
rate_int->integer = 1;
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_RATE);
|
||||
|
||||
// Set period size to nearest supported
|
||||
struct snd_interval *period_size_int = ¶ms.intervals[SNDRV_PCM_HW_PARAM_PERIOD_SIZE - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
|
||||
unsigned int period_size = DESIRED_PERIOD_SIZE;
|
||||
if (period_size < period_size_int->min) period_size = period_size_int->min;
|
||||
if (period_size > period_size_int->max) period_size = period_size_int->max;
|
||||
if (period_size != DESIRED_PERIOD_SIZE) {
|
||||
fprintf(stderr, "Adjusted period size to %u frames (hardware range: %u-%u)\n", period_size, period_size_int->min, period_size_int->max);
|
||||
}
|
||||
period_size_int->min = period_size_int->max = period_size;
|
||||
period_size_int->integer = 1;
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
|
||||
|
||||
// Set periods (less strict, clamp to range)
|
||||
struct snd_interval *periods_int = ¶ms.intervals[SNDRV_PCM_HW_PARAM_PERIODS - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
|
||||
unsigned int periods = DESIRED_PERIODS;
|
||||
if (periods < periods_int->min) periods = periods_int->min;
|
||||
if (periods > periods_int->max) periods = periods_int->max;
|
||||
if (periods != DESIRED_PERIODS) {
|
||||
fprintf(stderr, "Adjusted periods to %u (hardware range: %u-%u)\n", periods, periods_int->min, periods_int->max);
|
||||
}
|
||||
periods_int->min = periods_int->max = periods;
|
||||
periods_int->integer = 1;
|
||||
params.rmask |= (1U << SNDRV_PCM_HW_PARAM_PERIODS);
|
||||
|
||||
// Refine again with desired values to confirm
|
||||
if (ioctl(fd, SNDRV_PCM_IOCTL_HW_REFINE, ¶ms) < 0) {
|
||||
perror("Failed to refine desired HW params");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Refined hw params the last time\n");
|
||||
|
||||
// Now apply the parameters
|
||||
if (ioctl(fd, SNDRV_PCM_IOCTL_HW_PARAMS, ¶ms) < 0) {
|
||||
perror("Failed to set HW params");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("HW params set\n");
|
||||
|
||||
if (ioctl(fd, SNDRV_PCM_IOCTL_PREPARE, 0) < 0) {
|
||||
perror("Failed to prepare PCM");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Prepared\n");
|
||||
|
||||
// Generate and play sine wave
|
||||
size_t frame_size = channels * BYTES_PER_SAMPLE;
|
||||
short *buffer = malloc(period_size * frame_size);
|
||||
if (!buffer) {
|
||||
perror("Failed to allocate buffer");
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned long total_frames = (unsigned long)sample_rate * DURATION;
|
||||
unsigned long frames_written = 0;
|
||||
double phase = 0.0;
|
||||
const double freq = 440.0; // Hz
|
||||
const double phase_inc = 2.0 * M_PI * freq / sample_rate;
|
||||
|
||||
while (frames_written < total_frames) {
|
||||
size_t frames_to_write = period_size;
|
||||
if (frames_written + frames_to_write > total_frames) {
|
||||
frames_to_write = total_frames - frames_written;
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < frames_to_write; ++j) {
|
||||
short sample = (short)(32767.0 * sin(phase));
|
||||
for (unsigned int ch = 0; ch < channels; ++ch) {
|
||||
buffer[j * channels + ch] = sample;
|
||||
}
|
||||
phase += phase_inc;
|
||||
if (phase >= 2.0 * M_PI) phase -= 2.0 * M_PI;
|
||||
}
|
||||
|
||||
ssize_t bytes_written = write(fd, buffer, frames_to_write * frame_size);
|
||||
printf("bytes written = %lu\n", bytes_written);
|
||||
if (bytes_written < 0) {
|
||||
if (errno == EPIPE) {
|
||||
// Underrun: recover
|
||||
ioctl(fd, SNDRV_PCM_IOCTL_PREPARE, 0);
|
||||
continue;
|
||||
}
|
||||
perror("Write failed");
|
||||
break;
|
||||
}
|
||||
|
||||
frames_written += bytes_written / frame_size;
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
// Drain remaining data
|
||||
ioctl(fd, SNDRV_PCM_IOCTL_DRAIN, 0);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
@ -33,6 +33,14 @@ puckLevitationHeight = 0.4 + 0.2
|
||||
puckSpots :: [Vec2]
|
||||
puckSpots = [(Vec2 (-10) (-10)), (Vec2 (-15) (-15)) , (Vec2 (-18) (-18)), (Vec2 (-18) (-25)), (Vec2 (-18) (-30))]
|
||||
|
||||
introText :: String
|
||||
introText = "Накануне новогодняя сессия 2025 года. Все были готовы провести экзамен по матану, но злой Гринч похитил 67 " ++
|
||||
"шайб с бергамотом Матвея и улетел. Вся надежда была потеряна, но в полёте Гринч выронил все, и те упали в Дубки. Тебе " ++
|
||||
"необходимо вернуть их Матвею.\n" ++
|
||||
"Естесственно, вернёшь ты их Гринчу, так как ты и сам не понимаешь преобразования Фурье и хочешь помочь сорвать" ++
|
||||
"экзамен.\n\n" ++
|
||||
"Итак, ты в Дубках..."
|
||||
|
||||
main :: IO()
|
||||
main = do
|
||||
alice <- newAlice
|
||||
|
||||
@ -64,7 +64,7 @@ int main(){
|
||||
});
|
||||
|
||||
LucyGlyphCache_add_glyphs(lucy_requests);
|
||||
LucyRenderer_add_text(&st.alice->lucy_renderer, st.font_face_of_size_40, (vec4){0, 0, 0, 1}, 0,
|
||||
LucyRenderer_add_simple_label(&st.alice->lucy_renderer, st.font_face_of_size_40, (vec4){0, 0, 0, 1}, 0,
|
||||
cstr("Bebra budet\nотнюхана\n"), (ivec2){10, 10});
|
||||
|
||||
ListNodeAliceGenericMeshHand* model_gen = Alice_add_generic_mesh(st.alice, AliceGenericMeshPath_for_log(cstr("."), 10, 2, 6));
|
||||
|
||||
@ -13,4 +13,5 @@ layout (binding=0) uniform sampler2D images[];
|
||||
void main(){
|
||||
float I = texture(images[nonuniformEXT(tex_ind)], tex_cord).r;
|
||||
fin_color = vec4(color.rgb, color.a * I);
|
||||
//fin_color = vec4(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec4 color;
|
||||
layout(location = 1) in vec2 pos;
|
||||
layout(location = 2) in vec2 tex_cord;
|
||||
layout(location = 3) in uint tex_ind;
|
||||
layout(location = 1) in vec2 lt_pos;
|
||||
layout(location = 2) in vec2 br_pos;
|
||||
layout(location = 3) in vec2 lt_tex;
|
||||
layout(location = 4) in vec2 br_tex;
|
||||
layout(location = 5) in uint tex_ind;
|
||||
|
||||
layout(push_constant, std430) uniform pc {
|
||||
float width;
|
||||
@ -23,8 +25,17 @@ float deng(float B1, float x){
|
||||
}
|
||||
|
||||
void main(){
|
||||
const vec2 all_v_pos[6] = vec2[](
|
||||
vec2(br_pos.x, lt_pos.y), lt_pos, vec2(lt_pos.x, br_pos.y),
|
||||
vec2(br_pos.x, lt_pos.y), vec2(lt_pos.x, br_pos.y), br_pos
|
||||
);
|
||||
const vec2 all_v_tex[6] = vec2[](
|
||||
vec2(br_tex.x, lt_tex.y), lt_tex, vec2(lt_tex.x, br_tex.y),
|
||||
vec2(br_tex.x, lt_tex.y), vec2(lt_tex.x, br_tex.y), br_tex
|
||||
);
|
||||
vsout_color = color;
|
||||
vsout_tex_cord = tex_cord;
|
||||
vsout_tex_cord = all_v_tex[gl_VertexIndex % 6];
|
||||
vsout_tex_ind = tex_ind;
|
||||
vec2 pos = all_v_pos[gl_VertexIndex % 6];
|
||||
gl_Position = vec4(deng(width, pos.x), deng(height, pos.y), 0, 1);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user