meta: build system for Dear ImGui + GL3W + FreeType2

* Add build instructions for Dear ImGui that build the SDL +
  OpenGL 3 / OpenGL ES 2 backend.
* Use Dear ImGui's bundled GL3W as a loader (including in azur itself,
  which has not been using a loader until now).
* Properly select headers for OpenGL ES 2.0 (with the VAO extension) and
  attributes for WebGL; clear up OpenGL 4 error codes.
* If FreeType2 is available through pkg-config, or if empscripten is
  used (since it has a FreeType port), use FreeType to render fonts in
  Dear ImGui for much-appreciated hinting quality.

Minor changes:
* Add window title to azur_init().
* Use emscripten's infinite loop simulation to make sure everything
  stays in the same thread. This is needed for Dear ImGui to work.
This commit is contained in:
Lephe 2021-07-05 14:03:21 +02:00 committed by Lephenixnoir
parent bd081b03a2
commit 31da1c0998
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
7 changed files with 127 additions and 20 deletions

View File

@ -45,6 +45,7 @@ if(FACETS_PLATFORM STREQUAL linux)
pkg_check_modules(sdl2 REQUIRED sdl2 IMPORTED_TARGET)
pkg_check_modules(sdl2_image REQUIRED SDL2_image IMPORTED_TARGET)
pkg_check_modules(opengl REQUIRED opengl IMPORTED_TARGET)
pkg_check_modules(glx REQUIRED glx IMPORTED_TARGET)
link_libraries(PkgConfig::sdl2_image PkgConfig::sdl2 PkgConfig::opengl -lm)
endif()
@ -64,4 +65,9 @@ endif()
#---
# This provides Dear ImGui but also GL3W as an OpenGL loader
if(NOT FACETS_PLATFORM STREQUAL gint)
add_subdirectory(imgui-builds)
endif()
add_subdirectory(azur)

View File

