prosperon/source/engine/thirdparty/sokol/tests/functional/sokol_gl_test.c

324 lines
11 KiB
C

//------------------------------------------------------------------------------
// sokol-gl-test.c
//------------------------------------------------------------------------------
#include "sokol_gfx.h"
#define SOKOL_GL_IMPL
#include "sokol_gl.h"
#include "utest.h"
#include <float.h>
#define T(b) EXPECT_TRUE(b)
#define TFLT(f0,f1,epsilon) {T(fabs((f0)-(f1))<=(epsilon));}
static void init(void) {
sg_setup(&(sg_desc){0});
sgl_setup(&(sgl_desc_t){0});
}
static void shutdown(void) {
sgl_shutdown();
sg_shutdown();
}
UTEST(sokol_gl, default_init_shutdown) {
init();
T(_sgl.init_cookie == _SGL_INIT_COOKIE);
T(_sgl.def_ctx_id.id == SGL_DEFAULT_CONTEXT.id);
T(_sgl.cur_ctx_id.id == _sgl.def_ctx_id.id);
T(_sgl.cur_ctx);
T(_sgl.cur_ctx->vertices.cap == 65536);
T(_sgl.cur_ctx->commands.cap == 16384);
T(_sgl.cur_ctx->uniforms.cap == 16384);
T(_sgl.cur_ctx->vertices.next == 0);
T(_sgl.cur_ctx->commands.next == 0);
T(_sgl.cur_ctx->uniforms.next == 0);
T(_sgl.cur_ctx->vertices.ptr != 0);
T(_sgl.cur_ctx->uniforms.ptr != 0);
T(_sgl.cur_ctx->commands.ptr != 0);
T(_sgl.cur_ctx->error == SGL_NO_ERROR);
T(!_sgl.cur_ctx->in_begin);
T(_sgl.cur_ctx->def_pip.id != SG_INVALID_ID);
T(_sgl.pip_pool.pool.size == (_SGL_DEFAULT_PIPELINE_POOL_SIZE + 1));
TFLT(_sgl.cur_ctx->u, 0.0f, FLT_MIN);
TFLT(_sgl.cur_ctx->v, 0.0f, FLT_MIN);
T(_sgl.cur_ctx->rgba == 0xFFFFFFFF);
T(_sgl.cur_ctx->cur_img.id == _sgl.def_img.id);
shutdown();
}
UTEST(sokol_gl, viewport) {
init();
sgl_viewport(1, 2, 3, 4, true);
T(_sgl.cur_ctx->commands.next == 1);
T(_sgl.cur_ctx->commands.ptr[0].cmd == SGL_COMMAND_VIEWPORT);
T(_sgl.cur_ctx->commands.ptr[0].args.viewport.x == 1);
T(_sgl.cur_ctx->commands.ptr[0].args.viewport.y == 2);
T(_sgl.cur_ctx->commands.ptr[0].args.viewport.w == 3);
T(_sgl.cur_ctx->commands.ptr[0].args.viewport.h == 4);
T(_sgl.cur_ctx->commands.ptr[0].args.viewport.origin_top_left);
sgl_viewport(5, 6, 7, 8, false);
T(_sgl.cur_ctx->commands.next == 2);
T(_sgl.cur_ctx->commands.ptr[1].cmd == SGL_COMMAND_VIEWPORT);
T(_sgl.cur_ctx->commands.ptr[1].args.viewport.x == 5);
T(_sgl.cur_ctx->commands.ptr[1].args.viewport.y == 6);
T(_sgl.cur_ctx->commands.ptr[1].args.viewport.w == 7);
T(_sgl.cur_ctx->commands.ptr[1].args.viewport.h == 8);
T(!_sgl.cur_ctx->commands.ptr[1].args.viewport.origin_top_left);
shutdown();
}
UTEST(sokol_gl, scissor_rect) {
init();
sgl_scissor_rect(10, 20, 30, 40, true);
T(_sgl.cur_ctx->commands.next == 1);
T(_sgl.cur_ctx->commands.ptr[0].cmd == SGL_COMMAND_SCISSOR_RECT);
T(_sgl.cur_ctx->commands.ptr[0].args.scissor_rect.x == 10);
T(_sgl.cur_ctx->commands.ptr[0].args.scissor_rect.y == 20);
T(_sgl.cur_ctx->commands.ptr[0].args.scissor_rect.w == 30);
T(_sgl.cur_ctx->commands.ptr[0].args.scissor_rect.h == 40);
T(_sgl.cur_ctx->commands.ptr[0].args.scissor_rect.origin_top_left);
sgl_scissor_rect(50, 60, 70, 80, false);
T(_sgl.cur_ctx->commands.next == 2);
T(_sgl.cur_ctx->commands.ptr[1].cmd == SGL_COMMAND_SCISSOR_RECT);
T(_sgl.cur_ctx->commands.ptr[1].args.scissor_rect.x == 50);
T(_sgl.cur_ctx->commands.ptr[1].args.scissor_rect.y == 60);
T(_sgl.cur_ctx->commands.ptr[1].args.scissor_rect.w == 70);
T(_sgl.cur_ctx->commands.ptr[1].args.scissor_rect.h == 80);
T(!_sgl.cur_ctx->commands.ptr[1].args.scissor_rect.origin_top_left);
shutdown();
}
UTEST(sokol_gl, texture) {
init();
T(_sgl.cur_ctx->cur_img.id == _sgl.def_img.id);
uint32_t pixels[64] = { 0 };
sg_image img = sg_make_image(&(sg_image_desc){
.type = SG_IMAGETYPE_2D,
.width = 8,
.height = 8,
.data.subimage[0][0] = SG_RANGE(pixels),
});
sg_sampler smp = sg_make_sampler(&(sg_sampler_desc){0});
sgl_texture(img, smp);
T(_sgl.cur_ctx->cur_img.id == img.id);
T(_sgl.cur_ctx->cur_smp.id == smp.id);
shutdown();
}
UTEST(sokol_gl, texture_image_nosampler) {
init();
T(_sgl.cur_ctx->cur_img.id == _sgl.def_img.id);
uint32_t pixels[64] = { 0 };
sg_image img = sg_make_image(&(sg_image_desc){
.type = SG_IMAGETYPE_2D,
.width = 8,
.height = 8,
.data.subimage[0][0] = SG_RANGE(pixels),
});
sgl_texture(img, (sg_sampler){0});
T(_sgl.cur_ctx->cur_img.id == img.id);
T(_sgl.cur_ctx->cur_smp.id == _sgl.def_smp.id);
shutdown();
}
UTEST(sokol_gl, texture_noimage_sampler) {
init();
T(_sgl.cur_ctx->cur_img.id == _sgl.def_img.id);
sg_sampler smp = sg_make_sampler(&(sg_sampler_desc){0});
sgl_texture((sg_image){0}, smp);
T(_sgl.cur_ctx->cur_img.id == _sgl.def_img.id);
T(_sgl.cur_ctx->cur_smp.id == smp.id);
shutdown();
}
UTEST(sokol_gl, texture_noimage_nosampler) {
init();
T(_sgl.cur_ctx->cur_img.id == _sgl.def_img.id);
sgl_texture((sg_image){0}, (sg_sampler){0});
T(_sgl.cur_ctx->cur_img.id == _sgl.def_img.id);
T(_sgl.cur_ctx->cur_smp.id == _sgl.def_smp.id);
shutdown();
}
UTEST(sokol_gl, begin_end) {
init();
sgl_begin_triangles();
sgl_v3f(1.0f, 2.0f, 3.0f);
sgl_v3f(4.0f, 5.0f, 6.0f);
sgl_v3f(7.0f, 8.0f, 9.0f);
sgl_end();
T(_sgl.cur_ctx->base_vertex == 0);
T(_sgl.cur_ctx->vertices.next == 3);
T(_sgl.cur_ctx->commands.next == 1);
T(_sgl.cur_ctx->uniforms.next == 1);
T(_sgl.cur_ctx->commands.ptr[0].cmd == SGL_COMMAND_DRAW);
T(_sgl.cur_ctx->commands.ptr[0].args.draw.pip.id == _sgl_pipeline_at(_sgl.cur_ctx->def_pip.id)->pip[SGL_PRIMITIVETYPE_TRIANGLES].id);
T(_sgl.cur_ctx->commands.ptr[0].args.draw.base_vertex == 0);
T(_sgl.cur_ctx->commands.ptr[0].args.draw.num_vertices == 3);
T(_sgl.cur_ctx->commands.ptr[0].args.draw.uniform_index == 0);
shutdown();
}
UTEST(sokol_gl, matrix_mode) {
init();
sgl_matrix_mode_modelview(); T(_sgl.cur_ctx->cur_matrix_mode == SGL_MATRIXMODE_MODELVIEW);
sgl_matrix_mode_projection(); T(_sgl.cur_ctx->cur_matrix_mode == SGL_MATRIXMODE_PROJECTION);
sgl_matrix_mode_texture(); T(_sgl.cur_ctx->cur_matrix_mode == SGL_MATRIXMODE_TEXTURE);
shutdown();
}
UTEST(sokol_gl, load_identity) {
init();
sgl_load_identity();
const _sgl_matrix_t* m = _sgl_matrix_modelview(_sgl.cur_ctx);
TFLT(m->v[0][0], 1.0f, FLT_MIN); TFLT(m->v[0][1], 0.0f, FLT_MIN); TFLT(m->v[0][2], 0.0f, FLT_MIN); TFLT(m->v[0][3], 0.0f, FLT_MIN);
TFLT(m->v[1][0], 0.0f, FLT_MIN); TFLT(m->v[1][1], 1.0f, FLT_MIN); TFLT(m->v[1][2], 0.0f, FLT_MIN); TFLT(m->v[1][3], 0.0f, FLT_MIN);
TFLT(m->v[2][0], 0.0f, FLT_MIN); TFLT(m->v[2][1], 0.0f, FLT_MIN); TFLT(m->v[2][2], 1.0f, FLT_MIN); TFLT(m->v[2][3], 0.0f, FLT_MIN);
TFLT(m->v[3][0], 0.0f, FLT_MIN); TFLT(m->v[3][1], 0.0f, FLT_MIN); TFLT(m->v[3][2], 0.0f, FLT_MIN); TFLT(m->v[3][3], 1.0f, FLT_MIN);
shutdown();
}
UTEST(sokol_gl, load_matrix) {
init();
const float m[16] = {
0.5f, 0.0f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f,
2.0f, 3.0f, 4.0f, 1.0f
};
sgl_load_matrix(m);
const _sgl_matrix_t* m0 = _sgl_matrix_modelview(_sgl.cur_ctx);
TFLT(m0->v[0][0], 0.5f, FLT_MIN);
TFLT(m0->v[1][1], 0.5f, FLT_MIN);
TFLT(m0->v[2][2], 0.5f, FLT_MIN);
TFLT(m0->v[3][0], 2.0f, FLT_MIN);
TFLT(m0->v[3][1], 3.0f, FLT_MIN);
TFLT(m0->v[3][2], 4.0f, FLT_MIN);
TFLT(m0->v[3][3], 1.0f, FLT_MIN);
sgl_load_transpose_matrix(m);
const _sgl_matrix_t* m1 = _sgl_matrix_modelview(_sgl.cur_ctx);
TFLT(m1->v[0][0], 0.5f, FLT_MIN);
TFLT(m1->v[1][1], 0.5f, FLT_MIN);
TFLT(m1->v[2][2], 0.5f, FLT_MIN);
TFLT(m1->v[0][3], 2.0f, FLT_MIN);
TFLT(m1->v[1][3], 3.0f, FLT_MIN);
TFLT(m1->v[2][3], 4.0f, FLT_MIN);
TFLT(m1->v[3][3], 1.0f, FLT_MIN);
shutdown();
}
UTEST(sokol_gl, make_destroy_pipelines) {
sg_setup(&(sg_desc){0});
sgl_setup(&(sgl_desc_t){
/* one pool slot is used by soko-gl itself */
.pipeline_pool_size = 4
});
sgl_pipeline pip[3] = { {0} };
sg_pipeline_desc desc = {
.depth = {
.write_enabled = true,
.compare = SG_COMPAREFUNC_LESS_EQUAL
}
};
for (int i = 0; i < 3; i++) {
pip[i] = sgl_make_pipeline(&desc);
T(pip[i].id != SG_INVALID_ID);
T((2-i) == _sgl.pip_pool.pool.queue_top);
const _sgl_pipeline_t* pip_ptr = _sgl_lookup_pipeline(pip[i].id);
T(pip_ptr);
T(pip_ptr->slot.id == pip[i].id);
T(pip_ptr->slot.state == SG_RESOURCESTATE_VALID);
}
/* trying to create another one fails because buffer is exhausted */
T(sgl_make_pipeline(&desc).id == SG_INVALID_ID);
for (int i = 0; i < 3; i++) {
sgl_destroy_pipeline(pip[i]);
T(0 == _sgl_lookup_pipeline(pip[i].id));
const _sgl_pipeline_t* pip_ptr = _sgl_pipeline_at(pip[i].id);
T(pip_ptr);
T(pip_ptr->slot.id == SG_INVALID_ID);
T(pip_ptr->slot.state == SG_RESOURCESTATE_INITIAL);
T((i+1) == _sgl.pip_pool.pool.queue_top);
}
sgl_shutdown();
sg_shutdown();
}
UTEST(sokol_gl, make_destroy_contexts) {
init();
sgl_context ctx = sgl_make_context(&(sgl_context_desc_t){
.max_vertices = 1024,
.max_commands = 256,
.color_format = SG_PIXELFORMAT_RG8,
.depth_format = SG_PIXELFORMAT_NONE,
.sample_count = 4,
});
T(ctx.id != SG_INVALID_ID);
T(ctx.id != SGL_DEFAULT_CONTEXT.id);
// creating a context should not change the current context
T(ctx.id != _sgl.cur_ctx_id.id);
sgl_set_context(ctx);
T(_sgl.cur_ctx->vertices.cap == 1024);
T(_sgl.cur_ctx->commands.cap == 256);
T(_sgl.cur_ctx->uniforms.cap == 256);
T(ctx.id == _sgl.cur_ctx_id.id);
T(sgl_get_context().id == ctx.id);
sgl_set_context(SGL_DEFAULT_CONTEXT);
T(sgl_get_context().id == SGL_DEFAULT_CONTEXT.id);
sgl_destroy_context(ctx);
shutdown();
}
UTEST(sokol_gl, destroy_active_context) {
init();
sgl_context ctx = sgl_make_context(&(sgl_context_desc_t){
.max_vertices = 1024,
.max_commands = 256,
.color_format = SG_PIXELFORMAT_RG8,
.depth_format = SG_PIXELFORMAT_NONE,
.sample_count = 4,
});
sgl_set_context(ctx);
sgl_destroy_context(ctx);
T(_sgl.cur_ctx == 0);
T(sgl_error() == SGL_ERROR_NO_CONTEXT);
shutdown();
}
UTEST(sokol_gl, context_pipeline) {
init();
sgl_context ctx1 = sgl_make_context(&(sgl_context_desc_t){
.max_vertices = 1024,
.max_commands = 256,
.color_format = SG_PIXELFORMAT_R8,
.depth_format = SG_PIXELFORMAT_NONE,
.sample_count = 4,
});
sgl_context ctx2 = sgl_make_context(&(sgl_context_desc_t){
.max_vertices = 1024,
.max_commands = 256,
.color_format = SG_PIXELFORMAT_RG8,
.depth_format = SG_PIXELFORMAT_NONE,
.sample_count = 2,
});
sgl_set_context(ctx1);
sgl_pipeline pip1 = sgl_make_pipeline(&(sg_pipeline_desc){
.colors[0].blend.enabled = true,
});
T(pip1.id != SG_INVALID_ID);
// FIXME: currently sg_query_pipeline_info() doesn't provide enough information
sgl_pipeline pip2 = sgl_context_make_pipeline(ctx2, &(sg_pipeline_desc){
.alpha_to_coverage_enabled = true,
});
T(pip2.id != SG_INVALID_ID);
shutdown();
}
UTEST(sokol_gl, default_context) {
init();
T(sgl_default_context().id == SGL_DEFAULT_CONTEXT.id);
shutdown();
}