// `abi(.c)` callbacks accessing struct methods on global pointers —
// regression coverage for prior data-corruption when the callback dispatches
// through a global pointer to a method on the pointed-to struct.

#import "modules/std.sx";

Pipe :: struct {
    pw: i32;
    ph: i32;
    frame: i32;

    resize :: (self: *Pipe, nw: i32, nh: i32) {
        self.pw = nw;
        self.ph = nh;
    }

    tick :: (self: *Pipe) {
        self.frame = self.frame + 1;
    }
}

g_pipe : *Pipe = ---;
g_width  : i32 = 800;
g_height : i32 = 600;

do_render :: () {
    g_pipe.resize(g_width, g_height);
    g_pipe.tick();
    print("wrapper: pw={}, ph={}, frame={}\n", g_pipe.pw, g_pipe.ph, g_pipe.frame);
}

callback_inline :: (userdata: *void, code: i64) -> bool abi(.c) {
    g_width = xx code;
    g_height = xx (code + 1);
    g_pipe.resize(xx g_width, xx g_height);
    g_pipe.tick();
    print("inline:  pw={}, ph={}, frame={}\n", g_pipe.pw, g_pipe.ph, g_pipe.frame);
    true
}

callback_wrapper :: (userdata: *void, code: i64) -> bool abi(.c) {
    g_width = xx code;
    g_height = xx (code + 1);
    do_render();
    true
}

main :: () {
    pipe := Pipe.{ pw = 0, ph = 0, frame = 0 };
    g_pipe = @pipe;

    callback_inline(xx 0, 320);
    callback_wrapper(xx 0, 640);
}