@ -47,6 +47,11 @@ if(AZUR_PLATFORM_EMSCRIPTEN)
set_target_properties(azur PROPERTIES LINK_DEPENDS "${ASSETS_ABSOLUTE}")
endif()
# Use ImGui's integrated GL3W loader (which we build separately)
if(AZUR_GRAPHICS_OPENGL_3_3)
target_link_libraries(azur PUBLIC gl3w)
endif()
target_include_directories(azur
PUBLIC "${PROJECT_SOURCE_DIR}/include"
PUBLIC "${PROJECT_BINARY_DIR}/include"

View File

@ -14,7 +14,7 @@ AZUR_BEGIN_DECLS
On GINT_CG, the window size is fixed to 396x224 and ignored.
TODO: On GINT_CG, accept super-resolution in azur_init(). */
int azur_init(int window_width, int window_height);
int azur_init(char const *title, int window_width, int window_height);
/* azur_main_loop(): Run the update/render loop.

View File

@ -6,9 +6,19 @@
#include <azur/defs.h>
AZUR_BEGIN_DECLS
#define GL_GLEXT_PROTOTYPES
#include <SDL2/SDL_opengl.h>
#include <SDL2/SDL_opengl_glext.h>
#ifdef AZUR_GRAPHICS_OPENGL_3_3
# include "GL/gl3w.h"
# include <SDL2/SDL_opengl.h>
#endif /* OpenGL 3.3 */
#ifdef AZUR_GRAPHICS_OPENGL_ES_2_0
# define GL_GLEXT_PROTOTYPES
# include <SDL2/SDL_opengles2.h>
# define glGenVertexArrays glGenVertexArraysOES
# define glBindVertexArray glBindVertexArrayOES
# define glDeleteVertexArrays glDeleteVertexArraysOES
#endif /* OpenGL ES 2.0 */
/* azgl_error(): String description of a GLenum error code.
The returned pointer might be a static buffer modified by further calls. */

View File

@ -10,7 +10,7 @@ static SDL_GLContext glcontext = NULL;
static void main_loop_quit(void);
int azur_init(int window_width, int window_height)
int azur_init(char const *title, int window_width, int window_height)
{
int rc = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
if(rc < 0) {
@ -24,16 +24,24 @@ int azur_init(int window_width, int window_height)
return 1;
}
/* Select OpenGL 3.3 core, but not on the OpenGL ES/emscripten backend,
which does not support context attributes. */
/* Select OpenGL 3.3 core */
#ifdef AZUR_GRAPHICS_OPENGL_3_3
SDL_GL_SetAttribute(
SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
#endif
window = SDL_CreateWindow("facets-floating",
/* ... or select Open GL ES 2.0 */
#ifdef AZUR_GRAPHICS_OPENGL_ES_2_0
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#endif
window = SDL_CreateWindow(title,
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
window_width, window_height,
SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
@ -47,11 +55,21 @@ int azur_init(int window_width, int window_height)
azlog(FATAL, "SDL_GL_CreateContext: %s\n", SDL_GetError());
return 1;
}
SDL_GL_MakeCurrent(window, glcontext);
rc = SDL_GL_SetSwapInterval(0);
if(rc < 0)
azlog(ERROR, "SDL_GL_SetSwapInterval: %s\n", SDL_GetError());
#ifdef AZUR_GRAPHICS_OPENGL_3_3
rc = gl3wInit();
if(rc != 0) {
azlog(FATAL, "gl3wInit: %d\n", rc);
return 1;
}
#endif
glEnable(GL_SCISSOR_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@ -100,14 +118,18 @@ struct params {
bool tied, started;
};
static void nop(void)
{
}
static EM_BOOL frame(double time, void *data)
{
struct params *params = data;
if(params->tied && params->started)
params->update();
if(params->update) params->update();
params->render();
if(params->render) params->render();
params->started = true;
return EM_TRUE;
@ -129,7 +151,13 @@ int azur_main_loop(
if(!(flags & AZUR_MAIN_LOOP_TIED)) {
void (*update_v)(void) = (void *)update;
emscripten_set_main_loop(update_v, update_ups, false);
emscripten_set_main_loop(update_v, update_ups, true);
}
else {
/* Even if no update is requested, we want emscripten to simulate an
infinite loop, as it is needed for Dear ImGui to work due to
threading considerations */
emscripten_set_main_loop(nop, 1, true);
}
return 0;
@ -193,7 +221,7 @@ int azur_main_loop(
while(1) {
if(update_tick && !(flags & AZUR_MAIN_LOOP_TIED)) {
update_tick = 0;
if(update()) break;
if(update && update()) break;
}
/* When vsync is enabled, render() is indirectly blocking so we just
@ -203,9 +231,9 @@ int azur_main_loop(
/* Tied renders and updates */
if(started && (flags & AZUR_MAIN_LOOP_TIED)) {
if(update()) break;
if(update && update()) break;
}
render();
if(render) render();
started = true;
}

View File

@ -45,10 +45,6 @@ char const *azgl_error(GLenum ec)
return "Invalid value";
case GL_INVALID_OPERATION:
return "Invalid operation";
case GL_STACK_OVERFLOW:
return "Stack overflow";
case GL_STACK_UNDERFLOW:
return "Stack underflow";
case GL_OUT_OF_MEMORY:
return "Out of memory";
}

View File

@ -0,0 +1,62 @@
# The GL3W library which is generated along in Dear ImGui
if(AZUR_GRAPHICS_OPENGL_3_3)
add_library(gl3w
../imgui/examples/libs/gl3w/GL/gl3w.c)
target_include_directories(gl3w PUBLIC
../imgui/examples/libs/gl3w)
# Link with GLX for GL3X to find the extensions, and -ldl
target_link_libraries(gl3w INTERFACE PkgConfig::glx -ldl)
endif()
# The Dear ImGui library for SDL + OpenGL3/OpenGLES2
set(SOURCES
../imgui/imgui.cpp
../imgui/imgui_demo.cpp
../imgui/imgui_draw.cpp
../imgui/imgui_tables.cpp
../imgui/imgui_widgets.cpp
../imgui/backends/imgui_impl_opengl3.cpp
../imgui/backends/imgui_impl_sdl.cpp)
# Use Freetype if the library is installed, or the emscripten port
if(AZUR_PLATFORM_EMSCRIPTEN)
list(APPEND SOURCES ../imgui/misc/freetype/imgui_freetype.cpp)
else()
pkg_check_modules(freetype2 freetype2 IMPORTED_TARGET)
if(freetype2_FOUND)
list(APPEND SOURCES ../imgui/misc/freetype/imgui_freetype.cpp)
endif()
endif()
add_library(imgui ${SOURCES})
# Try to reduce the size of the binary code by including individual functions
# from the archive, instead of whole files
target_compile_options(imgui PRIVATE -ffunction-sections)
target_compile_options(imgui INTERFACE -Wl,--gc-sections)
# Use the pre-built GL3W loader on desktop
if(AZUR_GRAPHICS_OPENGL_3_3)
target_compile_definitions(imgui PUBLIC
-DIMGUI_IMPL_OPENGL_LOADER_GL3W="GL/gl3w.h")
target_link_libraries(imgui PUBLIC gl3w)
# Use the autonomous GLES 2.0 loader otherwise
elseif(AZUR_GRAPHICS_OPENGL_ES_2_0)
target_compile_definitions(imgui PUBLIC
-DIMGUI_IMPL_OPENGL_ES2)
endif()
# FreeType2 settings
if(freetype2_FOUND)
target_compile_definitions(imgui PUBLIC -DIMGUI_ENABLE_FREETYPE)
target_include_directories(imgui PRIVATE ../imgui/misc/freetype)
target_link_libraries(imgui PUBLIC PkgConfig::freetype2)
elseif(AZUR_PLATFORM_EMSCRIPTEN)
target_compile_definitions(imgui PUBLIC -DIMGUI_ENABLE_FREETYPE)
target_include_directories(imgui PRIVATE ../imgui/misc/freetype)
target_compile_options(imgui PUBLIC -sUSE_FREETYPE=2)
target_link_options(imgui INTERFACE -sUSE_FREETYPE=2)
endif()
# Provide include directories
target_include_directories(imgui PUBLIC ../imgui ../imgui/backends)