From 026ead0b33d1655a10f83d24ed2cb387b7ebcc43 Mon Sep 17 00:00:00 2001 From: Roz K Date: Sat, 24 Dec 2022 11:27:53 +0100 Subject: [PATCH] Split display from render and rework init/terminate. --- Makefile | 4 +- __init__.py | 172 +++++++----- cpp/display.hpp | 34 +++ cpp/display/display_glx.cpp | 243 +++++++++++++++++ .../display_glx.hpp} | 23 +- cpp/display/display_x11.hpp | 27 ++ cpp/events.hpp | 20 +- cpp/events/events_x11.cpp | 216 ++++++++------- cpp/events/events_x11.hpp | 44 ++++ cpp/opengl/render_context_glx.cpp | 249 ------------------ cpp/render.hpp | 12 +- cpp/{opengl => render}/render_opengles.cpp | 67 +++-- cpp/{opengl => render}/render_opengles.hpp | 3 +- cpp/types.hpp | 1 + 14 files changed, 633 insertions(+), 482 deletions(-) create mode 100644 cpp/display.hpp create mode 100644 cpp/display/display_glx.cpp rename cpp/{opengl/render_context.hpp => display/display_glx.hpp} (77%) create mode 100644 cpp/display/display_x11.hpp create mode 100644 cpp/events/events_x11.hpp delete mode 100644 cpp/opengl/render_context_glx.cpp rename cpp/{opengl => render}/render_opengles.cpp (94%) rename cpp/{opengl => render}/render_opengles.hpp (97%) diff --git a/Makefile b/Makefile index d9323ba..43aae9f 100644 --- a/Makefile +++ b/Makefile @@ -14,9 +14,9 @@ # along with this program. If not, see . SOURCES = \ -cpp/opengl/render_context_glx.cpp \ -cpp/opengl/render_opengles.cpp \ +cpp/display/display_glx.cpp \ cpp/events/events_x11.cpp \ +cpp/render/render_opengles.cpp \ cpp/math.cpp OUTPUTFILE = engine.so diff --git a/__init__.py b/__init__.py index eac4b35..bf9bf10 100644 --- a/__init__.py +++ b/__init__.py @@ -19,6 +19,31 @@ from pathlib import Path _engine = ctypes.cdll.LoadLibrary(Path(__file__).parent / "engine.so") +# types.hpp + +def _flag(x): + return 1 << x + +def buffer(type, size): + return (type * size)() + +def _voidp(x): + return x.buffer_info()[0] + +def _ubytep(x): + assert x.typecode == 'B' + return x.buffer_info()[0] + +def _ushortp(x): + assert x.typecode == 'H' + return x.buffer_info()[0] + +def _floatp(x): + assert x.typecode == 'f' + return x.buffer_info()[0] + +# math.hpp + class vec3(ctypes.Structure): _fields_ = ('x', ctypes.c_float), ('y', ctypes.c_float), ('z', ctypes.c_float) @@ -42,71 +67,14 @@ class mat3(ctypes.Structure): class mat4(ctypes.Structure): _fields_ = ('x', vec4), ('y', vec4), ('z', vec4), ('w', vec4) -vec3_right = vec3(1.0, 0.0, 0.0) -vec3_forward = vec3(0.0, 1.0, 0.0) -vec3_up = vec3(0.0, 0.0, 1.0) - -def _flag(x): - return 1 << x - -TEXTURE_FORMAT_SRGB8_A8 = 0 -TEXTURE_FORMAT_RGBA8 = 1 -TEXTURE_FORMAT_RGB10_A2 = 2 -TEXTURE_FORMAT_32F = 3 - -TEXTURE_FORMAT_TYPECODE = ('B', 'B', 'I', 'f') -TEXTURE_FORMAT_NELEMS = (4, 4, 1, 1) - -TEXTURE_FLAG_3D = _flag(0) -TEXTURE_FLAG_MIPMAPS = _flag(1) -TEXTURE_FLAG_MIN_NEAREST = 0 -TEXTURE_FLAG_MIN_LINEAR = _flag(2) -TEXTURE_FLAG_MAG_NEAREST = 0 -TEXTURE_FLAG_MAG_LINEAR = _flag(3) - -VERTEX_FORMAT_VEC3_FLOAT = 1 -VERTEX_FORMAT_VEC3_INT10 = 2 -VERTEX_FORMAT_VEC3_UINT10 = 3 -VERTEX_FORMAT_NORMALIZE = _flag(7) - -def vertex_format(*format): - return array('B', format).tobytes() - -PARAM_FORMAT_VEC3_FLOAT = 1 -PARAM_FORMAT_VEC3_SHORT = 2 -PARAM_FORMAT_VEC3_INT10 = 3 -PARAM_FORMAT_NORMALIZE = _flag(7) - -def params_format(*format): - return array('B', format).tobytes() - -INSTANCE_FLAG_SPAWNED = _flag(0) -INSTANCE_FLAG_VISIBLE = _flag(1) - -BATCH_MAX_SIZE = 65536 - -def buffer(type, size): - return (type * size)() - _vec3p = ctypes.POINTER(vec3) _vec4p = ctypes.POINTER(vec4) _mat3p = ctypes.POINTER(mat3) _mat4p = ctypes.POINTER(mat4) -def _voidp(x): - return x.buffer_info()[0] - -def _ubytep(x): - assert x.typecode == 'B' - return x.buffer_info()[0] - -def _ushortp(x): - assert x.typecode == 'H' - return x.buffer_info()[0] - -def _floatp(x): - assert x.typecode == 'f' - return x.buffer_info()[0] +vec3_right = vec3(1.0, 0.0, 0.0) +vec3_forward = vec3(0.0, 1.0, 0.0) +vec3_up = vec3(0.0, 0.0, 1.0) vec3_rotate = _engine.rk_vec3_rotate vec3_rotate.argtypes = ( @@ -173,13 +141,64 @@ mat4_mul_mat4.argtypes = ( _mat4p, # a _mat4p) # b -initialize = _engine.rk_initialize -initialize.restype = ctypes.c_void_p -initialize.argtypes = ( +# display.hpp + +create_display = _engine.rk_create_display +create_display.restype = ctypes.c_void_p +create_display.argtypes = ( ctypes.c_char_p, # name ctypes.c_uint, # width ctypes.c_uint) # height +destroy_display = _engine.rk_destroy_display +destroy_display.argtypes = ( + ctypes.c_void_p,) # display + +swap_buffers = _engine.rk_swap_buffers +swap_buffers.argtypes = ( + ctypes.c_void_p,) # display + +# render.hpp + +TEXTURE_FORMAT_SRGB8_A8 = 0 +TEXTURE_FORMAT_RGBA8 = 1 +TEXTURE_FORMAT_RGB10_A2 = 2 +TEXTURE_FORMAT_32F = 3 + +TEXTURE_FORMAT_TYPECODE = ('B', 'B', 'I', 'f') +TEXTURE_FORMAT_NELEMS = (4, 4, 1, 1) + +TEXTURE_FLAG_3D = _flag(0) +TEXTURE_FLAG_MIPMAPS = _flag(1) +TEXTURE_FLAG_MIN_NEAREST = 0 +TEXTURE_FLAG_MIN_LINEAR = _flag(2) +TEXTURE_FLAG_MAG_NEAREST = 0 +TEXTURE_FLAG_MAG_LINEAR = _flag(3) + +VERTEX_FORMAT_VEC3_FLOAT = 1 +VERTEX_FORMAT_VEC3_INT10 = 2 +VERTEX_FORMAT_VEC3_UINT10 = 3 +VERTEX_FORMAT_NORMALIZE = _flag(7) + +def vertex_format(*format): + return array('B', format).tobytes() + +PARAM_FORMAT_VEC3_FLOAT = 1 +PARAM_FORMAT_VEC3_SHORT = 2 +PARAM_FORMAT_VEC3_INT10 = 3 +PARAM_FORMAT_NORMALIZE = _flag(7) + +def params_format(*format): + return array('B', format).tobytes() + +INSTANCE_FLAG_SPAWNED = _flag(0) +INSTANCE_FLAG_VISIBLE = _flag(1) + +BATCH_MAX_SIZE = 65536 + +render_initialize = _engine.rk_render_initialize +render_terminate = _engine.rk_render_terminate + _load_shader = _engine.rk_load_shader _load_shader.restype = ctypes.c_void_p _load_shader.argtypes = ( @@ -343,7 +362,7 @@ destroy_shader = _engine.rk_destroy_shader destroy_shader.argtypes = ( ctypes.c_void_p,) # shader -terminate = _engine.rk_terminate +# events.hpp EVENT_FOCUS_IN = 0 EVENT_FOCUS_OUT = 1 @@ -382,12 +401,24 @@ class _Events(ctypes.Union): class Event(ctypes.Structure): _fields_ = ('type', ctypes.c_uint), ('data', _Events) -set_autorepeat = _engine.rk_set_autorepeat -set_autorepeat.argtypes = ( - ctypes.c_bool,) # autorepeat +create_events = _engine.rk_create_events +create_events.restype = ctypes.c_void_p +create_events.argtypes = ( + ctypes.c_void_p,) # display -set_acceleration = _engine.rk_set_acceleration -set_acceleration.argtypes = ( +destroy_events = _engine.rk_destroy_events +destroy_events.argtypes = ( + ctypes.c_void_p, # display + ctypes.c_void_p) # events + +set_key_autorepeat = _engine.rk_set_key_autorepeat +set_key_autorepeat.argtypes = ( + ctypes.c_void_p, # events + ctypes.c_bool) # autorepeat + +set_motion_acceleration = _engine.rk_set_motion_acceleration +set_motion_acceleration.argtypes = ( + ctypes.c_void_p, # events ctypes.c_uint, # numerator ctypes.c_uint, # denominator ctypes.c_uint) # threshold @@ -395,5 +426,6 @@ set_acceleration.argtypes = ( consume_events = _engine.rk_consume_events consume_events.restype = ctypes.c_uint consume_events.argtypes = ( - ctypes.POINTER(Event), # events + ctypes.c_void_p, # events + ctypes.POINTER(Event), # buffer ctypes.c_uint) # max_events diff --git a/cpp/display.hpp b/cpp/display.hpp new file mode 100644 index 0000000..a5e493f --- /dev/null +++ b/cpp/display.hpp @@ -0,0 +1,34 @@ +// Copyright (C) 2022 RozK +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef _RK_ENGINE_DISPLAY_H +#define _RK_ENGINE_DISPLAY_H + +#include "types.hpp" + +typedef rk_handle_t rk_display_t; + +RK_EXPORT rk_display_t rk_create_display( + rk_char const * name, + rk_uint width, + rk_uint height); + +RK_EXPORT void rk_destroy_display( + rk_display_t display); + +RK_EXPORT void rk_swap_buffers( + rk_display_t display); + +#endif // _RK_ENGINE_DISPLAY_H diff --git a/cpp/display/display_glx.cpp b/cpp/display/display_glx.cpp new file mode 100644 index 0000000..05e2563 --- /dev/null +++ b/cpp/display/display_glx.cpp @@ -0,0 +1,243 @@ +// Copyright (C) 2022 RozK +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Adapted from https://www.khronos.org/opengl/wiki/Tutorial:_OpenGL_3.0_Context_Creation_(GLX) + +#include "../display.hpp" +#include "display_glx.hpp" +#include +#include + +static bool rk_error_occured = false; + +#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 +typedef GLXContext (*rk_CreateContextAttribsFunc)(Display *, GLXFBConfig, GLXContext, Bool, int const *); + +rk_DrawElementsInstancedBaseInstanceFunc rk_DrawElementsInstancedBaseInstance = nullptr; +rk_MultiDrawElementsIndirectFunc rk_MultiDrawElementsIndirect = nullptr; + +static int const rk_visual_attribs[] = { + GLX_X_RENDERABLE, True, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_DEPTH_SIZE, 24, + GLX_STENCIL_SIZE, 8, + GLX_DOUBLEBUFFER, True, + None +}; + +static int const rk_context_attribs[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 2, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES_PROFILE_BIT_EXT, + None +}; + +static void rk_glx_printf( + char const * messsage) { + printf("[GLX] %s\n", messsage); +} + +static bool rk_extension_supported( + char const * extlist, + char const * extension) { + char const * where = strchr(extension, ' '); + if (where || *extension == '\0') { + return false; + } + for (char const * start = extlist;;) { + where = strstr(start, extension); + if (!where) { + break; + } + char const * const terminator = where + strlen(extension); + if ((where == start || *(where - 1) == ' ') && (*terminator == ' ' || *terminator == '\0')) { + return true; + } + start = terminator; + } + return false; +} + +static int rk_error_handler( + Display * display, + XErrorEvent * event) { + rk_error_occured = true; + return 0; +} + +rk_display_t rk_create_display( + rk_char const * name, + rk_uint width, + rk_uint height) { + if (!name || !width || !height) { + return nullptr; + }; + rk_display_glx * const display = new rk_display_glx; + display->display = XOpenDisplay(nullptr); + display->window = 0; + display->colormap = 0; + display->context = nullptr; + if (!display->display) { + rk_glx_printf("Failed to open X display."); + rk_destroy_display(reinterpret_cast(display)); + return nullptr; + } + + int glx_major, glx_minor; + if (!glXQueryVersion(display->display, &glx_major, &glx_minor) || + (glx_major == 1 && glx_minor < 3) || glx_major < 1) { + rk_glx_printf("Invalid GLX version."); + rk_destroy_display(reinterpret_cast(display)); + return nullptr; + } + char const * const glx_exts = glXQueryExtensionsString(display->display, DefaultScreen(display->display)); + + int fbcount; + GLXFBConfig * const fbc = glXChooseFBConfig( + display->display, DefaultScreen(display->display), rk_visual_attribs, &fbcount); + if (!fbc) { + rk_glx_printf("Failed to retrieve framebuffer configs."); + rk_destroy_display(reinterpret_cast(display)); + return nullptr; + } + printf("[GLX] Found %d framebuffer configs.\n", fbcount); + + int best_fbc = -1; + int best_num_samp = -1; + for (int i = 0; i < fbcount; ++i) { + XVisualInfo * const vi = glXGetVisualFromFBConfig(display->display, fbc[i]); + if (vi) { + int samp_buf, samples; + glXGetFBConfigAttrib(display->display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf); + glXGetFBConfigAttrib(display->display, fbc[i], GLX_SAMPLES, &samples); + if (best_fbc < 0 || (samp_buf && samples > best_num_samp)) { + best_fbc = i; + best_num_samp = samples; + } + XFree(vi); + } + } + if (best_fbc == -1) { + XFree(fbc); + rk_glx_printf("Failed to find a suitable framebuffer config."); + rk_destroy_display(reinterpret_cast(display)); + return nullptr; + } + GLXFBConfig const bestFbc = fbc[best_fbc]; + XFree(fbc); + printf("[GLX] Select framebuffer config with %d samples.\n", best_num_samp); + + XVisualInfo * const vi = glXGetVisualFromFBConfig(display->display, bestFbc); + display->colormap = XCreateColormap( + display->display, RootWindow(display->display, vi->screen), vi->visual, AllocNone); + XSetWindowAttributes swa; + swa.colormap = display->colormap; +// swa.background_pixmap = None; +// swa.border_pixel = 0; + swa.event_mask = RK_EVENTS_MASK; + display->window = XCreateWindow(display->display, RootWindow(display->display, vi->screen), + 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual, + /*CWBorderPixel |*/ CWColormap | CWEventMask, &swa); + XFree(vi); + if (!display->window) { + rk_glx_printf("Failed to create window."); + rk_destroy_display(reinterpret_cast(display)); + return nullptr; + } + XStoreName(display->display, display->window, name); + XMapWindow(display->display, display->window); + + rk_CreateContextAttribsFunc const glXCreateContextAttribs = + reinterpret_cast( + glXGetProcAddressARB(reinterpret_cast("glXCreateContextAttribsARB"))); + + if (!rk_extension_supported(glx_exts, "GLX_ARB_create_context") || !glXCreateContextAttribs) { + rk_glx_printf("glXCreateContextAttribsARB extension not found."); + rk_destroy_display(reinterpret_cast(display)); + return nullptr; + } else { + rk_error_occured = false; + int (*oldHandler)(Display *, XErrorEvent *) = XSetErrorHandler(&rk_error_handler); + display->context = glXCreateContextAttribs(display->display, bestFbc, 0, True, rk_context_attribs); + XSync(display->display, False); + XSetErrorHandler(oldHandler); + if (rk_error_occured || !display->context) { + rk_glx_printf("Failed to create context."); + rk_destroy_display(reinterpret_cast(display)); + return nullptr; + } + } + + if (!glXIsDirect(display->display, display->context)) { + rk_glx_printf("Warning: Rendering context is indirect."); + } + glXMakeCurrent(display->display, display->window, display->context); + + char const * const gl_exts = reinterpret_cast(glGetString(GL_EXTENSIONS)); + if (rk_extension_supported(gl_exts, "GL_EXT_base_instance")) { + rk_DrawElementsInstancedBaseInstance = + reinterpret_cast( + glXGetProcAddressARB(reinterpret_cast("DrawElementsInstancedBaseInstance"))); + if (rk_DrawElementsInstancedBaseInstance) { + rk_glx_printf("Using extension GL_EXT_base_instance::DrawElementsInstancedBaseInstance."); + if (rk_extension_supported(gl_exts, "GL_EXT_multi_draw_indirect")) { + rk_MultiDrawElementsIndirect = + reinterpret_cast( + glXGetProcAddressARB(reinterpret_cast("MultiDrawElementsIndirectEXT"))); + if (rk_MultiDrawElementsIndirect) { + rk_glx_printf("Using extension GL_EXT_multi_draw_indirect::MultiDrawElementsIndirectEXT."); + } + } + } + } + + return reinterpret_cast(display); +} + +void rk_destroy_display( + rk_display_t _display) { + rk_display_glx * const display = reinterpret_cast(_display); + if (display) { + if (display->display) { + glXMakeCurrent(display->display, 0, nullptr); + if (display->context) { + glXDestroyContext(display->display, display->context); + } + if (display->window) { + XDestroyWindow(display->display, display->window); + } + if (display->colormap) { + XFreeColormap(display->display, display->colormap); + } + XCloseDisplay(display->display); + } + delete display; + } +} + +void rk_swap_buffers( + rk_display_t _display) { + rk_display_glx const * const display = reinterpret_cast(_display); + if (display && display->display && display->window) { + glXSwapBuffers(display->display, display->window); + } +} diff --git a/cpp/opengl/render_context.hpp b/cpp/display/display_glx.hpp similarity index 77% rename from cpp/opengl/render_context.hpp rename to cpp/display/display_glx.hpp index 43409c4..33bcbc4 100644 --- a/cpp/opengl/render_context.hpp +++ b/cpp/display/display_glx.hpp @@ -13,10 +13,17 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -#ifndef _RK_ENGINE_RENDER_CONTEXT_H -#define _RK_ENGINE_RENDER_CONTEXT_H +#ifndef _RK_ENGINE_DISPLAY_GLX_H +#define _RK_ENGINE_DISPLAY_GLX_H -#include "../render.hpp" +#include "../types.hpp" +#include "display_x11.hpp" +#include "../events/events_x11.hpp" +#include + +struct rk_display_glx : public rk_display_x11 { + GLXContext context; +}; typedef void (*rk_DrawElementsInstancedBaseInstanceFunc)(rk_uint, rk_uint, rk_uint, const void *, rk_uint, rk_uint); typedef void (*rk_MultiDrawElementsIndirectFunc)(rk_uint, rk_uint, const void *, rk_uint, rk_uint); @@ -24,12 +31,4 @@ typedef void (*rk_MultiDrawElementsIndirectFunc)(rk_uint, rk_uint, const void *, extern rk_DrawElementsInstancedBaseInstanceFunc rk_DrawElementsInstancedBaseInstance; extern rk_MultiDrawElementsIndirectFunc rk_MultiDrawElementsIndirect; -extern rk_window_t rk_create_context( - char const * name, - unsigned width, - unsigned height); - -extern void rk_swap_buffers(); -extern void rk_destroy_context(); - -#endif // _RK_ENGINE_RENDER_CONTEXT_H +#endif // _RK_ENGINE_DISPLAY_GLX_H diff --git a/cpp/display/display_x11.hpp b/cpp/display/display_x11.hpp new file mode 100644 index 0000000..c01cfa5 --- /dev/null +++ b/cpp/display/display_x11.hpp @@ -0,0 +1,27 @@ +// Copyright (C) 2022 RozK +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef _RK_ENGINE_DISPLAY_X11_H +#define _RK_ENGINE_DISPLAY_X11_H + +#include + +struct rk_display_x11 { + Display * display; + Window window; + Colormap colormap; +}; + +#endif // _RK_ENGINE_DISPLAY_X11_H diff --git a/cpp/events.hpp b/cpp/events.hpp index c6e7507..c00e8a6 100644 --- a/cpp/events.hpp +++ b/cpp/events.hpp @@ -17,6 +17,9 @@ #define _RK_ENGINE_EVENTS_H #include "types.hpp" +#include "display.hpp" + +typedef rk_handle_t rk_events_t; enum rk_event_type : rk_uint { RK_EVENT_FOCUS_IN = 0, @@ -52,19 +55,26 @@ struct rk_event { }; }; -extern bool rk_initialize_events(); -extern void rk_terminate_events(); +RK_EXPORT rk_events_t rk_create_events( + rk_display_t display); -RK_EXPORT void rk_set_autorepeat( +RK_EXPORT void rk_destroy_events( + rk_display_t display, + rk_events_t events); + +RK_EXPORT void rk_set_key_autorepeat( + rk_events_t events, rk_bool autorepeat); -RK_EXPORT void rk_set_acceleration( +RK_EXPORT void rk_set_motion_acceleration( + rk_events_t events, rk_uint numerator, rk_uint denominator, rk_uint threshold); RK_EXPORT rk_uint rk_consume_events( - rk_event * events, + rk_events_t events, + rk_event * buffer, rk_uint max_events); #endif // _RK_ENGINE_EVENTS_H diff --git a/cpp/events/events_x11.cpp b/cpp/events/events_x11.cpp index e427769..e357a41 100644 --- a/cpp/events/events_x11.cpp +++ b/cpp/events/events_x11.cpp @@ -14,144 +14,168 @@ // along with this program. If not, see . #include "../events.hpp" -#include +#include "events_x11.hpp" +#include "../display/display_x11.hpp" +#include -extern Display * rk_display; -extern Window rk_window; - -unsigned rk_events_mask = FocusChangeMask | - KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask; - -static XIM rk_input_manager = nullptr; -static XIC rk_input_context = nullptr; - -static bool rk_focused = false; -static bool rk_keyboard_autorepeat = false; -static XKeyboardState rk_previous_keyboard_state; -static int rk_previous_accel_numerator, rk_accel_numerator = 1; -static int rk_previous_accel_denominator, rk_accel_denominator = 1; -static int rk_previous_threshold, rk_accel_threshold = 0; - -static void rk_backup_setup() { - XGetKeyboardControl(rk_display, &rk_previous_keyboard_state); - XGetPointerControl(rk_display, - &rk_previous_accel_numerator, &rk_previous_accel_denominator, &rk_previous_threshold); +static void rk_x11_printf( + char const * messsage) { + printf("[X11] %s\n", messsage); } -static void rk_restore_setup() { - if (AutoRepeatModeOn == rk_previous_keyboard_state.global_auto_repeat) { - XAutoRepeatOn(rk_display); +static void rk_backup(rk_events_x11 & events) { + XKeyboardState backup; + XGetKeyboardControl(events.display, &backup); + events.backup_autorepeat = (AutoRepeatModeOn == backup.global_auto_repeat); + XGetPointerControl( + events.display, &events.backup_numerator, &events.backup_denominator, &events.backup_threshold); +} + +static void rk_restore(rk_events_x11 & events) { + if (events.backup_autorepeat) { + XAutoRepeatOn(events.display); } else { - XAutoRepeatOff(rk_display); + XAutoRepeatOff(events.display); } - XChangePointerControl(rk_display, True, True, - rk_previous_accel_numerator, rk_previous_accel_denominator, rk_previous_threshold); + XChangePointerControl( + events.display, True, True, events.backup_numerator, events.backup_denominator, events.backup_threshold); } -static void rk_apply_setup() { - if (rk_keyboard_autorepeat) { - XAutoRepeatOn(rk_display); +static void rk_apply(rk_events_x11 & events) { + if (events.key_autorepeat) { + XAutoRepeatOn(events.display); } else { - XAutoRepeatOff(rk_display); + XAutoRepeatOff(events.display); } - XChangePointerControl(rk_display, True, True, rk_accel_numerator, rk_accel_denominator, rk_accel_threshold); + XChangePointerControl( + events.display, True, True, events.motion_numerator, events.motion_denominator, events.motion_threshold); } -bool rk_initialize_events() { - rk_focused = false; - rk_backup_setup(); - rk_keyboard_autorepeat = (AutoRepeatModeOn == rk_previous_keyboard_state.global_auto_repeat); - rk_accel_numerator = rk_previous_accel_numerator; - rk_accel_denominator = rk_previous_accel_denominator; - rk_accel_threshold = rk_previous_threshold; - rk_input_manager = XOpenIM(rk_display, nullptr, nullptr, nullptr); - if (!rk_input_manager) { - return false; - } - rk_input_context = XCreateIC(rk_input_manager, - XNInputStyle, XIMPreeditNone | XIMStatusNone, - XNClientWindow, rk_window, - NULL); - if (!rk_input_context) { - return false; - } - XSetICFocus(rk_input_context); - return true; -} - -void rk_terminate_events() { - rk_restore_setup(); - if (rk_input_context) { - XUnsetICFocus(rk_input_context); - XDestroyIC(rk_input_context); - rk_input_context = nullptr; - } - if (rk_input_manager) { - XCloseIM(rk_input_manager); - rk_input_manager = nullptr; - } -} - -static void rk_focus_in() { - if (!rk_focused) { - rk_backup_setup(); - rk_apply_setup(); - XGrabPointer(rk_display, rk_window, True, +static void rk_focus_in(rk_events_x11 & events) { + if (!events.focused) { + rk_backup(events); + rk_apply(events); + XGrabPointer(events.display, events.window, True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, - GrabModeAsync, GrabModeAsync, rk_window, None, CurrentTime); - rk_focused = true; + GrabModeAsync, GrabModeAsync, events.window, None, CurrentTime); + events.focused = true; } } -static void rk_focus_out() { - if (rk_focused) { - XUngrabPointer(rk_display, CurrentTime); - rk_restore_setup(); - rk_focused = false; +static void rk_focus_out(rk_events_x11 & events) { + if (events.focused) { + XUngrabPointer(events.display, CurrentTime); + rk_restore(events); + events.focused = false; } } -void rk_set_autorepeat( +rk_events_t rk_create_events( + rk_display_t _display) { + rk_display_x11 const * const display = reinterpret_cast(_display); + if (!display || !display->display || !display->window) { + return nullptr; + } + rk_events_x11 * const events = new rk_events_x11; + events->display = display->display; + events->window = display->window; + events->input_manager = XOpenIM(display->display, nullptr, nullptr, nullptr); + if (!events->input_manager) { + rk_x11_printf("Failed to open input manager."); + delete events; + return nullptr; + } + events->input_context = XCreateIC(events->input_manager, + XNInputStyle, XIMPreeditNone | XIMStatusNone, + XNClientWindow, display->window, + NULL); + if (!events->input_context) { + rk_x11_printf("Failed to create input context."); + XCloseIM(events->input_manager); + delete events; + return nullptr; + } + events->focused = false; + rk_backup(*events); + events->key_autorepeat = events->backup_autorepeat; + events->motion_numerator = events->backup_numerator; + events->motion_denominator = events->backup_denominator; + events->motion_threshold = events->backup_threshold; + XSetICFocus(events->input_context); + return reinterpret_cast(events); +} + +void rk_destroy_events( + rk_display_t _display, + rk_events_t _events) { + rk_display_x11 const * const display = reinterpret_cast(_display); + rk_events_x11 * const events = reinterpret_cast(_events); + if (display && events && display->display && display->display == events->display) { + rk_restore(*events); + if (events->input_context) { + XUnsetICFocus(events->input_context); + XDestroyIC(events->input_context); + } + if (events->input_manager) { + XCloseIM(events->input_manager); + } + } + if (events) { + delete events; + } +} + +void rk_set_key_autorepeat( + rk_events_t _events, rk_bool autorepeat) { - rk_keyboard_autorepeat = autorepeat; - if (rk_focused) { - rk_apply_setup(); + rk_events_x11 * const events = reinterpret_cast(_events); + if (events) { + events->key_autorepeat = autorepeat; + if (events->focused) { + rk_apply(*events); + } } } -void rk_set_acceleration( +void rk_set_motion_acceleration( + rk_events_t _events, rk_uint numerator, rk_uint denominator, rk_uint threshold) { - rk_accel_numerator = numerator; - rk_accel_denominator = denominator; - rk_accel_threshold = threshold; - if (rk_focused) { - rk_apply_setup(); + rk_events_x11 * const events = reinterpret_cast(_events); + if (events) { + events->motion_numerator = numerator; + events->motion_denominator = denominator; + events->motion_threshold = threshold; + if (events->focused) { + rk_apply(*events); + } } } rk_uint rk_consume_events( - rk_event * events, + rk_events_t _events, + rk_event * buffer, rk_uint max_events) { static wchar_t string[256]; - if (!events || !max_events) { + rk_events_x11 * const events = reinterpret_cast(_events); + if (!events || !buffer || !max_events) { return 0; } XEvent x11_event; KeySym keysym; Status status; unsigned nevents = 0; - while (nevents < max_events && XCheckWindowEvent(rk_display, rk_window, rk_events_mask, &x11_event)) { + while (nevents < max_events && XCheckWindowEvent(events->display, events->window, RK_EVENTS_MASK, &x11_event)) { if (XFilterEvent(&x11_event, 0)) { continue; } - rk_event & event = events[nevents]; + rk_event & event = buffer[nevents]; switch (x11_event.type) { case FocusIn: if (NotifyNormal == x11_event.xfocus.mode) { - rk_focus_in(); + rk_focus_in(*events); event.type = RK_EVENT_FOCUS_IN; ++nevents; } @@ -159,7 +183,7 @@ rk_uint rk_consume_events( case FocusOut: if (NotifyNormal == x11_event.xfocus.mode) { - rk_focus_out(); + rk_focus_out(*events); event.type = RK_EVENT_FOCUS_OUT; ++nevents; } @@ -168,7 +192,7 @@ rk_uint rk_consume_events( case KeyPress: event.type = RK_EVENT_KEY_PRESS; event.key.code = x11_event.xkey.keycode; - XwcLookupString(rk_input_context, &x11_event.xkey, string, 256, &keysym, &status); + XwcLookupString(events->input_context, &x11_event.xkey, string, 256, &keysym, &status); switch (status) { case XLookupChars: event.key.symbol = XLookupKeysym(&x11_event.xkey, 0); diff --git a/cpp/events/events_x11.hpp b/cpp/events/events_x11.hpp new file mode 100644 index 0000000..423165e --- /dev/null +++ b/cpp/events/events_x11.hpp @@ -0,0 +1,44 @@ +// Copyright (C) 2022 RozK +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef _RK_ENGINE_EVENTS_X11_H +#define _RK_ENGINE_EVENTS_X11_H + +#include + +enum : unsigned { + RK_EVENTS_MASK = FocusChangeMask | + KeyPressMask | KeyReleaseMask | + ButtonPressMask | ButtonReleaseMask | + PointerMotionMask +}; + +struct rk_events_x11 { + Display * display; + Window window; + XIM input_manager; + XIC input_context; + bool focused; + bool key_autorepeat; + bool backup_autorepeat; + int motion_numerator; + int backup_numerator; + int motion_denominator; + int backup_denominator; + int motion_threshold; + int backup_threshold; +}; + +#endif // _RK_ENGINE_EVENTS_X11_H diff --git a/cpp/opengl/render_context_glx.cpp b/cpp/opengl/render_context_glx.cpp deleted file mode 100644 index 99d54bd..0000000 --- a/cpp/opengl/render_context_glx.cpp +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright (C) 2022 RozK -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Adapted from https://www.khronos.org/opengl/wiki/Tutorial:_OpenGL_3.0_Context_Creation_(GLX) - -#include "render_context.hpp" -#include "../events.hpp" -#include -#include -#include -#include -#include - -extern unsigned rk_events_mask; - -Display * rk_display = nullptr; -Window rk_window = 0; - -static Colormap rk_colormap = 0; -static GLXContext rk_context = nullptr; -static bool rk_error_occured = false; - -#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 -typedef GLXContext (*glXCreateContextAttribsARBProc)(Display *, GLXFBConfig, GLXContext, Bool, int const *); - -rk_DrawElementsInstancedBaseInstanceFunc rk_DrawElementsInstancedBaseInstance = nullptr; -rk_MultiDrawElementsIndirectFunc rk_MultiDrawElementsIndirect = nullptr; - -static int const rk_visual_attribs[] = { - GLX_X_RENDERABLE, True, - GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_DEPTH_SIZE, 24, - GLX_STENCIL_SIZE, 8, - GLX_DOUBLEBUFFER, True, - None -}; - -static int const rk_context_attribs[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, 3, - GLX_CONTEXT_MINOR_VERSION_ARB, 2, - GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES_PROFILE_BIT_EXT, - None -}; - -static void rk_printf( - char const * messsage) { - printf("[GLX] %s\n", messsage); -} - -static bool rk_extension_supported( - char const * extlist, - char const * extension) { - char const * where = strchr(extension, ' '); - if (where || *extension == '\0') { - return false; - } - for (char const * start = extlist;;) { - where = strstr(start, extension); - if (!where) { - break; - } - char const * const terminator = where + strlen(extension); - if ((where == start || *(where - 1) == ' ') && (*terminator == ' ' || *terminator == '\0')) { - return true; - } - start = terminator; - } - return false; -} - -static int rk_error_handler( - Display * display, - XErrorEvent * event) { - rk_error_occured = true; - return 0; -} - -rk_window_t rk_create_context( - char const * name, - unsigned width, - unsigned height) { - XSetLocaleModifiers(""); - - rk_display = XOpenDisplay(nullptr); - if (!rk_display) { - rk_printf("Failed to open X display."); - return nullptr; - } - - int glx_major, glx_minor; - if (!glXQueryVersion(rk_display, &glx_major, &glx_minor) || (glx_major == 1 && glx_minor < 3) || glx_major < 1) { - rk_printf("Invalid GLX version."); - rk_destroy_context(); - return nullptr; - } - - int fbcount; - GLXFBConfig * const fbc = glXChooseFBConfig(rk_display, DefaultScreen(rk_display), rk_visual_attribs, &fbcount); - if (!fbc) { - rk_printf("Failed to retrieve framebuffer configs."); - rk_destroy_context(); - return nullptr; - } - printf("[GLX] Found %d framebuffer configs.\n", fbcount); - - int best_fbc = -1; - int best_num_samp = -1; - for (int i = 0; i < fbcount; ++i) { - XVisualInfo * vi = glXGetVisualFromFBConfig(rk_display, fbc[i]); - if (vi) { - int samp_buf, samples; - glXGetFBConfigAttrib(rk_display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf); - glXGetFBConfigAttrib(rk_display, fbc[i], GLX_SAMPLES, &samples); - if (best_fbc < 0 || (samp_buf && samples > best_num_samp)) { - best_fbc = i; - best_num_samp = samples; - } - XFree(vi); - } - } - if (best_fbc == -1) { - XFree(fbc); - rk_printf("Failed to find a suitable framebuffer config."); - rk_destroy_context(); - return nullptr; - } - GLXFBConfig const bestFbc = fbc[best_fbc]; - XFree(fbc); - printf("[GLX] Select framebuffer config with %d samples.\n", best_num_samp); - - XVisualInfo * const vi = glXGetVisualFromFBConfig(rk_display, bestFbc); - rk_colormap = XCreateColormap(rk_display, RootWindow(rk_display, vi->screen), vi->visual, AllocNone); - XSetWindowAttributes swa; - swa.colormap = rk_colormap; - swa.background_pixmap = None; - swa.border_pixel = 0; - swa.event_mask = rk_events_mask; - rk_window = XCreateWindow(rk_display, RootWindow(rk_display, vi->screen), - 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual, - CWBorderPixel | CWColormap | CWEventMask, &swa); - XFree(vi); - if (!rk_window) { - rk_printf("Failed to create window."); - rk_destroy_context(); - return nullptr; - } - XStoreName(rk_display, rk_window, name); - - if (!rk_initialize_events()) { - rk_printf("Failed to initialize events."); - rk_destroy_context(); - return nullptr; - } - - XMapWindow(rk_display, rk_window); - - char const * const glx_exts = glXQueryExtensionsString(rk_display, DefaultScreen(rk_display)); - glXCreateContextAttribsARBProc const glXCreateContextAttribsARB = - reinterpret_cast( - glXGetProcAddressARB(reinterpret_cast("glXCreateContextAttribsARB"))); - - rk_error_occured = false; - int (*oldHandler)(Display *, XErrorEvent *) = XSetErrorHandler(&rk_error_handler); - if (!rk_extension_supported(glx_exts, "GLX_ARB_create_context") || !glXCreateContextAttribsARB) { - rk_printf("glXCreateContextAttribsARB() extension not found."); - rk_destroy_context(); - return nullptr; - } else { - rk_context = glXCreateContextAttribsARB(rk_display, bestFbc, 0, True, rk_context_attribs); - XSync(rk_display, False); - if (rk_error_occured || !rk_context) { - rk_printf("Failed to create context."); - rk_destroy_context(); - return nullptr; - } - } - XSetErrorHandler(oldHandler); - - if (!glXIsDirect(rk_display, rk_context)) { - rk_printf("Warning: Rendering context is indirect."); - } - glXMakeCurrent(rk_display, rk_window, rk_context); - - char const * const gl_exts = reinterpret_cast(glGetString(GL_EXTENSIONS)); - if (rk_extension_supported(gl_exts, "GL_EXT_base_instance")) { - rk_DrawElementsInstancedBaseInstance = - reinterpret_cast( - glXGetProcAddressARB(reinterpret_cast("DrawElementsInstancedBaseInstance"))); - if (rk_DrawElementsInstancedBaseInstance) { - rk_printf("Using extension GL_EXT_base_instance::DrawElementsInstancedBaseInstance."); - if (rk_extension_supported(gl_exts, "GL_EXT_multi_draw_indirect")) { - rk_MultiDrawElementsIndirect = - reinterpret_cast( - glXGetProcAddressARB(reinterpret_cast("MultiDrawElementsIndirectEXT"))); - if (rk_MultiDrawElementsIndirect) { - rk_printf("Using extension GL_EXT_multi_draw_indirect::MultiDrawElementsIndirectEXT."); - } - } - } - } - - return reinterpret_cast(rk_window); -} - -void rk_swap_buffers() { - if (rk_display && rk_window) { - glXSwapBuffers(rk_display, rk_window); - } -} - -void rk_destroy_context() { - if (rk_display) { - glXMakeCurrent(rk_display, 0, nullptr); - if (rk_context) { - glXDestroyContext(rk_display, rk_context); - rk_context = nullptr; - } - rk_terminate_events(); - if (rk_window) { - XDestroyWindow(rk_display, rk_window); - rk_window = 0; - } - if (rk_colormap) { - XFreeColormap(rk_display, rk_colormap); - rk_colormap = 0; - } - XCloseDisplay(rk_display); - rk_display = nullptr; - } -} diff --git a/cpp/render.hpp b/cpp/render.hpp index 885f2c8..0d46b6a 100644 --- a/cpp/render.hpp +++ b/cpp/render.hpp @@ -19,7 +19,6 @@ #include "types.hpp" #include "math.hpp" -typedef rk_handle_t rk_window_t; typedef rk_handle_t rk_shader_t; typedef rk_handle_t rk_input_t; typedef rk_handle_t rk_param_t; @@ -28,8 +27,6 @@ typedef rk_handle_t rk_triangles_t; typedef rk_handle_t rk_vertices_t; typedef rk_handle_t rk_batch_t; -#define RK_FLAG(bit) (1 << (bit)) - enum rk_texture_format : rk_uint { RK_TEXTURE_FORMAT_SRGB8_A8 = 0, RK_TEXTURE_FORMAT_RGBA8 = 1, @@ -81,10 +78,9 @@ union rk_mesh { }; }; -RK_EXPORT rk_window_t rk_initialize( - char const * name, - rk_uint width, - rk_uint height); +RK_EXPORT void rk_render_initialize(); + +RK_EXPORT void rk_render_terminate(); RK_EXPORT rk_shader_t rk_load_shader( rk_uint const vert_nlines, @@ -194,6 +190,4 @@ RK_EXPORT void rk_destroy_texture( RK_EXPORT void rk_destroy_shader( rk_shader_t shader); -RK_EXPORT void rk_terminate(); - #endif // _RK_ENGINE_RENDER_H diff --git a/cpp/opengl/render_opengles.cpp b/cpp/render/render_opengles.cpp similarity index 94% rename from cpp/opengl/render_opengles.cpp rename to cpp/render/render_opengles.cpp index bb80145..6c28863 100644 --- a/cpp/opengl/render_opengles.cpp +++ b/cpp/render/render_opengles.cpp @@ -13,17 +13,19 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +#include "../render.hpp" #include "render_opengles.hpp" +#include "../display/display_glx.hpp" #include static rk_shader const * rk_current_shader = nullptr; static rk_vertices const * rk_current_vertices = nullptr; -static void rk_printf(char const * messsage) { - printf("[RK_ENGINE] %s\n", messsage); +static void rk_printf(char const * message) { + printf("[RK] %s\n", message); } -#define rk_error(message) { if (glGetError() != GL_NO_ERROR) { rk_printf(message); } } +#define rk_gl_error(_message) { if (glGetError() != GL_NO_ERROR) { printf("[GL] %s\n", (_message)); } } static void rk_debug_message_callback( GLenum source, @@ -33,36 +35,32 @@ static void rk_debug_message_callback( GLsizei length, GLchar const * message, void const * userParam) { - printf("[RK_ENGINE][GL] (id=%d) %s\n", id, message); + printf("[GL] (id=%d) %s\n", id, message); } -rk_window_t rk_initialize( - char const * name, - rk_uint width, - rk_uint height) { - rk_window_t const window = rk_create_context(name, width, height); - if (window) { - GLubyte const * const vendor = glGetString(GL_VENDOR); - GLubyte const * const renderer = glGetString(GL_RENDERER); - printf("[RK_ENGINE] vendor: %s, renderer: %s\n", vendor, renderer); - GLubyte const * const version = glGetString(GL_VERSION); - GLubyte const * const language = glGetString(GL_SHADING_LANGUAGE_VERSION); - printf("[RK_ENGINE] version: %s, language: %s\n", version, language); +void rk_render_initialize() { + GLubyte const * const vendor = glGetString(GL_VENDOR); + GLubyte const * const renderer = glGetString(GL_RENDERER); + printf("[RK] vendor: %s, renderer: %s\n", vendor, renderer); + GLubyte const * const version = glGetString(GL_VERSION); + GLubyte const * const language = glGetString(GL_SHADING_LANGUAGE_VERSION); + printf("[RK] version: %s, language: %s\n", version, language); - glDebugMessageCallback(rk_debug_message_callback, nullptr); - glEnable(GL_DEBUG_OUTPUT); + glDebugMessageCallback(rk_debug_message_callback, nullptr); + glEnable(GL_DEBUG_OUTPUT); - glDisable(GL_BLEND); - glEnable(GL_DITHER); - glEnable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_STENCIL_TEST); - glEnable(GL_CULL_FACE); - glFrontFace(GL_CCW); - glCullFace(GL_BACK); - glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); - } - return window; + glDisable(GL_BLEND); + glEnable(GL_DITHER); + glEnable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_STENCIL_TEST); + glEnable(GL_CULL_FACE); + glFrontFace(GL_CCW); + glCullFace(GL_BACK); + glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); +} + +void rk_render_terminate() { } static void rk_print_shader_infolog(GLuint shader) { @@ -104,18 +102,18 @@ rk_shader_t rk_load_shader( rk_printf("Compiling vertex shader..."); glShaderSource(shader->vertex, vert_nlines, vert_lines, nullptr); glCompileShader(shader->vertex); - rk_error("glCompileShader() failed."); + rk_gl_error("glCompileShader() failed."); rk_print_shader_infolog(shader->vertex); rk_printf("Compiling fragment shader..."); glShaderSource(shader->fragment, frag_nlines, frag_lines, nullptr); glCompileShader(shader->fragment); - rk_error("glCompileShader() failed."); + rk_gl_error("glCompileShader() failed."); rk_print_shader_infolog(shader->fragment); rk_printf("Linking program..."); glAttachShader(shader->program, shader->vertex); glAttachShader(shader->program, shader->fragment); glLinkProgram(shader->program); - rk_error("glLinkProgram() failed."); + rk_gl_error("glLinkProgram() failed."); rk_print_program_infolog(shader->program); rk_printf("Done."); glReleaseShaderCompiler(); @@ -669,7 +667,6 @@ void rk_unselect_shader( } void rk_end_frame() { - rk_swap_buffers(); } void rk_destroy_batch( @@ -730,7 +727,3 @@ void rk_destroy_shader( delete shader; } } - -void rk_terminate() { - rk_destroy_context(); -} diff --git a/cpp/opengl/render_opengles.hpp b/cpp/render/render_opengles.hpp similarity index 97% rename from cpp/opengl/render_opengles.hpp rename to cpp/render/render_opengles.hpp index d73d160..d3a1186 100644 --- a/cpp/opengl/render_opengles.hpp +++ b/cpp/render/render_opengles.hpp @@ -16,8 +16,7 @@ #ifndef _RK_ENGINE_RENDER_OPENGLES_H #define _RK_ENGINE_RENDER_OPENGLES_H -#include "../render.hpp" -#include "render_context.hpp" +#include "../types.hpp" #include #include #include diff --git a/cpp/types.hpp b/cpp/types.hpp index 72f22ee..edac367 100644 --- a/cpp/types.hpp +++ b/cpp/types.hpp @@ -20,6 +20,7 @@ #include #define RK_EXPORT extern "C" +#define RK_FLAG(_bit) (1 << (_bit)) typedef bool rk_bool; typedef char rk_char;