diff options
| author | realtradam <[email protected]> | 2023-06-04 02:35:00 -0400 |
|---|---|---|
| committer | realtradam <[email protected]> | 2023-06-04 02:35:00 -0400 |
| commit | 35558b39040d37c939bd68b56985d6cb5385a451 (patch) | |
| tree | b10516557ba530d96799a8c4bed94b7644938811 /src | |
| parent | 856ce67eb21f64d86ecf6bb3651985f10e6236c3 (diff) | |
| download | RodeoKit-35558b39040d37c939bd68b56985d6cb5385a451.tar.gz RodeoKit-35558b39040d37c939bd68b56985d6cb5385a451.zip | |
refactor to have graphics and windowing seperategfx-rewrite
Diffstat (limited to 'src')
| -rw-r--r-- | src/audio/rodeo_audio.c | 4 | ||||
| -rw-r--r-- | src/gfx/irodeo_gfx.h | 30 | ||||
| -rw-r--r-- | src/gfx/irodeo_gfx_t.h | 49 | ||||
| -rw-r--r-- | src/gfx/rodeo_gfx.c | 732 | ||||
| -rw-r--r-- | src/input/rodeo_input.c | 16 | ||||
| -rw-r--r-- | src/rodeo.c | 861 | ||||
| -rw-r--r-- | src/rodeo_internal.h | 29 | ||||
| -rw-r--r-- | src/rodeo_internal_types.h | 39 | ||||
| -rw-r--r-- | src/window/irodeo_window.h | 30 | ||||
| -rw-r--r-- | src/window/irodeo_window_t.h | 21 | ||||
| -rw-r--r-- | src/window/rodeo_window.c | 166 |
11 files changed, 1040 insertions, 937 deletions
diff --git a/src/audio/rodeo_audio.c b/src/audio/rodeo_audio.c index 5f22357..f049fa2 100644 --- a/src/audio/rodeo_audio.c +++ b/src/audio/rodeo_audio.c @@ -17,7 +17,7 @@ static uint32_t **irodeo_audio_channelPool; //void //rodeo_audio_initialize(uint32_t num_sound_pools, uint32_t size_sound_pools) void -rodeo_audio_initialize(uint32_t channels) +rodeo_audio_init(uint32_t channels) { if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0) { @@ -90,7 +90,7 @@ rodeo_audio_initialize(uint32_t channels) } void -rodeo_audio_deinitialize(void) +rodeo_audio_deinit(void) { free(irodeo_audio_channelPool); Mix_Quit(); diff --git a/src/gfx/irodeo_gfx.h b/src/gfx/irodeo_gfx.h new file mode 100644 index 0000000..3acc49f --- /dev/null +++ b/src/gfx/irodeo_gfx.h @@ -0,0 +1,30 @@ + +// -- internal -- +// public +#include "rodeo/common.h" +// private +#include "gfx/irodeo_gfx_t.h" + +// -- external -- +#include "bgfx/c99/bgfx.h" +#include "stc/cstr.h" + +bgfx_shader_handle_t +irodeo_gfx_shader_load(const cstr path); + +void +irodeo_gfx_render_buffer_transient_alloc(void); + +void +irodeo_gfx_frame_stall(void); + +#define \ +mrodeo_bgfx_vertex_layout_do(vertex_layout) \ + mrodeo_defer_do( \ + bgfx_vertex_layout_begin( \ + vertex_layout, \ + bgfx_get_renderer_type() \ + ), \ + bgfx_vertex_layout_end(vertex_layout) \ + ) + diff --git a/src/gfx/irodeo_gfx_t.h b/src/gfx/irodeo_gfx_t.h new file mode 100644 index 0000000..7d9d1b7 --- /dev/null +++ b/src/gfx/irodeo_gfx_t.h @@ -0,0 +1,49 @@ +#pragma once + +// -- internal -- +// public +#include "rodeo/gfx_t.h" + +// -- external -- +#include "bgfx/c99/bgfx.h" +#define CGLM_FORCE_DEPTH_ZERO_TO_ONE +#include "cglm/mat4.h" + +typedef uint16_t irodeo_index_type_t; + +typedef +struct +{ + bgfx_vertex_layout_t vertex_layout; + //bgfx_dynamic_vertex_buffer_handle_t vertex_buffer_handle; + //bgfx_dynamic_index_buffer_handle_t index_buffer_handle; + bgfx_transient_vertex_buffer_t vertex_buffer_handle; + bgfx_transient_index_buffer_t index_buffer_handle; + rodeo_gfx_vertex_t *batched_vertices; + irodeo_index_type_t *batched_indices; + irodeo_index_type_t vertex_size; + irodeo_index_type_t index_count; + irodeo_index_type_t index_size; + //irodeo_index_type_t batched_indices[(mrodeo_vertex_size_max / 4) * 6]; + rodeo_gfx_texture_2d_t default_texture; + bgfx_texture_handle_t *active_texture_p; + bgfx_shader_handle_t vertex_shader; + bgfx_shader_handle_t fragment_shader; + bgfx_program_handle_t program_shader; + bgfx_uniform_handle_t texture_uniforms[2]; + mat4 view_matrix; + mat4 proj_matrix; + uint64_t frame_count; + uint32_t frame_limit; + uint32_t frame_start; + uint32_t frame_end; + float frame_time; +} +irodeo_gfx_state_t; + +struct +irodeo_gfx_texture_internal +{ + bgfx_texture_handle_t texture_bgfx; +}; + diff --git a/src/gfx/rodeo_gfx.c b/src/gfx/rodeo_gfx.c new file mode 100644 index 0000000..38dc145 --- /dev/null +++ b/src/gfx/rodeo_gfx.c @@ -0,0 +1,732 @@ + +// -- internal -- +// public +#include "rodeo.h" // TODO remove this +#include "rodeo/gfx.h" +#include "rodeo/window.h" +#include "rodeo/log.h" +// private +#include "gfx/irodeo_gfx.h" +#include "window/irodeo_window.h" +#include "rodeo_config.h" + +// -- external -- +#include "bgfx/c99/bgfx.h" +#define CGLM_FORCE_DEPTH_ZERO_TO_ONE +#include "cglm/cglm.h" +#include "SDL_image.h" +#include "SDL.h" // used for timing, need to replace in this file with BGFX at some point + +static irodeo_gfx_state_t irodeo_gfx_state = {0}; + +void +rodeo_gfx_init(void) +{ + +#ifdef __EMSCRIPTEN__ + bgfx_render_frame(-1); +#endif + + bgfx_platform_data_t pd = {0}; + memset(&pd, 0, sizeof(bgfx_platform_data_t)); + +#if !__EMSCRIPTEN__ + // x11 + pd.ndt = irodeo_window_wmi_get().info.x11.display; + pd.nwh = (void*)(uintptr_t)irodeo_window_wmi_get().info.x11.window; +#else + // web + pd.nwh = (void*)"#canvas"; +#endif + + bgfx_init_t init = {0}; + bgfx_init_ctor(&init); + //init.type = BGFX_RENDERER_TYPE_COUNT; // auto determine renderer + init.type = BGFX_RENDERER_TYPE_OPENGL; // force opengl renderer + //SDL_GetWindowSize(irodeo_gfx_state.window, &irodeo_gfx_state.screen_width, &irodeo_gfx_state.screen_height); + init.resolution.width = rodeo_window_screen_height_get(); + init.resolution.height = rodeo_window_screen_width_get(); + init.resolution.reset = BGFX_RESET_VSYNC; + init.platformData = pd; + bgfx_init(&init); + + bgfx_set_debug(BGFX_DEBUG_TEXT); + + //bgfx_set_state(BGFX_STATE_CULL_CCW, 0); + + //bgfx_dbg_text_clear(0x65, false); + + bgfx_set_view_clear( + 0, + BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, + 0x443355FF, + 1.0f, + 0 + ); + bgfx_set_view_rect(0, 0, 0, rodeo_window_screen_width_get(), rodeo_window_screen_height_get()); + + rodeo_log(rodeo_logLevel_info, "Setting up default render pipeline..."); + // set up vertex layout + mrodeo_bgfx_vertex_layout_do(&irodeo_gfx_state.vertex_layout) + { + bgfx_vertex_layout_add(&irodeo_gfx_state.vertex_layout, BGFX_ATTRIB_POSITION, 3, BGFX_ATTRIB_TYPE_FLOAT, false, false); + bgfx_vertex_layout_add(&irodeo_gfx_state.vertex_layout, BGFX_ATTRIB_COLOR0, 4, BGFX_ATTRIB_TYPE_FLOAT, false, false); + bgfx_vertex_layout_add(&irodeo_gfx_state.vertex_layout, BGFX_ATTRIB_TEXCOORD0, 2, BGFX_ATTRIB_TYPE_FLOAT, false, false); + bgfx_vertex_layout_add(&irodeo_gfx_state.vertex_layout, BGFX_ATTRIB_TEXCOORD1, 1, BGFX_ATTRIB_TYPE_FLOAT, false, false); + } + + // load shaders + cstr shader_path = cstr_lit("???"); + switch(bgfx_get_renderer_type()) { + case BGFX_RENDERER_TYPE_NOOP: + rodeo_log( + rodeo_logLevel_error, + "BGFX failed to get determine an appropriate renderer" + ); + exit(EXIT_FAILURE); + case BGFX_RENDERER_TYPE_OPENGLES: + cstr_assign( + &shader_path, + "shaders/100_es/" + ); + break; + case BGFX_RENDERER_TYPE_VULKAN: + cstr_assign( + &shader_path, + "shaders/spirv/" + ); + break; + case BGFX_RENDERER_TYPE_OPENGL: + cstr_assign( + &shader_path, + "shaders/opengl/" + ); + break; + default: + rodeo_log( + rodeo_logLevel_error, + "No shaders implemented for BGFX renderer chosen" + ); + exit(EXIT_FAILURE); + } + cstr vertex_shader_path = cstr_lit("simple.vertex.bin"); + cstr fragment_shader_path = cstr_lit("simple.fragment.bin"); + + cstr_insert_s( + &vertex_shader_path, + 0, + shader_path + ); + cstr_insert_s( + &fragment_shader_path, + 0, + shader_path + ); + + irodeo_gfx_state.vertex_shader = irodeo_gfx_shader_load(vertex_shader_path); + irodeo_gfx_state.fragment_shader = irodeo_gfx_shader_load(fragment_shader_path); + irodeo_gfx_state.program_shader = bgfx_create_program( + irodeo_gfx_state.vertex_shader, + irodeo_gfx_state.fragment_shader, + true + ); + rodeo_log( + rodeo_logLevel_info, + "Default render pipeline finished setup" + ); + + //bgfx_texture_handle_t default_bgfx_texture = rodeo_texture_2d_create_default(); + + irodeo_gfx_state.default_texture.internal_texture = malloc(sizeof(irodeo_gfx_texture_internal_t)); + + // used for binding textures to shader uniforms + irodeo_gfx_state.texture_uniforms[0] = bgfx_create_uniform("default_texture", BGFX_UNIFORM_TYPE_SAMPLER, 1); + irodeo_gfx_state.texture_uniforms[1] = bgfx_create_uniform("texture_0", BGFX_UNIFORM_TYPE_SAMPLER, 1); + + { + // represents 1 pixel sized white texture + const uint8_t default_texture_data[] = { + //red, blue, green, alpha + 0xff, 0xff, 0xff, 0xff, + }; + + irodeo_gfx_state.default_texture.internal_texture->texture_bgfx = + bgfx_create_texture_2d( + 1, + 1, + false, + 0, + BGFX_TEXTURE_FORMAT_RGBA8, + BGFX_SAMPLER_UVW_CLAMP | BGFX_SAMPLER_MAG_POINT, + bgfx_copy( + &default_texture_data, + sizeof(default_texture_data) + ) + ); + irodeo_gfx_state.default_texture.width = 1; + irodeo_gfx_state.default_texture.height = 1; + + irodeo_gfx_state.active_texture_p = &irodeo_gfx_state.default_texture.internal_texture->texture_bgfx; + } + + SDL_SetWindowResizable(irodeo_window_get(), true); + + bgfx_reset( + (uint32_t)rodeo_window_screen_width_get(), + (uint32_t)rodeo_window_screen_height_get(), + //BGFX_RESET_MSAA_X16 | BGFX_RESET_MAXANISOTROPY, + BGFX_RESET_VSYNC, + BGFX_TEXTURE_FORMAT_COUNT + ); + + rodeo_random_seed_set(SDL_GetTicks64()); + + irodeo_gfx_state.frame_end = (uint32_t)SDL_GetPerformanceCounter(); +} + +void +rodeo_gfx_deinit(void) +{ + + free(irodeo_gfx_state.default_texture.internal_texture); + + bgfx_destroy_program(irodeo_gfx_state.program_shader); + bgfx_shutdown(); +} + +void +rodeo_gfx_frame_begin(void) +{ + //vec3 eye = {0.0f, 0.0f, -35.0f}; + //vec3 center = {0.0f, 0.0f, 0.0f}; + //vec3 up = {0, 1, 0}; + + //glm_lookat(eye, center, up, view); + + glm_mat4_identity(irodeo_gfx_state.view_matrix); + + //glm_perspective(glm_rad(60.f), 640.f / 480.f, 0.1f, 100.0f, proj); + + // TODO: figure out if why 'zo' is correct + // but 'no' is incorrect + glm_ortho_rh_zo( + 0, + (float)rodeo_window_screen_width_get(), + (float)rodeo_window_screen_height_get(), + 0, + // near + -0.1f, + // far + 100.0f, + irodeo_gfx_state.proj_matrix + ); + + bgfx_set_view_transform(0, irodeo_gfx_state.view_matrix, irodeo_gfx_state.proj_matrix); + bgfx_set_view_rect(0, 0, 0, rodeo_window_screen_width_get(), rodeo_window_screen_height_get()); + bgfx_touch(0); + + irodeo_gfx_render_buffer_transient_alloc(); + + irodeo_gfx_state.frame_start = irodeo_gfx_state.frame_end; +} + +void +rodeo_gfx_frame_end(void) +{ + rodeo_gfx_renderer_flush(); + + bgfx_frame(false); + + #ifndef __EMSCRIPTEN__ + irodeo_gfx_frame_stall(); + #endif + irodeo_gfx_state.frame_count += 1; + irodeo_gfx_state.frame_end = (uint32_t)SDL_GetPerformanceCounter(); + // +#ifndef __EMSCRIPTEN__ + //irodeo_gfx_state.frame_time = ((float)(irodeo_gfx_state.frame_end - irodeo_gfx_state.frame_start) * 1000.0f / (float)SDL_GetPerformanceFrequency()); + irodeo_gfx_state.frame_time = (1.0f/60.f) * 1000; //((float)(state.end_frame - state.start_frame) * 1000.0f / (float)SDL_GetPerformanceFrequency()); +#else + irodeo_gfx_state.frame_time = (1.0f/60.f) * 1000; //((float)(state.end_frame - state.start_frame) * 1000.0f / (float)SDL_GetPerformanceFrequency()); +#endif +} + +float +rodeo_gfx_frame_time_get(void) +{ + return irodeo_gfx_state.frame_time; //(float)bgfx_get_stats()->cpuTimeFrame; +} + +float +rodeo_gfx_frame_perSecond_get(void) +{ + return 1.0f / (rodeo_gfx_frame_time_get() / 1000.0f); +} + +// measures how much time there is left in the remaining frame until +// the frame target time is reached. If we surpassed the target time +// then this will be negative +float +irodeo_gfx_frame_remaining_get(void) +{ + #ifdef __EMSCRIPTEN__ + float target = 60.0f; + #else + float target = (float)rodeo_gfx_frame_limit_get(); + #endif + + float result = (1/target * 1000.0f) - ((float)(SDL_GetPerformanceCounter() - irodeo_gfx_state.frame_start) / (float)SDL_GetPerformanceFrequency() * 1000.0f); + + return result; +} + + +// used internally at the end of every frame to fill for time +// in order to reach the desired framerate +void +irodeo_gfx_frame_stall(void) +{ + // if no frame limit then run as fast as possible + if(rodeo_gfx_frame_limit_get() == 0) + { + return; + } + + // sleep isnt perfectly accurate so we sleep for a slightly shorter + // amount of time + float stall_time = irodeo_gfx_frame_remaining_get(); + if(stall_time > 0.0005) + { + SDL_Delay((uint32_t)(stall_time * 0.9995)); + } + + // then we spinlock for the small remaining amount of time + stall_time = irodeo_gfx_frame_remaining_get(); + while(stall_time > 0.0005) { + stall_time = irodeo_gfx_frame_remaining_get(); + } +} + +void +rodeo_gfx_renderer_flush(void) +{ + // set default texture + bgfx_set_texture( + 0, + irodeo_gfx_state.texture_uniforms[0], + rodeo_gfx_texture_2d_default_get()->internal_texture->texture_bgfx, + UINT32_MAX + ); + if(irodeo_gfx_state.active_texture_p != NULL) + { + // set dynamic texture + bgfx_set_texture( + 1, + irodeo_gfx_state.texture_uniforms[1], + *irodeo_gfx_state.active_texture_p, + UINT32_MAX + ); + } + else + { + // set to default if none exists + bgfx_set_texture( + 1, + irodeo_gfx_state.texture_uniforms[1], + rodeo_gfx_texture_2d_default_get()->internal_texture->texture_bgfx, + UINT32_MAX + ); + } + + if(irodeo_gfx_state.vertex_size > 0) + { + bgfx_set_state( + BGFX_STATE_CULL_CW | + BGFX_STATE_WRITE_RGB | + BGFX_STATE_WRITE_A | + //BGFX_STATE_DEPTH_TEST_LESS | + //BGFX_STATE_MSAA | + BGFX_STATE_BLEND_ALPHA, + 0 + ); + + // upload remaining batched vertices + bgfx_set_transient_vertex_buffer(0, &irodeo_gfx_state.vertex_buffer_handle, 0, irodeo_gfx_state.vertex_size); + //const bgfx_memory_t* vbm = bgfx_copy(irodeo_gfx_state.batched_vertices, sizeof(rodeo_gfx_vertex_t) * irodeo_gfx_state.vertex_size); + //bgfx_update_dynamic_vertex_buffer(irodeo_gfx_state.vertex_buffer_handle, 0, vbm); + + // upload remaining batched indices + bgfx_set_transient_index_buffer(&irodeo_gfx_state.index_buffer_handle, 0, irodeo_gfx_state.index_size); + //bgfx_set_dynamic_index_buffer(irodeo_gfx_state.index_buffer_handle, 0, irodeo_gfx_state.index_size); + //const bgfx_memory_t* ibm = bgfx_copy(irodeo_gfx_state.batched_indices, sizeof(uint16_t) * irodeo_gfx_state.index_size); + //bgfx_update_dynamic_index_buffer(irodeo_gfx_state.index_buffer_handle, 0, ibm); + + + // submit vertices & batches + bgfx_submit(0, irodeo_gfx_state.program_shader, 0, BGFX_DISCARD_NONE); + + // reset arrays + irodeo_gfx_state.vertex_size = 0; + irodeo_gfx_state.index_size = 0; + irodeo_gfx_state.index_count = 0; + + // allocate new buffers + irodeo_gfx_render_buffer_transient_alloc(); + } + irodeo_gfx_state.active_texture_p = NULL; +} + +const rodeo_gfx_texture_2d_t* +rodeo_gfx_texture_2d_default_get(void) +{ + return &irodeo_gfx_state.default_texture; +} + +rodeo_gfx_texture_2d_t +rodeo_gfx_texture_2d_create_from_RGBA8( + const uint16_t width, + const uint16_t height, + const uint8_t memory[] +) +{ + rodeo_gfx_texture_2d_t texture; + texture.internal_texture = malloc(sizeof(irodeo_gfx_texture_internal_t)); + bgfx_copy(memory, (uint32_t)width * (uint32_t)height * sizeof(uint8_t) * 4); + texture.internal_texture->texture_bgfx = + bgfx_create_texture_2d( + width, + height, + false, + 0, + BGFX_TEXTURE_FORMAT_RGBA8, + BGFX_SAMPLER_UVW_CLAMP | BGFX_SAMPLER_MAG_POINT, + bgfx_copy(memory, (uint32_t)width * (uint32_t)height * sizeof(uint8_t) * 4) + ); + + texture.width = width; + texture.height = height; + + return texture; +} + +void +rodeo_gfx_texture_2d_destroy(rodeo_gfx_texture_2d_t *texture) +{ + bgfx_destroy_texture(texture->internal_texture->texture_bgfx); + free(texture->internal_texture); +} + +void +rodeo_gfx_rectangle_draw( + const rodeo_rectangle_t *rectangle, + const rodeo_color_RGBAFloat_t *color +) +{ + rodeo_gfx_texture_2d_draw( + rectangle, + NULL, + color, + NULL + ); +} + +void +rodeo_gfx_texture_2d_draw( + // cant be NULL + const rodeo_rectangle_t *destination, + // default: entire texture + const rodeo_rectangle_t *source, + // default: white + const rodeo_color_RGBAFloat_t *color, + // default: default texture + const rodeo_gfx_texture_2d_t *texture +) +{ + // whether to use default or custom texture + float texture_uniform_slot = 0.0; + + rodeo_rectangle_t source_applied; + if(source != NULL && texture != NULL) + { + source_applied = (rodeo_rectangle_t){ + .x = source->x / (float)texture->width, + .y = source->y / (float)texture->height, + .width = source->width / (float)texture->width, + .height = source->height / (float)texture->height, + }; + } + else + { + source_applied = (rodeo_rectangle_t){ + .x = 0.0f, + .y = 0.0f, + .width = 1.0f, + .height = 1.0f, + }; + } + + rodeo_color_RGBAFloat_t color_applied; + if(color != NULL) + { + color_applied = *color; + } + else + { + color_applied = (rodeo_color_RGBAFloat_t){ + { 1.0f, 1.0f, 1.0f, 1.0f } + }; + } + + // if not using texture: use default instead + // otherwise check what current texture is active + // if none or the same: set it + // if different: flush and then set it + if(texture != NULL) + { + if(irodeo_gfx_state.active_texture_p != NULL) + { + if(&texture->internal_texture->texture_bgfx != irodeo_gfx_state.active_texture_p) + { + rodeo_gfx_renderer_flush(); + } + } + texture_uniform_slot = 1.0; + irodeo_gfx_state.active_texture_p = &texture->internal_texture->texture_bgfx; + } + + + if(irodeo_gfx_state.vertex_size < mrodeo_vertex_size_max) + { + irodeo_gfx_state.batched_vertices[irodeo_gfx_state.vertex_size] = + (rodeo_gfx_vertex_t) + { + .x = destination->width + destination->x, + .y = destination->height + destination->y, + //.z = 0.0f, + .color = color_applied, + .texture_id = texture_uniform_slot, + .texture_x = source_applied.width + source_applied.x, + .texture_y = source_applied.height + source_applied.y, + }; + irodeo_gfx_state.vertex_size += 1; + irodeo_gfx_state.batched_vertices[irodeo_gfx_state.vertex_size] = + (rodeo_gfx_vertex_t) + { + .x = destination->width + destination->x, + .y = destination->y, + //.z = 0.0f, + .color = color_applied, + .texture_id = texture_uniform_slot, + .texture_x = source_applied.width + source_applied.x, + .texture_y = source_applied.y, + }; + irodeo_gfx_state.vertex_size += 1; + irodeo_gfx_state.batched_vertices[irodeo_gfx_state.vertex_size] = + (rodeo_gfx_vertex_t) + { + .x = destination->x, + .y = destination->y, + //.z = 0.0f, + .color = color_applied, + .texture_id = texture_uniform_slot, + .texture_x = source_applied.x, + .texture_y = source_applied.y, + }; + irodeo_gfx_state.vertex_size += 1; + irodeo_gfx_state.batched_vertices[irodeo_gfx_state.vertex_size] = + (rodeo_gfx_vertex_t) + { + .x = destination->x, + .y = destination->height + destination->y, + //.z = 0.0f, + .color = color_applied, + .texture_id = texture_uniform_slot, + .texture_x = source_applied.x, + .texture_y = source_applied.height + source_applied.y, + }; + irodeo_gfx_state.vertex_size += 1; + + irodeo_index_type_t indices[] = + { + 0, 1, 3, + 1, 2, 3 + //2, 1, 0, + //2, 3, 1 + }; + irodeo_gfx_state.batched_indices[irodeo_gfx_state.index_size] = irodeo_gfx_state.index_count + indices[0]; + irodeo_gfx_state.index_size += 1; + irodeo_gfx_state.batched_indices[irodeo_gfx_state.index_size] = irodeo_gfx_state.index_count + indices[1]; + irodeo_gfx_state.index_size += 1; + irodeo_gfx_state.batched_indices[irodeo_gfx_state.index_size] = irodeo_gfx_state.index_count + indices[2]; + irodeo_gfx_state.index_size += 1; + irodeo_gfx_state.batched_indices[irodeo_gfx_state.index_size] = irodeo_gfx_state.index_count + indices[3]; + irodeo_gfx_state.index_size += 1; + irodeo_gfx_state.batched_indices[irodeo_gfx_state.index_size] = irodeo_gfx_state.index_count + indices[4]; + irodeo_gfx_state.index_size += 1; + irodeo_gfx_state.batched_indices[irodeo_gfx_state.index_size] = irodeo_gfx_state.index_count + indices[5]; + irodeo_gfx_state.index_size += 1; + irodeo_gfx_state.index_count += 4; + } + + if(irodeo_gfx_state.vertex_size >= mrodeo_vertex_size_max) + { + rodeo_gfx_renderer_flush(); + } +} + +rodeo_gfx_texture_2d_t +rodeo_gfx_texture_2d_create_from_path(cstr path) +{ + // load image to surface + SDL_Surface *surface = IMG_Load(cstr_str(&path)); + if(surface == NULL) + { + rodeo_log( + rodeo_logLevel_error, + "Loading texture from image failed: %s", + IMG_GetError() + ); + return (rodeo_gfx_texture_2d_t){0}; + } + + // check and handle a color key for transparency + // not sure if I actually need this... + //uint32_t color_key; + //if(SDL_GetColorKey(surface, &color_key) == 0) + //{ + // SDL_SetColorKey(surface, SDL_TRUE, color_key); + //} + + // convert pixel format of surface into RGBA8 + SDL_Surface *converted_surface = + SDL_ConvertSurfaceFormat( + surface, + // pixel format needs to be backwards + // of what bgfx uses for some reason + SDL_PIXELFORMAT_ABGR8888, + 0 + ); + if(converted_surface == NULL) + { + rodeo_log( + rodeo_logLevel_error, + "Converting image to RGBA8 while loading texture failed: %s", + SDL_GetError() + ); + SDL_FreeSurface(surface); + return (rodeo_gfx_texture_2d_t){0}; + } + + // load the pixel data into our own texture + rodeo_gfx_texture_2d_t texture = rodeo_gfx_texture_2d_create_from_RGBA8( + (uint16_t)converted_surface->w, + (uint16_t)converted_surface->h, + converted_surface->pixels + ); + + SDL_FreeSurface(surface); + SDL_FreeSurface(converted_surface); + + return texture; +} + +uint64_t +rodeo_gfx_frame_count_get(void) +{ + return irodeo_gfx_state.frame_count; +} + +void +rodeo_gfx_frame_limit_set(uint32_t limit) +{ + #ifdef __EMSCRIPTEN__ + rodeo_log( + rodeo_logLevel_warning, + "Framerate limit cannot be set on web platform. Limit is enforced by platform to 60fps" + ); + #else + irodeo_gfx_state.frame_limit = limit; + #endif +} + +uint32_t +rodeo_gfx_frame_limit_get(void) +{ + #ifdef __EMSCRIPTEN__ + return 60; + #else + return irodeo_gfx_state.frame_limit; + #endif +} + +cstr +rodeo_gfx_renderer_name_get(void) +{ + return cstr_from( + bgfx_get_renderer_name(bgfx_get_renderer_type()) + ); +} + +bgfx_shader_handle_t +irodeo_gfx_shader_load(const cstr path) +{ + const char* path_cstr = cstr_str(&path); + + FILE *file = fopen(path_cstr, "rb"); + + if(!file) + { + rodeo_log( + rodeo_logLevel_error, + "Shader file \"%s\" not found", + path_cstr + ); + return (bgfx_shader_handle_t)BGFX_INVALID_HANDLE; + } + + fseek(file, 0, SEEK_END); + int64_t file_size_temp = ftell(file); + if(file_size_temp < 0) + { + rodeo_log( + rodeo_logLevel_error, + "Failed to get current file position of given stream(ftell() error)" + ); + exit(EXIT_FAILURE); + } + if((file_size_temp + 1) > UINT32_MAX) + { + rodeo_log( + rodeo_logLevel_error, + "File size larger then what bgfx can allocate" + ); + exit(EXIT_FAILURE); + } + uint32_t file_size = (uint32_t)file_size_temp; + fseek(file, 0, SEEK_SET); + + + const bgfx_memory_t *mem = bgfx_alloc(file_size + 1); + fread(mem->data, 1, file_size, file); + mem->data[mem->size - 1] = '\0'; + fclose(file); + + bgfx_shader_handle_t shader = bgfx_create_shader(mem); + rodeo_log( + rodeo_logLevel_info, + "Shader loaded with idx: %"PRIu8"", + shader.idx + ); + + return shader; +} + +void +irodeo_gfx_render_buffer_transient_alloc(void) +{ + bgfx_alloc_transient_vertex_buffer(&irodeo_gfx_state.vertex_buffer_handle, mrodeo_vertex_size_max, &irodeo_gfx_state.vertex_layout); + bgfx_alloc_transient_index_buffer(&irodeo_gfx_state.index_buffer_handle, mrodeo_index_size_max, false); + irodeo_gfx_state.batched_vertices = (rodeo_gfx_vertex_t*)irodeo_gfx_state.vertex_buffer_handle.data; + irodeo_gfx_state.batched_indices = (irodeo_index_type_t*)irodeo_gfx_state.index_buffer_handle.data; +} + diff --git a/src/input/rodeo_input.c b/src/input/rodeo_input.c index f6f0d9f..ee2d180 100644 --- a/src/input/rodeo_input.c +++ b/src/input/rodeo_input.c @@ -4,8 +4,10 @@ #include "rodeo/input.h" #include "irodeo_input_t.h" #include "rodeo/log.h" -// pirvate +#include "rodeo/window.h" +// private #include "rodeo_internal.h" +#include "window/irodeo_window.h" // -- external -- #include "SDL.h" @@ -17,7 +19,7 @@ static irodeo_input_state_t istate = {0}; bool -rodeo_input_events_poll(void) +rodeo_input_poll(void) { SDL_Event event = {0}; while(SDL_PollEvent(&event)) @@ -26,7 +28,7 @@ rodeo_input_events_poll(void) { case SDL_QUIT: { - return true; + rodeo_window_quit(); } //break; case SDL_WINDOWEVENT: @@ -41,17 +43,17 @@ rodeo_input_events_poll(void) BGFX_RESET_VSYNC, BGFX_TEXTURE_FORMAT_COUNT ); - irodeo_screen_width_set((uint16_t)width); - irodeo_screen_height_set((uint16_t)height); + irodeo_window_screen_width_setVar((uint16_t)width); + irodeo_window_screen_height_setVar((uint16_t)height); rodeo_log( rodeo_logLevel_warning, "%"PRIu16"x", - rodeo_screen_width_get() + rodeo_window_screen_width_get() ); rodeo_log( rodeo_logLevel_warning, "%"PRIu16"\n", - rodeo_screen_height_get() + rodeo_window_screen_height_get() ); } } diff --git a/src/rodeo.c b/src/rodeo.c index 6978a52..4699f86 100644 --- a/src/rodeo.c +++ b/src/rodeo.c @@ -3,7 +3,6 @@ // public #include "rodeo.h" #include "rodeo_types.h" -#include "rodeo/input.h" // private #include "rodeo_internal.h" #include "rodeo_internal_types.h" @@ -31,383 +30,6 @@ static irodeo_state_t state = {0}; void -rodeo_window_init( - uint16_t screen_height, - uint16_t screen_width, - cstr title -) -{ - state.window = NULL; - state.screen_surface = NULL; - state.screen_height = screen_height; - state.screen_width = screen_width; - state.frame_count = 0; - - rodeo_log( - rodeo_logLevel_info, - "Initializing SDL..." - ); - - { - uint32_t init_flags_sdl = 0; - init_flags_sdl = init_flags_sdl | SDL_INIT_VIDEO; - init_flags_sdl = init_flags_sdl | SDL_INIT_AUDIO; - init_flags_sdl = init_flags_sdl | SDL_INIT_GAMECONTROLLER; - - if(SDL_Init(init_flags_sdl) < 0) - { - rodeo_log( - rodeo_logLevel_error, - "Failed to initialize SDL. SDL_Error: %s", - SDL_GetError() - ); - exit(EXIT_FAILURE); - } - rodeo_log( - rodeo_logLevel_info, - "Success initializing SDL" - ); - } - - rodeo_log( - rodeo_logLevel_info, - "Initializing SDL window..." - ); - state.window = SDL_CreateWindow( - cstr_str(&title), - SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, - screen_width, - screen_height, - SDL_WINDOW_SHOWN //| SDL_WINDOW_RESIZABLE - ); - if(state.window == NULL) - { - rodeo_log( - rodeo_logLevel_error, - "Failed creating SDL window. SDL_Error: %s", - SDL_GetError() - ); - exit(EXIT_FAILURE); - } - rodeo_log( - rodeo_logLevel_info, - "Success initializing SDL window" - ); - -#if !__EMSCRIPTEN__ - rodeo_log( - rodeo_logLevel_info, - "SDL setting up driver specific information..." - ); - SDL_VERSION(&state.wmi.version); - if( - !SDL_GetWindowWMInfo( - state.window, - &state.wmi - ) - ) - { - rodeo_log( - rodeo_logLevel_error, - "SDL failed to get driver specific information. SDL Error: %s", SDL_GetError() - ); - exit(EXIT_FAILURE); - } - rodeo_log( - rodeo_logLevel_info, - "Success getting driver specific information" - ); - bgfx_render_frame(-1); -#endif - - - bgfx_platform_data_t pd; - memset(&pd, 0, sizeof(bgfx_platform_data_t)); - -#if !__EMSCRIPTEN__ - // x11 - pd.ndt = state.wmi.info.x11.display; - pd.nwh = (void*)(uintptr_t)state.wmi.info.x11.window; -#else - // web - pd.nwh = (void*)"#canvas"; -#endif - - bgfx_init_t init = {0}; - bgfx_init_ctor(&init); - //init.type = BGFX_RENDERER_TYPE_COUNT; // auto determine renderer - init.type = BGFX_RENDERER_TYPE_OPENGL; // force opengl renderer - //SDL_GetWindowSize(state.window, &state.screen_width, &state.screen_height); - init.resolution.width = state.screen_width; - init.resolution.height = state.screen_height; - init.resolution.reset = BGFX_RESET_VSYNC; - init.platformData = pd; - bgfx_init(&init); - - bgfx_set_debug(BGFX_DEBUG_TEXT); - - //bgfx_set_state(BGFX_STATE_CULL_CCW, 0); - - //bgfx_dbg_text_clear(0x65, false); - - bgfx_set_view_clear( - 0, - BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, - 0x443355FF, - 1.0f, - 0 - ); - bgfx_set_view_rect(0, 0, 0, state.screen_width, state.screen_height); - - rodeo_log(rodeo_logLevel_info, "Setting up default render pipeline..."); - // set up vertex layout - mrodeo_bgfx_vertex_layout_do(&state.vertex_layout) - { - bgfx_vertex_layout_add(&state.vertex_layout, BGFX_ATTRIB_POSITION, 3, BGFX_ATTRIB_TYPE_FLOAT, false, false); - bgfx_vertex_layout_add(&state.vertex_layout, BGFX_ATTRIB_COLOR0, 4, BGFX_ATTRIB_TYPE_FLOAT, false, false); - bgfx_vertex_layout_add(&state.vertex_layout, BGFX_ATTRIB_TEXCOORD0, 2, BGFX_ATTRIB_TYPE_FLOAT, false, false); - bgfx_vertex_layout_add(&state.vertex_layout, BGFX_ATTRIB_TEXCOORD1, 1, BGFX_ATTRIB_TYPE_FLOAT, false, false); - } - - // load shaders - cstr shader_path = cstr_lit("???"); - switch(bgfx_get_renderer_type()) { - case BGFX_RENDERER_TYPE_NOOP: - rodeo_log( - rodeo_logLevel_error, - "BGFX failed to get determine an appropriate renderer" - ); - exit(EXIT_FAILURE); - case BGFX_RENDERER_TYPE_OPENGLES: - cstr_assign( - &shader_path, - "shaders/100_es/" - ); - break; - case BGFX_RENDERER_TYPE_VULKAN: - cstr_assign( - &shader_path, - "shaders/spirv/" - ); - break; - case BGFX_RENDERER_TYPE_OPENGL: - cstr_assign( - &shader_path, - "shaders/opengl/" - ); - break; - default: - rodeo_log( - rodeo_logLevel_error, - "No shaders implemented for BGFX renderer chosen" - ); - exit(EXIT_FAILURE); - } - cstr vertex_shader_path = cstr_lit("simple.vertex.bin"); - cstr fragment_shader_path = cstr_lit("simple.fragment.bin"); - - cstr_insert_s( - &vertex_shader_path, - 0, - shader_path - ); - cstr_insert_s( - &fragment_shader_path, - 0, - shader_path - ); - - state.vertex_shader = irodeo_shader_load(vertex_shader_path); - state.fragment_shader = irodeo_shader_load(fragment_shader_path); - state.program_shader = bgfx_create_program( - state.vertex_shader, - state.fragment_shader, - true - ); - rodeo_log( - rodeo_logLevel_info, - "Default render pipeline finished setup" - ); - - //bgfx_texture_handle_t default_bgfx_texture = rodeo_texture_2d_create_default(); - - state.default_texture.internal_texture = malloc(sizeof(irodeo_texture_internal_t)); - - // used for binding textures to shader uniforms - state.texture_uniforms[0] = bgfx_create_uniform("default_texture", BGFX_UNIFORM_TYPE_SAMPLER, 1); - state.texture_uniforms[1] = bgfx_create_uniform("texture_0", BGFX_UNIFORM_TYPE_SAMPLER, 1); - - { - // represents 1 pixel sized white texture - const uint8_t default_texture_data[] = { - //red, blue, green, alpha - 0xff, 0xff, 0xff, 0xff, - }; - - state.default_texture.internal_texture->texture_bgfx = - bgfx_create_texture_2d( - 1, - 1, - false, - 0, - BGFX_TEXTURE_FORMAT_RGBA8, - BGFX_SAMPLER_UVW_CLAMP | BGFX_SAMPLER_MAG_POINT, - bgfx_copy( - &default_texture_data, - sizeof(default_texture_data) - ) - ); - state.default_texture.width = 1; - state.default_texture.height = 1; - - rodeo_audio_initialize(4 * 4); - - state.active_texture_p = &state.default_texture.internal_texture->texture_bgfx; - } - - SDL_SetWindowResizable(state.window, true); - - /* - rodeo_log( - rodeo_logLevel_info, - "%"PRIu32", %b\n", - bgfx_get_caps()->limits.transientVbSize, - bgfx_get_caps()->homogeneousDepth - );*/ - - //vec3 eye = {0.0f, 0.0f, -35.0f}; - //vec3 center = {0.0f, 0.0f, 0.0f}; - //vec3 up = {0, 1, 0}; - - //glm_lookat(eye, center, up, view); - - glm_mat4_identity(state.view_matrix); - - //glm_perspective(glm_rad(60.f), 640.f / 480.f, 0.1f, 100.0f, proj); - - // TODO: figure out if why 'zo' is correct - // but 'no' is incorrect - glm_ortho_rh_zo( - 0, - (float)state.screen_width, - (float)state.screen_height, - 0, - // near - -0.1f, - // far - 100.0f, - state.proj_matrix - ); - - rodeo_random_seed_set(SDL_GetTicks64()); - - state.end_frame = SDL_GetPerformanceCounter(); -} - -void -rodeo_window_deinit(void) -{ - free(state.default_texture.internal_texture); - - //bgfx_destroy_dynamic_index_buffer(state.index_buffer_handle); - //bgfx_destroy_dynamic_vertex_buffer(state.vertex_buffer_handle); - bgfx_destroy_program(state.program_shader); - bgfx_shutdown(); - - SDL_DestroyWindow(state.window); - Mix_Quit(); - SDL_Quit(); -} - -SDL_Window * -irodeo_window_get(void) -{ - return state.window; -} - -uint16_t -rodeo_screen_width_get(void) -{ - return state.screen_width; -} - -uint16_t -rodeo_screen_height_get(void) -{ - return state.screen_height; -} - -void -irodeo_screen_width_set(uint16_t width) -{ - state.screen_width = width; -} - -void -irodeo_screen_height_set(uint16_t height) -{ - state.screen_height = height; -} - -void -rodeo_frame_begin(void) -{ - state.quit = rodeo_input_events_poll(); - - bgfx_set_view_transform(0, state.view_matrix, state.proj_matrix); - bgfx_set_view_rect(0, 0, 0, state.screen_width, state.screen_height); - bgfx_touch(0); - - irodeo_render_buffer_transient_alloc(); - - state.start_frame = state.end_frame; -} - -void -rodeo_frame_end(void) -{ - rodeo_renderer_flush(); - - bgfx_frame(false); - - #ifndef __EMSCRIPTEN__ - irodeo_frame_stall(); - #endif - state.frame_count += 1; - state.end_frame = SDL_GetPerformanceCounter(); - -#ifndef __EMSCRIPTEN__ - state.frame_time = ((float)(state.end_frame - state.start_frame) * 1000.0f / (float)SDL_GetPerformanceFrequency()); -#else - state.frame_time = (1.0f/60.f) * 1000; //((float)(state.end_frame - state.start_frame) * 1000.0f / (float)SDL_GetPerformanceFrequency()); -#endif - - - /* - float minimum_fps = 20.0f; - float temp_frame_time = ((float)(state.end_frame - state.start_frame) * 1000.0f / (float)SDL_GetPerformanceFrequency()); - state.frame_time = (temp_frame_time < ((1.0f/minimum_fps) * 1000)) ? temp_frame_time : ((1.0f / minimum_fps) * 1000); - */ - /* - rodeo_log( - rodeo_logLevel_info, - "Vertex Buffer Used: %f", - (float)bgfx_get_stats()->transientVbUsed / (float)bgfx_get_caps()->limits.transientVbSize - ); - */ -} - -void -irodeo_render_buffer_transient_alloc(void) -{ - bgfx_alloc_transient_vertex_buffer(&state.vertex_buffer_handle, mrodeo_vertex_size_max, &state.vertex_layout); - bgfx_alloc_transient_index_buffer(&state.index_buffer_handle, mrodeo_index_size_max, false); - state.batched_vertices = (rodeo_vertex_t*)state.vertex_buffer_handle.data; - state.batched_indices = (irodeo_index_type_t*)state.index_buffer_handle.data; -} - -void rodeo_mainLoop_run( rodeo_mainLoop_function main_loop_func ) @@ -415,25 +37,13 @@ rodeo_mainLoop_run( #if __EMSCRIPTEN__ emscripten_set_main_loop(main_loop_func, 0, 1); #else - while(!rodeo_window_quit_get()) + while(!rodeo_window_shouldQuit()) { main_loop_func(); } #endif } -bool -rodeo_window_quit_get(void) -{ - return state.quit; -} - -void -rodeo_window_quit_set(bool quit) -{ - state.quit = quit; -} - void rodeo_debug_text_draw(u_int16_t x, u_int16_t y, const char *format, ...) { @@ -443,432 +53,6 @@ rodeo_debug_text_draw(u_int16_t x, u_int16_t y, const char *format, ...) } } -cstr -rodeo_renderer_name_get(void) -{ - return cstr_from( - bgfx_get_renderer_name(bgfx_get_renderer_type()) - ); -} - -void -rodeo_renderer_flush(void) -{ - // set default texture - bgfx_set_texture( - 0, - state.texture_uniforms[0], - rodeo_texture_2d_default_get()->internal_texture->texture_bgfx, - UINT32_MAX - ); - if(state.active_texture_p != NULL) - { - // set dynamic texture - bgfx_set_texture( - 1, - state.texture_uniforms[1], - *state.active_texture_p, - UINT32_MAX - ); - } - else - { - // set to default if none exists - bgfx_set_texture( - 1, - state.texture_uniforms[1], - rodeo_texture_2d_default_get()->internal_texture->texture_bgfx, - UINT32_MAX - ); - } - - if(state.vertex_size > 0) - { - bgfx_set_state( - BGFX_STATE_CULL_CW | - BGFX_STATE_WRITE_RGB | - BGFX_STATE_WRITE_A | - //BGFX_STATE_DEPTH_TEST_LESS | - //BGFX_STATE_MSAA | - BGFX_STATE_BLEND_ALPHA, - 0 - ); - - // upload remaining batched vertices - bgfx_set_transient_vertex_buffer(0, &state.vertex_buffer_handle, 0, state.vertex_size); - //const bgfx_memory_t* vbm = bgfx_copy(state.batched_vertices, sizeof(rodeo_vertex_t) * state.vertex_size); - //bgfx_update_dynamic_vertex_buffer(state.vertex_buffer_handle, 0, vbm); - - // upload remaining batched indices - bgfx_set_transient_index_buffer(&state.index_buffer_handle, 0, state.index_size); - //bgfx_set_dynamic_index_buffer(state.index_buffer_handle, 0, state.index_size); - //const bgfx_memory_t* ibm = bgfx_copy(state.batched_indices, sizeof(uint16_t) * state.index_size); - //bgfx_update_dynamic_index_buffer(state.index_buffer_handle, 0, ibm); - - - // submit vertices & batches - bgfx_submit(0, state.program_shader, 0, BGFX_DISCARD_NONE); - - // reset arrays - state.vertex_size = 0; - state.index_size = 0; - state.index_count = 0; - - // allocate new buffers - irodeo_render_buffer_transient_alloc(); - } - state.active_texture_p = NULL; -} - -const rodeo_texture_2d_t* -rodeo_texture_2d_default_get(void) -{ - return &state.default_texture; -} - -rodeo_texture_2d_t -rodeo_texture_2d_create_from_RGBA8( - const uint16_t width, - const uint16_t height, - const uint8_t memory[] -) -{ - rodeo_texture_2d_t texture; - texture.internal_texture = malloc(sizeof(irodeo_texture_internal_t)); - texture.internal_texture->texture_bgfx = - bgfx_create_texture_2d( - width, - height, - false, - 0, - BGFX_TEXTURE_FORMAT_RGBA8, - BGFX_SAMPLER_UVW_CLAMP | BGFX_SAMPLER_MAG_POINT, - bgfx_copy(memory, (uint32_t)width * (uint32_t)height * sizeof(uint8_t) * 4) - ); - - texture.width = width; - texture.height = height; - - return texture; -} - -void -rodeo_texture_2d_destroy(rodeo_texture_2d_t *texture) -{ - bgfx_destroy_texture(texture->internal_texture->texture_bgfx); - free(texture->internal_texture); -} - -void -rodeo_rectangle_draw( - const rodeo_rectangle_t *rectangle, - const rodeo_color_RGBAFloat_t *color -) -{ - rodeo_texture_2d_draw( - rectangle, - NULL, - color, - NULL - ); -} - -void -rodeo_texture_2d_draw( - // cant be NULL - const rodeo_rectangle_t *destination, - // default: entire texture - const rodeo_rectangle_t *source, - // default: white - const rodeo_color_RGBAFloat_t *color, - // default: default texture - const rodeo_texture_2d_t *texture -) -{ - // whether to use default or custom texture - float texture_uniform_slot = 0.0; - - rodeo_rectangle_t source_applied; - if(source != NULL && texture != NULL) - { - source_applied = (rodeo_rectangle_t){ - .x = source->x / (float)texture->width, - .y = source->y / (float)texture->height, - .width = source->width / (float)texture->width, - .height = source->height / (float)texture->height, - }; - } - else - { - source_applied = (rodeo_rectangle_t){ - .x = 0.0f, - .y = 0.0f, - .width = 1.0f, - .height = 1.0f, - }; - } - - rodeo_color_RGBAFloat_t color_applied; - if(color != NULL) - { - color_applied = *color; - } - else - { - color_applied = (rodeo_color_RGBAFloat_t){ - { 1.0f, 1.0f, 1.0f, 1.0f } - }; - } - - // if not using texture: use default instead - // otherwise check what current texture is active - // if none or the same: set it - // if different: flush and then set it - if(texture != NULL) - { - if(state.active_texture_p != NULL) - { - if(&texture->internal_texture->texture_bgfx != state.active_texture_p) - { - rodeo_renderer_flush(); - } - } - texture_uniform_slot = 1.0; - state.active_texture_p = &texture->internal_texture->texture_bgfx; - } - - - if(state.vertex_size < mrodeo_vertex_size_max) - { - state.batched_vertices[state.vertex_size] = - (rodeo_vertex_t) - { - .x = destination->width + destination->x, - .y = destination->height + destination->y, - //.z = 0.0f, - .color = color_applied, - .texture_id = texture_uniform_slot, - .texture_x = source_applied.width + source_applied.x, - .texture_y = source_applied.height + source_applied.y, - }; - state.vertex_size += 1; - state.batched_vertices[state.vertex_size] = - (rodeo_vertex_t) - { - .x = destination->width + destination->x, - .y = destination->y, - //.z = 0.0f, - .color = color_applied, - .texture_id = texture_uniform_slot, - .texture_x = source_applied.width + source_applied.x, - .texture_y = source_applied.y, - }; - state.vertex_size += 1; - state.batched_vertices[state.vertex_size] = - (rodeo_vertex_t) - { - .x = destination->x, - .y = destination->y, - //.z = 0.0f, - .color = color_applied, - .texture_id = texture_uniform_slot, - .texture_x = source_applied.x, - .texture_y = source_applied.y, - }; - state.vertex_size += 1; - state.batched_vertices[state.vertex_size] = - (rodeo_vertex_t) - { - .x = destination->x, - .y = destination->height + destination->y, - //.z = 0.0f, - .color = color_applied, - .texture_id = texture_uniform_slot, - .texture_x = source_applied.x, - .texture_y = source_applied.height + source_applied.y, - }; - state.vertex_size += 1; - - irodeo_index_type_t indices[] = - { - 0, 1, 3, - 1, 2, 3 - //2, 1, 0, - //2, 3, 1 - }; - state.batched_indices[state.index_size] = state.index_count + indices[0]; - state.index_size += 1; - state.batched_indices[state.index_size] = state.index_count + indices[1]; - state.index_size += 1; - state.batched_indices[state.index_size] = state.index_count + indices[2]; - state.index_size += 1; - state.batched_indices[state.index_size] = state.index_count + indices[3]; - state.index_size += 1; - state.batched_indices[state.index_size] = state.index_count + indices[4]; - state.index_size += 1; - state.batched_indices[state.index_size] = state.index_count + indices[5]; - state.index_size += 1; - state.index_count += 4; - } - - if(state.vertex_size >= mrodeo_vertex_size_max) - { - rodeo_renderer_flush(); - } -} - -rodeo_texture_2d_t -rodeo_texture_2d_create_from_path(cstr path) -{ - // load image to surface - SDL_Surface *surface = IMG_Load(cstr_str(&path)); - if(surface == NULL) - { - rodeo_log( - rodeo_logLevel_error, - "Loading texture from image failed: %s", - IMG_GetError() - ); - return (rodeo_texture_2d_t){0}; - } - - // check and handle a color key for transparency - // not sure if I actually need this... - //uint32_t color_key; - //if(SDL_GetColorKey(surface, &color_key) == 0) - //{ - // SDL_SetColorKey(surface, SDL_TRUE, color_key); - //} - - // convert pixel format of surface into RGBA8 - SDL_Surface *converted_surface = - SDL_ConvertSurfaceFormat( - surface, - // pixel format needs to be backwards - // of what bgfx uses for some reason - SDL_PIXELFORMAT_ABGR8888, - 0 - ); - if(converted_surface == NULL) - { - rodeo_log( - rodeo_logLevel_error, - "Converting image to RGBA8 while loading texture failed: %s", - SDL_GetError() - ); - SDL_FreeSurface(surface); - return (rodeo_texture_2d_t){0}; - } - - // load the pixel data into our own texture - rodeo_texture_2d_t texture = rodeo_texture_2d_create_from_RGBA8( - (uint16_t)converted_surface->w, - (uint16_t)converted_surface->h, - converted_surface->pixels - ); - - SDL_FreeSurface(surface); - SDL_FreeSurface(converted_surface); - - return texture; -} - -bgfx_shader_handle_t -irodeo_shader_load(const cstr path) -{ - const char* path_cstr = cstr_str(&path); - bgfx_shader_handle_t invalid = BGFX_INVALID_HANDLE; - - FILE *file = fopen(path_cstr, "rb"); - - if(!file) - { - rodeo_log( - rodeo_logLevel_error, - "Shader file \"%s\" not found", - path_cstr - ); - return invalid; - } - - fseek(file, 0, SEEK_END); - int64_t file_size_temp = ftell(file); - if(file_size_temp < 0) - { - rodeo_log( - rodeo_logLevel_error, - "Failed to get current file position of given stream(ftell() error)" - ); - exit(EXIT_FAILURE); - } - if((file_size_temp + 1) > UINT32_MAX) - { - rodeo_log( - rodeo_logLevel_error, - "File size larger then what bgfx can allocate" - ); - exit(EXIT_FAILURE); - } - uint32_t file_size = (uint32_t)file_size_temp; - fseek(file, 0, SEEK_SET); - - - const bgfx_memory_t *mem = bgfx_alloc(file_size + 1); - fread(mem->data, 1, file_size, file); - mem->data[mem->size - 1] = '\0'; - fclose(file); - - bgfx_shader_handle_t shader = bgfx_create_shader(mem); - rodeo_log( - rodeo_logLevel_info, - "Shader loaded with idx: %"PRIu8"", - shader.idx - ); - - return shader; -} - -uint64_t -rodeo_frame_count_get(void) -{ - return state.frame_count; -} - -float -rodeo_frame_time_get(void) -{ - return state.frame_time; -} - -float -rodeo_frame_perSecond_get(void) -{ - return 1.0f / (rodeo_frame_time_get() / 1000.0f); -} - -void -rodeo_frame_limit_set(uint32_t limit) -{ - #ifdef __EMSCRIPTEN__ - rodeo_log( - rodeo_logLevel_warning, - "Framerate limit cannot be set on web platform. Limit is enforced by platform to 60fps" - ); - #else - state.frame_limit = limit; - #endif -} - -uint32_t -rodeo_frame_limit_get(void) -{ - #ifdef __EMSCRIPTEN__ - return 60; - #else - return state.frame_limit; - #endif -} - void irodeo_random_seed_set(stc64_t seed) { @@ -881,46 +65,3 @@ irodeo_random_seed_get(void) return &state.random_seed; } -// measures how much time there is left in the remaining frame until -// the frame target time is reached. If we surpassed the target time -// then this will be negative -float -irodeo_frame_remaining_get(void) -{ - #ifdef __EMSCRIPTEN__ - float target = 60.0f; - #else - float target = (float)rodeo_frame_limit_get(); - #endif - - float result = (1/target * 1000.0f) - ((float)(SDL_GetPerformanceCounter() - state.start_frame) / (float)SDL_GetPerformanceFrequency() * 1000.0f); - - return result; -} - -// used internally at the end of every frame to fill for time -// in order to reach the desired framerate -void -irodeo_frame_stall(void) -{ - // if no frame limit then run as fast as possible - if(rodeo_frame_limit_get() == 0) - { - return; - } - - // sleep isnt perfectly accurate so we sleep for a slightly shorter - // amount of time - float stall_time = irodeo_frame_remaining_get(); - if(stall_time > 0.0005) - { - SDL_Delay((uint32_t)(stall_time * 0.9995)); - } - - // then we spinlock for the small remaining amount of time - stall_time = irodeo_frame_remaining_get(); - while(stall_time > 0.0005) { - stall_time = irodeo_frame_remaining_get(); - } -} - diff --git a/src/rodeo_internal.h b/src/rodeo_internal.h index 167215b..cc76df7 100644 --- a/src/rodeo_internal.h +++ b/src/rodeo_internal.h @@ -8,30 +8,6 @@ // -- external -- #include "SDL.h" -#define \ -mrodeo_bgfx_vertex_layout_do(vertex_layout) \ - mrodeo_defer_do( \ - bgfx_vertex_layout_begin( \ - vertex_layout, \ - bgfx_get_renderer_type() \ - ), \ - bgfx_vertex_layout_end(vertex_layout) \ - ) - -SDL_Window * -irodeo_window_get(void); - -void -irodeo_screen_width_set(uint16_t width); - -void -irodeo_screen_height_set(uint16_t height); - -void -irodeo_render_buffer_transient_alloc(void); - -bgfx_shader_handle_t -irodeo_shader_load(const cstr path); void irodeo_random_seed_set(stc64_t seed); @@ -39,8 +15,3 @@ irodeo_random_seed_set(stc64_t seed); stc64_t* irodeo_random_seed_get(void); -float -irodeo_frame_remaining_get(void); - -void -irodeo_frame_stall(void); diff --git a/src/rodeo_internal_types.h b/src/rodeo_internal_types.h index 4b3a6ff..263b9c0 100644 --- a/src/rodeo_internal_types.h +++ b/src/rodeo_internal_types.h @@ -18,50 +18,11 @@ /*#define CGLM_CLIPSPACE_INCLUDE_ALL*/ #include "cglm/cglm.h" -typedef uint16_t irodeo_index_type_t; - typedef struct { - SDL_Window* window; - SDL_Surface* screen_surface; - SDL_SysWMinfo wmi; - uint16_t screen_width; - uint16_t screen_height; - SDL_Event sdl_event; - bool quit; - - bgfx_vertex_layout_t vertex_layout; - //bgfx_dynamic_vertex_buffer_handle_t vertex_buffer_handle; - //bgfx_dynamic_index_buffer_handle_t index_buffer_handle; - bgfx_transient_vertex_buffer_t vertex_buffer_handle; - bgfx_transient_index_buffer_t index_buffer_handle; - rodeo_vertex_t *batched_vertices; - irodeo_index_type_t *batched_indices; - irodeo_index_type_t vertex_size; - irodeo_index_type_t index_count; - irodeo_index_type_t index_size; - //irodeo_index_type_t batched_indices[(mrodeo_vertex_size_max / 4) * 6]; - rodeo_texture_2d_t default_texture; - bgfx_texture_handle_t *active_texture_p; - bgfx_shader_handle_t vertex_shader; - bgfx_shader_handle_t fragment_shader; - bgfx_program_handle_t program_shader; - bgfx_uniform_handle_t texture_uniforms[2]; - mat4 view_matrix; - mat4 proj_matrix; - stc64_t random_seed; uint64_t frame_count; - uint64_t start_frame; - uint64_t end_frame; - float frame_time; uint32_t frame_limit; } irodeo_state_t; - -struct -irodeo_texture_internal_t -{ - bgfx_texture_handle_t texture_bgfx; -}; diff --git a/src/window/irodeo_window.h b/src/window/irodeo_window.h new file mode 100644 index 0000000..f0c02e2 --- /dev/null +++ b/src/window/irodeo_window.h @@ -0,0 +1,30 @@ +#pragma once + +// -- internal -- +// private +#include "irodeo_window_t.h" + +// -- external -- +#include "SDL.h" +#include "SDL_syswm.h" + +SDL_Window * +irodeo_window_get(void); + +SDL_Surface * +irodeo_window_surface_get(void); + +void +irodeo_window_screen_width_setVar(uint16_t width); + +void +irodeo_window_screen_height_setVar(uint16_t height); + +SDL_Window * +irodeo_window_get(void); + +SDL_Surface * +irodeo_window_surface_get(void); + +SDL_SysWMinfo +irodeo_window_wmi_get(void); diff --git a/src/window/irodeo_window_t.h b/src/window/irodeo_window_t.h new file mode 100644 index 0000000..e2dd0a4 --- /dev/null +++ b/src/window/irodeo_window_t.h @@ -0,0 +1,21 @@ +#pragma once + +// -- external -- +#include "SDL.h" +#include "SDL_syswm.h" + +// -- system -- +#include "inttypes.h" +#include "stdbool.h" + +typedef +struct +{ + SDL_Window* window; + SDL_Surface* screen_surface; + SDL_SysWMinfo wmi; + uint16_t screen_width; + uint16_t screen_height; + bool quit; +} +irodeo_window_state_t; diff --git a/src/window/rodeo_window.c b/src/window/rodeo_window.c new file mode 100644 index 0000000..5267bfa --- /dev/null +++ b/src/window/rodeo_window.c @@ -0,0 +1,166 @@ + +// -- internal -- +// public +#include "rodeo/window.h" +#include "rodeo/log.h" +// private +#include "window/irodeo_window.h" + +// -- external -- +#include "SDL.h" +#include "stc/cstr.h" + +static irodeo_window_state_t irodeo_window_state = {0}; + +void +rodeo_window_init( + uint16_t screen_height, + uint16_t screen_width, + cstr title +) +{ + irodeo_window_state.window = NULL; + irodeo_window_state.screen_surface = NULL; + irodeo_window_state.screen_height = screen_height; + irodeo_window_state.screen_width = screen_width; + + rodeo_log( + rodeo_logLevel_info, + "Initializing SDL..." + ); + + { + uint32_t init_flags_sdl = 0; + init_flags_sdl = init_flags_sdl | SDL_INIT_VIDEO; + init_flags_sdl = init_flags_sdl | SDL_INIT_AUDIO; + init_flags_sdl = init_flags_sdl | SDL_INIT_GAMECONTROLLER; + + if(SDL_Init(init_flags_sdl) < 0) + { + rodeo_log( + rodeo_logLevel_error, + "Failed to initialize SDL. SDL_Error: %s", + SDL_GetError() + ); + exit(EXIT_FAILURE); + } + rodeo_log( + rodeo_logLevel_info, + "Success initializing SDL" + ); + } + + rodeo_log( + rodeo_logLevel_info, + "Initializing SDL window..." + ); + irodeo_window_state.window = SDL_CreateWindow( + cstr_str(&title), + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + screen_width, + screen_height, + SDL_WINDOW_SHOWN //| SDL_WINDOW_RESIZABLE + ); + if(irodeo_window_state.window == NULL) + { + rodeo_log( + rodeo_logLevel_error, + "Failed creating SDL window. SDL_Error: %s", + SDL_GetError() + ); + exit(EXIT_FAILURE); + } + rodeo_log( + rodeo_logLevel_info, + "Success initializing SDL window" + ); + +#if !__EMSCRIPTEN__ + rodeo_log( + rodeo_logLevel_info, + "SDL setting up driver specific information..." + ); + SDL_VERSION(&irodeo_window_state.wmi.version); + if( + !SDL_GetWindowWMInfo( + irodeo_window_state.window, + &irodeo_window_state.wmi + ) + ) + { + rodeo_log( + rodeo_logLevel_error, + "SDL failed to get driver specific information. SDL Error: %s", SDL_GetError() + ); + exit(EXIT_FAILURE); + } + rodeo_log( + rodeo_logLevel_info, + "Success getting driver specific information" + ); +#endif + +} + +void +rodeo_window_deinit(void) +{ + SDL_DestroyWindow(irodeo_window_state.window); + //Mix_Quit(); + SDL_Quit(); +} + +uint16_t +rodeo_window_screen_width_get(void) +{ + return irodeo_window_state.screen_width; +} + +uint16_t +rodeo_window_screen_height_get(void) +{ + return irodeo_window_state.screen_height; +} + +void +irodeo_window_screen_width_setVar(uint16_t width) +{ + irodeo_window_state.screen_width = width; +} + +void +irodeo_window_screen_height_setVar(uint16_t height) +{ + irodeo_window_state.screen_height = height; +} + +bool +rodeo_window_shouldQuit(void) +{ + return irodeo_window_state.quit; +} + +void +rodeo_window_quit(void) +{ + irodeo_window_state.quit = true; +} + +SDL_Window * +irodeo_window_get(void) +{ + return irodeo_window_state.window; +} + +SDL_Surface * +irodeo_window_surface_get(void) +{ + return irodeo_window_state.screen_surface; +} + +SDL_SysWMinfo +irodeo_window_wmi_get(void) +{ + return irodeo_window_state.wmi; +} |
