#include #include /* TODO: REMOVE THIS INCLUSION */ #include #include #include #define ENGINE_RENDERING_WINDOW_H_EXCLUDE_EXTERNS #include #undef ENGINE_RENDERING_WINDOW_H_EXCLUDE_EXTERNS #undef GLFW_INCLUDE_NONE #include #include #include extern Instance* GLOBAL_PLATFORM; static inline u64 platform_get_time_usec(void) { struct timespec t; int res = clock_gettime(CLOCK_MONOTONIC, &t); if (res != 0) { // TODO: Check errno WARN("Failed to get system time"); } return (u64)(t.tv_sec * 1000000 + t.tv_nsec / 1000); } /* wrapper to get time in ms */ u64 (*get_time)(void) = platform_get_time_usec; #define DAW_WINDOW_VSYNC (1 << 0) #define DAW_WINDOW_FULLSCREEN (1 << 1) #define DAW_WINDOW_RESIZEABLE (1 << 2) // Wrapper to get a specific window and set up related structures. // What the fuck is this doing here. Window* Window_new(const struct Platform* p, const char *restrict title, Window_framework framework, Window_renderer renderer, ivec2 size, u32 flags) { Window* w = NULL; switch (framework) { case WINDOW_FRAMEWORK_GLFW: switch (renderer) { case WINDOW_RENDERER_OPENGL: /* For now, pass instance as NULL, fix it once all the necessary bs is * out of struct Instance */ w = p->window_init(GLOBAL_PLATFORM, title, size, flags); // Manually reset bindings et. al. w->bindings = NULL; w->bindings_sz = 0; w->bindings_len = 0; w->render_targets = NULL; return w; default: ERROR("Unsupported renderer."); } break; default: ERROR("Unsupported framework."); } return NULL; } void window_reset_cameras(Window *restrict w, void *restrict state, RenderTargets *restrict targets) { usize b_ofst = 0; for (usize i = 0; i < targets->framebuffer_len; i++) { ivec3 newsz; // Set last dimension to 0 to ensure 2d newsz[2] = 0; // Well aware that we copy a smaller sized vec into a larger one, thank you. glm_ivec2_copy(w->windowsize, newsz); const i8 num_textures = targets->framebuffer_parameters[i].num_textures; const i8 num_renderbuffers = targets->framebuffer_parameters[i].num_renderbuffers; // Change framebuffer & attached buffers dimensions, if framebuffer resize callback exists if (targets->framebuffer_size_callback[i] != NULL) { targets->framebuffer_size_callback[i](&newsz, w->windowsize); // as far as I can tell from the OpenGL docs, it should be safe to just // delete framebuffers and attached buffers u32 *buffer = &targets->buffer[b_ofst]; if (num_textures != 0) { r_destroy_textures(w->context, buffer, targets->framebuffer_parameters[i].num_textures); // Move buf ptr } if (num_renderbuffers != 0) { // renderbuffer(s) should be located after "textures", so their index // starts at num_textures. r_destroy_renderbuffers(w->context, &buffer[num_textures], targets->framebuffer_parameters[i].num_renderbuffers); } r_destroy_framebuffers(w->context, &targets->framebuffer[i], 1); // TODO: Re-Create framebuffers and related buffers with new sizes. glm_ivec3_copy(newsz, targets->framebuffer_parameters[i].dimensions); r_create_framebuffers(w->context, &targets->framebuffer[i], 1); r_setup_framebuffer(w->context, targets->framebuffer[i], targets->framebuffer_parameters[i], buffer, &targets->buffer_parameters[b_ofst]); } b_ofst += num_textures + num_renderbuffers; } // Reset the cameras in a separate loop, this ensures all potential // texture-names have been assigned, and can now be accessed through the // camera-reset callback, in case some layers depend on others. for (usize i = 0; i < targets->framebuffer_len; i++) { // Reset camera using callback (if any) if (targets->camera_reset_callback[i] != NULL) { targets->camera_reset_callback[i](w, targets->cam[i], state, targets->framebuffer_parameters[i].dimensions); } } } void get_mousepos(double *x, double *y) { Window* w = GLOBAL_PLATFORM->window; switch(w->framework) { case WINDOW_FRAMEWORK_GLFW: glfwGetCursorPos(GLOBAL_PLATFORM->window->window, x, y); break; default: ERROR("get_mouse_pos not implemented for chosen framework."); } } void window_get_size(ivec2* dst) { glm_ivec2_copy(GLOBAL_PLATFORM->window->windowsize, *dst); } // Assume framebuffer_len and texture_len is already set void window_init_renderstack(Window *restrict w, usize num_fbuf, usize num_buf, FramebufferParameters *restrict fb_params, u32 *restrict buffer_params ) { ASSERT(w != NULL); ASSERT(fb_params != NULL); ASSERT(buffer_params != NULL); RenderTargets *t = NULL; usize allocation_sz = sizeof(RenderTargets) + sizeof(*t->framebuffer) * num_fbuf + sizeof(*t->framebuffer_parameters) * num_fbuf + sizeof(*t->cam) * num_fbuf + sizeof(*t->framebuffer_size_callback) * num_fbuf + sizeof(*t->camera_reset_callback) * num_fbuf + sizeof(*t->buffer) * num_buf + sizeof(*t->buffer_parameters) * num_buf; void* allocation = malloc(allocation_sz); memset(allocation, 0, allocation_sz); #define ADVANCE_PTR(target, count)\ t->target = (void*)((u64)allocation + acc); \ acc += sizeof(*t->target) * count t = allocation; t->framebuffer_len = num_fbuf; t->buffer_len = num_buf; u64 acc = sizeof(RenderTargets); ADVANCE_PTR(framebuffer, num_fbuf); ADVANCE_PTR(framebuffer_parameters, num_fbuf); ADVANCE_PTR(cam, num_fbuf); ADVANCE_PTR(framebuffer_size_callback, num_fbuf); ADVANCE_PTR(camera_reset_callback, num_fbuf); ADVANCE_PTR(buffer, num_buf); ADVANCE_PTR(buffer_parameters, num_buf); // TODO: callbacks #undef ADVANCE_PTR memcpy(t->framebuffer_parameters, fb_params, sizeof(*t->framebuffer_parameters) * num_fbuf); memcpy(t->buffer_parameters, buffer_params, sizeof(*t->buffer_parameters) * num_buf); r_create_framebuffers(w->context, &t->framebuffer[0], num_fbuf); // Iteratively set up each framebuffer and framebuffer-attached objects usize buffer_offset = 0; for (usize fb_idx = 0; fb_idx < num_fbuf; fb_idx++) { r_setup_framebuffer(w->context, t->framebuffer[fb_idx], t->framebuffer_parameters[fb_idx], &t->buffer[buffer_offset], &t->buffer_parameters[buffer_offset]); buffer_offset += t->framebuffer_parameters[fb_idx].num_textures + t->framebuffer_parameters[fb_idx].num_renderbuffers; } w->render_targets = t; } void window_free_renderstack(RenderTargets *restrict t) { // Everything is in the same buffer anyways free(t->framebuffer); } void draw_model(Window *restrict w, u32 framebuffer_idx, RenderObject* o, vec4 pos) { r_draw_model(w->context, w->render_targets, framebuffer_idx, o, pos); }