#include "graphics.h" #include #include #include #include #include #include "cglm/vec4.h" #include "utils.h" #include "wlstate.h" #define WAYC_OPENGL_MAJOR 4 #define WAYC_OPENGL_MINOR 6 #define WAYC_COLOR_BITS 8 /* clang-format off */ static EGLint WAYC_EGL_ATTRS[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, WAYC_COLOR_BITS, EGL_GREEN_SIZE, WAYC_COLOR_BITS, EGL_BLUE_SIZE, WAYC_COLOR_BITS, EGL_ALPHA_SIZE, WAYC_COLOR_BITS, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE }; static EGLint WAYC_OGL_ATTRS[] = { EGL_CONTEXT_MAJOR_VERSION, WAYC_OPENGL_MAJOR, EGL_CONTEXT_MINOR_VERSION, WAYC_OPENGL_MINOR, EGL_NONE }; /* clang-format on */ static bool wayc_graphics_config(EGLDisplay display, EGLConfig* config) { wayc_notnull(display); wayc_notnull(config); EGLint nconfs = 0; if (!eglChooseConfig(display, WAYC_EGL_ATTRS, config, 1, &nconfs)) return false; return nconfs > 0; } static void wayc_sokol_log(const char* msg, uint32_t x, uint32_t y, const char* file, uint32_t line, const char* func, void* user) { wayc_notnull(msg); wayc_notnull(file); wayc_notnull(func); (void)user; fprintf(stderr, "[%s:%d:%s] %s (%d, %d)\n", file, line, func, msg, x, y); } enum graphics_error_e wayc_graphics_init(struct graphics_s* graphics, struct wlstate_s* state) { wayc_notnull(graphics); wayc_notnull(state); memset(graphics, 0, sizeof(*graphics)); EGLDisplay display = eglGetDisplay(state->display); if (display == EGL_NO_DISPLAY) return GRAPHICS_ERROR_ACQUIRE_DISPLAY; if (!eglInitialize(display, nullptr, nullptr)) { eglTerminate(display); return GRAPHICS_ERROR_ACQUIRE_DISPLAY; } if (!eglBindAPI(EGL_OPENGL_API)) { eglTerminate(display); return GRAPHICS_ERROR_USE_DESKTOP; } EGLConfig config; if (!wayc_graphics_config(display, &config)) { eglTerminate(display); return GRAPHICS_ERROR_SELECT_CONFIG; } EGLContext context = eglCreateContext(display, config, EGL_NO_CONTEXT, WAYC_OGL_ATTRS); if (context == EGL_NO_CONTEXT) { eglDestroyContext(display, context); eglTerminate(display); return GRAPHICS_ERROR_CREATE_CONTEXT; } graphics->display = display; graphics->config = config; graphics->context = context; return GRAPHICS_ERROR_NONE; } void wayc_graphics_deinit(struct graphics_s* graphics) { wayc_notnull(graphics); if (graphics->display == nullptr || graphics->context == nullptr) return; eglDestroyContext(graphics->display, graphics->context); eglTerminate(graphics->display); graphics->display = nullptr; graphics->context = nullptr; } enum renderer_error_e wayc_renderer_init(struct renderer_s* renderer, struct window_s* window, struct graphics_s* graphics, i32 width, i32 height, vec4 ccolor) { wayc_notnull(renderer); wayc_notnull(window); wayc_notnull(graphics); memset(renderer, 0, sizeof(*renderer)); wl_egl_window_t ewindow = wl_egl_window_create(window->surface, width, height); if (ewindow == nullptr) return RENDERER_ERROR_WINDOW_CREATION; EGLNativeWindowType nwindow = (EGLNativeWindowType)ewindow; EGLSurface esurface = eglCreateWindowSurface( graphics->display, graphics->config, nwindow, nullptr); if (esurface == EGL_NO_SURFACE) { wl_egl_window_destroy(ewindow); return RENDERER_ERROR_SURFACE_CREATION; } renderer->graphics = graphics; renderer->ewindow = ewindow; renderer->esurface = esurface; renderer->width = width; renderer->height = height; glm_vec4_copy(ccolor, renderer->ccolor); wayc_renderer_use(renderer); if (gladLoadGLLoader((GLADloadproc)eglGetProcAddress) == 0) { wayc_renderer_deinit(renderer); return RENDERER_ERROR_LOAD_FUNCTIONS; } sg_logger logger = {}; logger.func = wayc_sokol_log; sg_desc desc = {}; desc.logger = logger; sg_setup(&desc); return RENDERER_ERROR_NONE; } void wayc_renderer_begin(struct renderer_s* renderer) { wayc_notnull(renderer); sg_gl_swapchain gl_swap = {}; gl_swap.framebuffer = 0; sg_swapchain swap = {}; swap.gl = gl_swap; swap.width = renderer->width; swap.height = renderer->height; swap.sample_count = 1; sg_color_attachment_action color_action = {}; color_action.load_action = SG_LOADACTION_CLEAR; color_action.clear_value = { WAYC_X(renderer->ccolor), WAYC_Y(renderer->ccolor), WAYC_Z(renderer->ccolor), WAYC_A(renderer->ccolor)}; color_action.store_action = SG_STOREACTION_STORE; sg_pass_action action = {}; action.colors[0] = color_action; sg_pass pass = {}; pass.swapchain = swap; pass.action = action; sg_begin_pass(&pass); } void wayc_renderer_end(struct renderer_s* renderer) { wayc_notnull(renderer); struct graphics_s* graphics = renderer->graphics; sg_end_pass(); sg_commit(); eglSwapBuffers(graphics->display, renderer->esurface); } void wayc_renderer_deinit(struct renderer_s* renderer) { wayc_notnull(renderer); if (renderer->graphics == nullptr || renderer->esurface == nullptr || renderer->ewindow == nullptr) return; sg_shutdown(); eglDestroySurface(renderer->graphics->display, renderer->esurface); wl_egl_window_destroy(renderer->ewindow); renderer->graphics = nullptr; renderer->esurface = nullptr; renderer->ewindow = nullptr; }