From a2c162f12337142c054c2e1f01ad508ee56963d2 Mon Sep 17 00:00:00 2001 From: sanine Date: Mon, 22 Aug 2022 11:00:42 -0500 Subject: refactor: move data functions into separate file --- CMakeLists.txt | 1 + demo/honey.lua | 18 ++--- src/gl/data.c | 155 ++++++++++++++++++++++++++++++++++++++ src/gl/data.test.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/gl/gl.c | 143 +---------------------------------- src/gl/gl.h | 1 + src/gl/gl.test.c | 1 + 7 files changed, 384 insertions(+), 151 deletions(-) create mode 100644 src/gl/data.c create mode 100644 src/gl/data.test.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 02490f6..dc9a83c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,7 @@ set(HONEY_LIB_FILES ${SRC_ROOT}/gl/gl.c ${SRC_ROOT}/gl/shader.c ${SRC_ROOT}/gl/drawing.c + ${SRC_ROOT}/gl/data.c ${SRC_ROOT}/gl/window.c ) diff --git a/demo/honey.lua b/demo/honey.lua index fce264c..5e14461 100644 --- a/demo/honey.lua +++ b/demo/honey.lua @@ -67,23 +67,23 @@ local vertices = { 0.0, 0.5, 0.0 } -local vertexArray = gl.createVertexArray() +local vertexArray = gl.data.createVertexArray() -local vertexBuffer = gl.createBuffer() -gl.bindVertexArray(vertexArray) +local vertexBuffer = gl.data.createBuffer() +gl.data.bindVertexArray(vertexArray) -gl.bindBuffer(gl.bufferTarget.arrayBuffer, vertexBuffer) +gl.data.bindBuffer(gl.data.bufferTarget.arrayBuffer, vertexBuffer) local err = gl.getError() if err ~= gl.errorType.noError then error(gl.errorName(err)) end -gl.bufferData(gl.bufferTarget.arrayBuffer, gl.dataType.float, vertices, gl.bufferUsage.staticDraw) +gl.data.bufferData(gl.data.bufferTarget.arrayBuffer, gl.dataType.float, vertices, gl.data.bufferUsage.staticDraw) if gl.getError() ~= gl.errorType.noError then error(gl.getError()) end -gl.vertexAttribPointer(0, 3, false, 3, 0) +gl.data.vertexAttribPointer(0, 3, false, 3, 0) if gl.getError() ~= gl.errorType.noError then error(gl.getError()) end -gl.vertexArrayEnableAttrib(0) +gl.data.vertexArrayEnableAttrib(0) if gl.getError() ~= gl.errorType.noError then error(gl.getError()) end -gl.bindBuffer(gl.bufferTarget.arrayBuffer, 0) +gl.data.bindBuffer(gl.data.bufferTarget.arrayBuffer, 0) if gl.getError() ~= gl.errorType.noError then error(gl.getError()) end while not window.shouldClose(w) do @@ -91,7 +91,7 @@ while not window.shouldClose(w) do gl.draw.clear(gl.draw.bufferMask.colorBuffer); gl.shader.use(shader) - gl.bindVertexArray(vertexArray) + gl.data.bindVertexArray(vertexArray) gl.draw.drawArrays(gl.draw.primitiveType.triangles, 0, 3) window.swapBuffers(w) diff --git a/src/gl/data.c b/src/gl/data.c new file mode 100644 index 0000000..f598784 --- /dev/null +++ b/src/gl/data.c @@ -0,0 +1,155 @@ +#include +#include +#include "gl/glad/glad.h" +#include +#include +#include +#include "gl.h" + +int gl_create_buffer(lua_State *L); +int gl_bind_buffer(lua_State *L); +int gl_buffer_data(lua_State *L); + +int gl_vertex_array_create(lua_State *L); +int gl_vertex_array_bind(lua_State *L); +int gl_vertex_attrib_pointer(lua_State *L); +int gl_vertex_array_enable_attrib(lua_State *L); + + +void setup_data(lua_State *L, int gl_index) +{ + int buffer_binding_targets = hs_create_table(L, + hs_str_int("arrayBuffer", GL_ARRAY_BUFFER), + hs_str_int("elementArrayBuffer", GL_ELEMENT_ARRAY_BUFFER), + ); + + int buffer_usage_patterns = hs_create_table(L, + hs_str_int("streamDraw", GL_STREAM_DRAW), + hs_str_int("staticDraw", GL_STATIC_DRAW), + hs_str_int("dynamicDraw", GL_DYNAMIC_DRAW), + ); + + hs_create_table(L, + hs_str_cfunc("createBuffer", gl_create_buffer), + hs_str_cfunc("bindBuffer", gl_bind_buffer), + hs_str_cfunc("bufferData", gl_buffer_data), + + hs_str_cfunc("createVertexArray", gl_vertex_array_create), + hs_str_cfunc("bindVertexArray", gl_vertex_array_bind), + hs_str_cfunc("vertexAttribPointer", gl_vertex_attrib_pointer), + hs_str_cfunc("vertexArrayEnableAttrib", gl_vertex_array_enable_attrib), + + hs_str_tbl("bufferTarget", buffer_binding_targets), + hs_str_tbl("bufferUsage", buffer_usage_patterns), + ); + + lua_setfield(L, gl_index, "data"); +} + + +int gl_create_buffer(lua_State *L) +{ + int buf; + glGenBuffers(1, &buf); + lua_pushinteger(L, buf); + return 1; +} + + +int gl_bind_buffer(lua_State *L) +{ + lua_Integer target, buf; + hs_parse_args(L, hs_int(target), hs_int(buf)); + glBindBuffer(target, buf); + return 0; +} + + +int gl_buffer_data(lua_State *L) +{ + lua_Integer target, type, usage; + int table; + hs_parse_args(L, hs_int(target), hs_int(type), hs_tbl(table), hs_int(usage)); + + if (type != GL_INT && type != GL_FLOAT) { + hs_throw_error(L, "invalid type"); + } + + /* build raw buffer */ + size_t len = lua_objlen(L, table); + void *buf; + if (type == GL_FLOAT) { + float *fbuf = malloc(len * sizeof(float)); + if (fbuf == NULL) + hs_throw_error(L, "failed to allocate intermediary fbuffer"); + for (int i=0; i +#include +#include +#include +#include "test/honey-test.h" + + +int mock_glfwInit_(void); +int mock_hs_throw_error_(lua_State *L, const char *str, ...); +void mock_glfwTerminate_(); +void mock_glBufferData_(int, size_t, const void *, int); + +#define DUMMY_FUNCTION(...) + +#define glfwInit mock_glfwInit_ +#define hs_throw_error mock_hs_throw_error_ +#define glfwTerminate mock_glfwTerminate_ +#undef glBufferData +#define glBufferData mock_glBufferData_ +#define setup_shader DUMMY_FUNCTION +#define setup_drawing DUMMY_FUNCTION +#include "gl/gl.c" +#undef glBufferData +#undef glfwTerminate +#undef hs_throw_error +#undef glfwInit + + +lily_mock_t *mock_hs_throw_error = NULL; +static int mock_hs_throw_error_(lua_State *L, const char *str, ...) +{ + struct lily_mock_arg_t args[] = { + { sizeof(const char *), &str } + }; + lily_mock_store_call(mock_hs_throw_error, args); + + lua_pushstring(L, "some error"); + lua_error(L); + + return 0; +} + +lily_mock_t *mock_glBufferData = NULL; +static void mock_glBufferData_(int target, size_t size, const void *data, int usage) +{ + struct lily_mock_arg_t args[] = { + { sizeof(int), &target }, + { sizeof(size_t), &size }, + { sizeof(int), &usage } + }; + lily_mock_store_call(mock_glBufferData, args); + + int use_ints; lily_get_value(mock_glBufferData, int, &use_ints); + + if (use_ints) { + size_t count = size/sizeof(int); + int *numbers = data; + for (int i=0; in_calls, 1); + lily_assert_int_equal(mock_hs_throw_error->n_calls, 0); +} + + +void gl_init_fails() +{ + lily_mock_use(&mock_glfwInit); + lily_mock_use(&mock_hs_throw_error); + + lua_State *L = luaL_newstate(); + lily_store_value(mock_glfwInit, int, 0); + lua_pushcfunction(L, gl_init); + int err = lua_pcall(L, 0, 0, 0); + lua_close(L); + + lily_assert_int_equal(err, LUA_ERRRUN); + lily_assert_int_equal(mock_hs_throw_error->n_calls, 1); +} + + +void gl_terminate_works() +{ + lily_mock_use(&mock_glfwTerminate); + + lua_State *L = luaL_newstate(); + lua_pushcfunction(L, gl_terminate); + int err = lua_pcall(L, 0, 0, 0); + lua_close(L); + + lily_assert_int_equal(err, 0); + lily_assert_int_equal(mock_glfwTerminate->n_calls, 1); +} + + +void gl_buffer_float_works() +{ + lily_mock_use(&mock_hs_throw_error); + lily_mock_use(&mock_glBufferData); + lily_store_value(mock_glBufferData, int, 0); // use floats + + lua_State *L = luaL_newstate(); + lua_pushcfunction(L, gl_buffer_data); + lua_pushinteger(L, GL_ARRAY_BUFFER); + lua_pushinteger(L, GL_FLOAT); + hs_create_table(L, + hs_int_num(1, 22), + hs_int_num(2, 33), + hs_int_num(3, 44), + ); + lua_pushinteger(L, GL_STATIC_DRAW); + int err = hs_call(L, 4, 0); + lua_close(L); + + lily_assert_int_equal(err, 0); + lily_assert_int_equal(mock_glBufferData->n_calls, 1); + int target; size_t size; int usage; + struct lily_mock_arg_t args[] = { + { sizeof(int), &target }, + { sizeof(size_t), &size }, + { sizeof(int), &usage } + }; + lily_mock_get_call(mock_glBufferData, args, 0); + lily_assert_int_equal(target, GL_ARRAY_BUFFER); + lily_assert_int_equal(size, 3*sizeof(float)); + lily_assert_int_equal(usage, GL_STATIC_DRAW); + + float n; + lily_get_value(mock_glBufferData, float, &n); + lily_assert_float_equal(n, 22, 0.1); + lily_get_value(mock_glBufferData, float, &n); + lily_assert_float_equal(n, 33, 0.1); + lily_get_value(mock_glBufferData, float, &n); + lily_assert_float_equal(n, 44, 0.1); +} + + +void gl_buffer_int_works() +{ + lily_mock_use(&mock_hs_throw_error); + lily_mock_use(&mock_glBufferData); + lily_store_value(mock_glBufferData, int, 1); // use ints + + lua_State *L = luaL_newstate(); + lua_pushcfunction(L, gl_buffer_data); + lua_pushinteger(L, GL_ARRAY_BUFFER); + lua_pushinteger(L, GL_INT); + hs_create_table(L, + hs_int_num(1, 22), + hs_int_num(2, 33), + hs_int_num(3, 44), + ); + lua_pushinteger(L, GL_STATIC_DRAW); + int err = hs_call(L, 4, 0); + lua_close(L); + + lily_assert_int_equal(err, 0); + lily_assert_int_equal(mock_glBufferData->n_calls, 1); + int target; size_t size; int usage; + struct lily_mock_arg_t args[] = { + { sizeof(int), &target }, + { sizeof(size_t), &size }, + { sizeof(int), &usage } + }; + lily_mock_get_call(mock_glBufferData, args, 0); + lily_assert_int_equal(target, GL_ARRAY_BUFFER); + lily_assert_int_equal(size, 3*sizeof(float)); + lily_assert_int_equal(usage, GL_STATIC_DRAW); + + int n; + lily_get_value(mock_glBufferData, int, &n); + lily_assert_int_equal(n, 22); + lily_get_value(mock_glBufferData, int, &n); + lily_assert_int_equal(n, 33); + lily_get_value(mock_glBufferData, int, &n); + lily_assert_int_equal(n, 44); +} + +void suite_gl() +{ + lily_run_test(gl_init_succeeds); + lily_run_test(gl_init_fails); + lily_run_test(gl_terminate_works); + lily_run_test(gl_buffer_float_works); + lily_run_test(gl_buffer_int_works); + + lily_mock_destroy(mock_glfwInit); + lily_mock_destroy(mock_hs_throw_error); + lily_mock_destroy(mock_glfwTerminate); + lily_mock_destroy(mock_glBufferData); +} diff --git a/src/gl/gl.c b/src/gl/gl.c index 876df9d..8a1cb17 100644 --- a/src/gl/gl.c +++ b/src/gl/gl.c @@ -18,16 +18,6 @@ int glad_init(lua_State *L); int gl_terminate(lua_State *L); int gl_get_error(lua_State *L); -/* buffers */ -int gl_create_buffer(lua_State *L); -int gl_bind_buffer(lua_State *L); -int gl_buffer_data(lua_State *L); - -int gl_vertex_array_create(lua_State *L); -int gl_vertex_array_bind(lua_State *L); -int gl_vertex_attrib_pointer(lua_State *L); -int gl_vertex_array_enable_attrib(lua_State *L); - void setup_gl(lua_State *L, int honey_index) { int data_types = hs_create_table(L, @@ -44,17 +34,6 @@ void setup_gl(lua_State *L, int honey_index) hs_str_int("outOfMemory", GL_OUT_OF_MEMORY), ); - int buffer_binding_targets = hs_create_table(L, - hs_str_int("arrayBuffer", GL_ARRAY_BUFFER), - hs_str_int("elementArrayBuffer", GL_ELEMENT_ARRAY_BUFFER), - ); - - int buffer_usage_patterns = hs_create_table(L, - hs_str_int("streamDraw", GL_STREAM_DRAW), - hs_str_int("staticDraw", GL_STATIC_DRAW), - hs_str_int("dynamicDraw", GL_DYNAMIC_DRAW), - ); - int gl_index = hs_create_table(L, hs_str_cfunc("init", gl_init), hs_str_cfunc("initGlad", glad_init), @@ -63,23 +42,11 @@ void setup_gl(lua_State *L, int honey_index) hs_str_tbl("dataType", data_types), hs_str_tbl("errorType", error_types), - - /* buffer */ - hs_str_cfunc("createBuffer", gl_create_buffer), - hs_str_cfunc("bindBuffer", gl_bind_buffer), - hs_str_cfunc("bufferData", gl_buffer_data), - - hs_str_cfunc("createVertexArray", gl_vertex_array_create), - hs_str_cfunc("bindVertexArray", gl_vertex_array_bind), - hs_str_cfunc("vertexAttribPointer", gl_vertex_attrib_pointer), - hs_str_cfunc("vertexArrayEnableAttrib", gl_vertex_array_enable_attrib), - - hs_str_tbl("bufferTarget", buffer_binding_targets), - hs_str_tbl("bufferUsage", buffer_usage_patterns), ); setup_shader(L, gl_index); setup_drawing(L, gl_index); + setup_data(L, gl_index); lua_setfield(L, honey_index, "gl"); } @@ -113,111 +80,3 @@ int gl_get_error(lua_State *L) lua_pushinteger(L, glGetError()); return 1; } - - -int gl_create_buffer(lua_State *L) -{ - int buf; - glGenBuffers(1, &buf); - lua_pushinteger(L, buf); - return 1; -} - - -int gl_bind_buffer(lua_State *L) -{ - lua_Integer target, buf; - hs_parse_args(L, hs_int(target), hs_int(buf)); - glBindBuffer(target, buf); - return 0; -} - - -int gl_buffer_data(lua_State *L) -{ - lua_Integer target, type, usage; - int table; - hs_parse_args(L, hs_int(target), hs_int(type), hs_tbl(table), hs_int(usage)); - - if (type != GL_INT && type != GL_FLOAT) { - hs_throw_error(L, "invalid type"); - } - - /* build raw buffer */ - size_t len = lua_objlen(L, table); - void *buf; - if (type == GL_FLOAT) { - float *fbuf = malloc(len * sizeof(float)); - if (fbuf == NULL) - hs_throw_error(L, "failed to allocate intermediary fbuffer"); - for (int i=0; i