summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2022-08-22 11:00:42 -0500
committersanine <sanine.not@pm.me>2022-08-22 11:00:42 -0500
commita2c162f12337142c054c2e1f01ad508ee56963d2 (patch)
tree80fb3c8cbd8f08000423d5dc961986be07978c28
parentdccc9bef56d51c5cad13c2568c5a3b97f637fd6e (diff)
refactor: move data functions into separate file
-rw-r--r--CMakeLists.txt1
-rw-r--r--demo/honey.lua18
-rw-r--r--src/gl/data.c155
-rw-r--r--src/gl/data.test.c216
-rw-r--r--src/gl/gl.c143
-rw-r--r--src/gl/gl.h1
-rw-r--r--src/gl/gl.test.c1
7 files changed, 384 insertions, 151 deletions
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 <stdlib.h>
+#include <stdbool.h>
+#include "gl/glad/glad.h"
+#include <GLFW/glfw3.h>
+#include <lua.h>
+#include <honeysuckle.h>
+#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<len; i++) {
+ lua_rawgeti(L, table, i+1);
+ if (!lua_isnumber(L, -1)) {
+ hs_throw_error(L, "all table items must be numbers (failed at index %d)", i);
+ }
+ fbuf[i] = lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ }
+ len = len * sizeof(float);
+ buf = fbuf;
+ }
+ else {
+ int *ibuf = malloc(len * sizeof(int));
+ if (ibuf == NULL)
+ hs_throw_error(L, "failed to allocate intermediary ibuffer");
+ for (int i=0; i<len; i++) {
+ lua_rawgeti(L, table, i+1);
+ if (!lua_isnumber(L, -1)) {
+ hs_throw_error(L, "all table items must be integers (failed at index %d)", i);
+ }
+ ibuf[i] = lua_tointeger(L, -1);
+ lua_pop(L, 1);
+ }
+ len = len * sizeof(int);
+ buf = ibuf;
+ }
+
+ /* call */
+ glBufferData(target, len, buf, usage);
+ free(buf);
+ return 0;
+}
+
+
+int gl_vertex_array_create(lua_State *L)
+{
+ int array;
+ glGenVertexArrays(1, &array);
+ lua_pushinteger(L, array);
+ return 1;
+}
+
+
+int gl_vertex_array_bind(lua_State *L)
+{
+ lua_Integer array;
+ hs_parse_args(L, hs_int(array));
+ glBindVertexArray(array);
+ return 0;
+}
+
+
+int gl_vertex_attrib_pointer(lua_State *L)
+{
+ lua_Integer index, size, stride, offset;
+ bool normalized;
+ hs_parse_args(L, hs_int(index), hs_int(size), hs_bool(normalized), hs_int(stride), hs_int(offset));
+ glVertexAttribPointer(index, size, GL_FLOAT,
+ normalized, stride*sizeof(float),
+ (void*) (offset*sizeof(float)));
+ return 0;
+}
+
+
+int gl_vertex_array_enable_attrib(lua_State *L)
+{
+ lua_Integer index;
+ hs_parse_args(L, hs_int(index));
+ glEnableVertexAttribArray(index);
+ return 0;
+}
diff --git a/src/gl/data.test.c b/src/gl/data.test.c
new file mode 100644
index 0000000..143b0ce
--- /dev/null
+++ b/src/gl/data.test.c
@@ -0,0 +1,216 @@
+#include <string.h>
+#include <lua.h>
+#include <lauxlib.h>
+#include <honeysuckle.h>
+#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; i<count; i++) {
+ lily_store_value(mock_glBufferData, int, numbers[i]);
+ }
+ }
+ else {
+ size_t count = size/sizeof(float);
+ float *numbers = data;
+ for (int i=0; i<count; i++) {
+ lily_store_value(mock_glBufferData, float, numbers[i]);
+ }
+ }
+}
+
+
+/* ~~~~~~~~ suite ~~~~~~~~ */
+
+void gl_init_succeeds()
+{
+ lily_mock_use(&mock_glfwInit);
+ lily_mock_use(&mock_hs_throw_error);
+
+ lua_State *L = luaL_newstate();
+ lily_store_value(mock_glfwInit, int, 1);
+ lua_pushcfunction(L, gl_init);
+ int err = lua_pcall(L, 0, 0, 0);
+ lua_close(L);
+
+ lily_assert_int_equal(err, 0);
+ lily_assert_int_equal(mock_glfwInit->n_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<len; i++) {
- lua_rawgeti(L, table, i+1);
- if (!lua_isnumber(L, -1)) {
- hs_throw_error(L, "all table items must be numbers (failed at index %d)", i);
- }
- fbuf[i] = lua_tonumber(L, -1);
- lua_pop(L, 1);
- }
- len = len * sizeof(float);
- buf = fbuf;
- }
- else {
- int *ibuf = malloc(len * sizeof(int));
- if (ibuf == NULL)
- hs_throw_error(L, "failed to allocate intermediary ibuffer");
- for (int i=0; i<len; i++) {
- lua_rawgeti(L, table, i+1);
- if (!lua_isnumber(L, -1)) {
- hs_throw_error(L, "all table items must be integers (failed at index %d)", i);
- }
- ibuf[i] = lua_tointeger(L, -1);
- lua_pop(L, 1);
- }
- len = len * sizeof(int);
- buf = ibuf;
- }
-
- /* call */
- glBufferData(target, len, buf, usage);
- free(buf);
- return 0;
-}
-
-
-int gl_vertex_array_create(lua_State *L)
-{
- int array;
- glGenVertexArrays(1, &array);
- lua_pushinteger(L, array);
- return 1;
-}
-
-
-int gl_vertex_array_bind(lua_State *L)
-{
- lua_Integer array;
- hs_parse_args(L, hs_int(array));
- glBindVertexArray(array);
- return 0;
-}
-
-
-int gl_vertex_attrib_pointer(lua_State *L)
-{
- lua_Integer index, size, stride, offset;
- bool normalized;
- hs_parse_args(L, hs_int(index), hs_int(size), hs_bool(normalized), hs_int(stride), hs_int(offset));
- glVertexAttribPointer(index, size, GL_FLOAT,
- normalized, stride*sizeof(float),
- (void*) (offset*sizeof(float)));
- return 0;
-}
-
-
-int gl_vertex_array_enable_attrib(lua_State *L)
-{
- lua_Integer index;
- hs_parse_args(L, hs_int(index));
- glEnableVertexAttribArray(index);
- return 0;
-}
diff --git a/src/gl/gl.h b/src/gl/gl.h
index f384c54..766fe63 100644
--- a/src/gl/gl.h
+++ b/src/gl/gl.h
@@ -6,6 +6,7 @@
void setup_gl(lua_State *L, int honey_index);
void setup_shader(lua_State *L, int gl_index);
void setup_drawing(lua_State *L, int gl_index);
+void setup_data(lua_State *L, int gl_index);
void setup_window(lua_State *L, int honey_index);
diff --git a/src/gl/gl.test.c b/src/gl/gl.test.c
index 363036a..7a687b4 100644
--- a/src/gl/gl.test.c
+++ b/src/gl/gl.test.c
@@ -20,6 +20,7 @@ void mock_glBufferData_(int, size_t, const void *, int);
#define setup_shader DUMMY_FUNCTION
#define setup_drawing DUMMY_FUNCTION
#include "gl/gl.c"
+#include "gl/data.c"
#undef glBufferData
#undef glfwTerminate
#undef hs_throw_error