Skip to content

Commit

Permalink
switch to SDL
Browse files Browse the repository at this point in the history
  • Loading branch information
SomeoneSerge committed Oct 24, 2022
1 parent c382d41 commit cf8b8e4
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 80 deletions.
13 changes: 9 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ add_library(
external/imgui/imgui_draw.cpp
external/imgui/imgui_tables.cpp
external/imgui/imgui_widgets.cpp
external/imgui/backends/imgui_impl_glfw.cpp
# external/imgui/backends/imgui_impl_glfw.cpp
external/imgui/backends/imgui_impl_sdl.cpp
external/imgui/backends/imgui_impl_opengl3.cpp
external/implot/implot.cpp
external/implot/implot_demo.cpp
Expand Down Expand Up @@ -46,18 +47,22 @@ if(BUILD_EMSCRIPTEN)

set_target_properties(
${PROJECT_NAME} PROPERTIES LINK_FLAGS
"-s USE_GLFW=3 -s MIN_WEBGL_VERSION=2 -s MAX_WEBGL_VERSION=2 --shell-file ${PROJECT_SOURCE_DIR}/shell.html"
"-fexceptions -s USE_SDL=2 -s MIN_WEBGL_VERSION=2 -s MAX_WEBGL_VERSION=2 --shell-file ${PROJECT_SOURCE_DIR}/shell.html"
)
target_compile_options(imgui PUBLIC -s USE_SDL=2 -fexceptions)
else()
find_package(GLEW REQUIRED)
find_package(glfw3 REQUIRED)
find_package(SDL2 REQUIRED)
find_package(OpenGL REQUIRED)

# I guess I don't want to target_link_libraries imgui with SDL2, do I?
target_include_directories(imgui PUBLIC ${SDL2_INCLUDE_DIRS})

target_link_libraries(
vizfft

GLEW
glfw
SDL2::SDL2
OpenGL::GL
)
endif()
Expand Down
161 changes: 102 additions & 59 deletions include/imraii.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,21 @@
#define _IM_RAII_H

#include <Eigen/Dense>

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <cstring>
#include <imgui.h>
#include <imgui_impl_glfw.h>

#include <imgui_impl_opengl3.h>
#include <imgui_impl_sdl.h>

#include <SDL.h>
#if defined(IMGUI_IMPL_OPENGL_ES2)
#include <SDL_opengles2.h>
#else
#include <SDL_opengl.h>
#endif

#include <implot.h>
#include <iomanip>
#include <iostream>
Expand All @@ -28,74 +37,77 @@ class NoCopy {
NoCopy operator=(const NoCopy &) = delete;
};

class SafeGlfwCtx : NoCopy {
class SafeSDLSession : NoCopy {
public:
SafeGlfwCtx() {
if (!glfwInit()) {
throw std::runtime_error("glfwInit() failed");
SafeSDLSession() {
if (0 != SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) {
std::cerr << "SDL_Init() failed: " << SDL_GetError() << std::endl;
std::abort();
}
}
~SafeGlfwCtx() { glfwTerminate(); }
~SafeSDLSession() { SDL_Quit(); }
};

class SafeGlfwWindow : NoCopy {
class SafeSDLWindow : NoCopy {
public:
SafeGlfwWindow(const char *title = "imraii.h",
const double width = WINDOW_MIN_WIDTH,
const double height = WINDOW_MIN_WIDTH * (9.0 / 16.0),
const double device_pixel_ratio = 1.0) {
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
SafeSDLWindow(const char *title = "imraii.h",
const double width = WINDOW_MIN_WIDTH,
const double height = WINDOW_MIN_WIDTH * (9.0 / 16.0),
const double device_pixel_ratio = 1.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);
#ifdef __EMSCRIPTEN__
// glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
#endif

SDL_WindowFlags windowFlags =
(SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI);

#ifdef __EMSCRIPTEN__
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
#else
windowFlags = (SDL_WindowFlags)(windowFlags | SDL_WINDOW_RESIZABLE);
#endif

_window =
glfwCreateWindow(width * device_pixel_ratio,
height * device_pixel_ratio, title, nullptr, nullptr);
_window = SDL_CreateWindow(
title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
width * device_pixel_ratio, height * device_pixel_ratio, windowFlags);
_context = SDL_GL_CreateContext(_window);

#ifdef __EMSCRIPTEN__
auto _result = emscripten_set_canvas_element_size("canvas", width, height);
// auto _result = emscripten_set_canvas_element_size("canvas", width,
// height);
#endif
}
~SafeGlfwWindow() { glfwDestroyWindow(_window); }
~SafeSDLWindow() { SDL_DestroyWindow(_window); }

GLFWwindow *window() const { return _window; }
void makeContextCurrent() const { glfwMakeContextCurrent(_window); };
SDL_Window *window() const { return _window; }
SDL_GLContext context() const { return _context; }
void makeContextCurrent() const { SDL_GL_MakeCurrent(_window, _context); };

private:
GLFWwindow *_window;
};

class SafeGlew : NoCopy {
public:
SafeGlew() {
glewExperimental = GL_TRUE;
glewInit();

if (glGenBuffers == nullptr) {
throw std::runtime_error("glewInit() failed: glGenBuffers == nullptr");
}
}
SDL_Window *_window;
SDL_GLContext _context;
};

class SafeImGui : NoCopy {
public:
SafeImGui(GLFWwindow *window) {
SafeImGui(SDL_Window *window, SDL_GLContext context) {
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init();
// ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplSDL2_InitForOpenGL(window, context);
ImGui_ImplOpenGL3_Init("#version 100");
ImPlot::CreateContext();
ImGui::StyleColorsDark();
}
~SafeImGui() {
ImPlot::DestroyContext();
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
// ImGui_ImplGlfw_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
}
};
Expand All @@ -113,6 +125,19 @@ class SafeVBO : NoCopy {
GLuint _vbo;
};

class SafeGlew : NoCopy {
public:
SafeGlew() {
glewExperimental = GL_TRUE;
glewInit();

if (glGenBuffers == nullptr) {
std::cerr << "glewInit() failed: glGenBuffers == nullptr" << std::endl;
std::abort();
}
}
};

class SafeVAO : NoCopy {
public:
SafeVAO() {
Expand Down Expand Up @@ -172,48 +197,66 @@ class VtxFragProgram : NoCopy {
SafeShaderProgram _program;
};

class GlfwFrame : NoCopy {
class SDLFrame : NoCopy {
public:
GlfwFrame(GLFWwindow *window) : window(window) {
glfwGetFramebufferSize(window, &_width, &_height);
SDLFrame(SDL_Window *window) : _shouldClose(false), window(window) {

SDL_Event event;
while (SDL_PollEvent(&event)) {
ImGui_ImplSDL2_ProcessEvent(&event);

if (event.type == SDL_WINDOWEVENT &&
event.window.event == SDL_WINDOWEVENT_CLOSE &&
event.window.windowID == SDL_GetWindowID(window))
_shouldClose = true;
};

SDL_GL_GetDrawableSize(window, &_width, &_height);

glClearColor(.45f, .55f, .6f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
int numKeys = 0;
const uint8_t *keyboard = SDL_GetKeyboardState(&numKeys);

if (keyboard[SDL_SCANCODE_ESCAPE]) {
_shouldClose = true;
}
}
~GlfwFrame() {
int dispWidth, dispHeight;
glfwGetFramebufferSize(window, &dispWidth, &dispHeight);
glViewport(0, 0, dispWidth, dispHeight);
glfwSwapBuffers(window);
glfwPollEvents();
~SDLFrame() {
SDL_GL_GetDrawableSize(window, &_width, &_height);
glViewport(0, 0, _width, _height);
SDL_GL_SwapWindow(window);
}

int width() const { return _width; }
int height() const { return _height; }

bool shouldClose() const { return _shouldClose; }

private:
GLFWwindow *window;
bool _shouldClose;
SDL_Window *window;
int _width, _height;
};

class ImGuiGlfwFrame : NoCopy {
class ImGuiSDLFrame : NoCopy {
const SafeSDLWindow &_window;

public:
ImGuiGlfwFrame() {
explicit ImGuiSDLFrame(const SafeSDLWindow &window) : _window(window) {
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui_ImplSDL2_NewFrame();


/* Fix negative DeltaTime in firefox */
auto &io = ImGui::GetIO();
io.DeltaTime = std::max(1e-9f, io.DeltaTime);
ImGui::NewFrame();
}
~ImGuiGlfwFrame() {
~ImGuiSDLFrame() {
ImGui::Render();
_window.makeContextCurrent();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
}
};
Expand Down Expand Up @@ -304,7 +347,7 @@ class SafeGlTexture : NoCopy {
if (channels != 1 && channels != 3 && channels != 4) {
std::cerr << "[E] texture cannot have " << channels << " channels"
<< std::endl;
throw std::invalid_argument("invalid number of channels");
std::abort();
}
const auto mode = modes[channels];

Expand Down
3 changes: 2 additions & 1 deletion shell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ mkShell {
cmake
pkg-config
ninja
glfw3
# glfw3
SDL2
glew.dev
libglvnd.dev
eigen
Expand Down
36 changes: 20 additions & 16 deletions src/vizfft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#define GL_GLEXT_PROTOTYPES
#define EGL_EGLEXT_PROTOTYPES

#define GLFW_INCLUDE_ES3
#include <GLES3/gl3.h>
// #define GLFW_INCLUDE_ES3
// #include <GLES3/gl3.h>
#endif

#include "implot.h"
Expand Down Expand Up @@ -103,14 +103,15 @@ struct Heatmap {
constexpr auto nyquist = 128;

struct App {
SafeGlfwCtx &glfwCtx;
SafeGlfwWindow &glfwWindow;
SafeGlew &glew;
SafeSDLSession &initSDL;
SafeSDLWindow &sdlWindow;
SafeImGui &imguiContext;
SafeGlTexture tex0, texAbs, texArg;
Heatmap heatAbs, heatArg;
ImEditVec2 editCoeffs;

bool shouldClose = false;

State prev = {.mulWindow = false,
.coef_a = std::numeric_limits<float>::quiet_NaN(),
.coef_b = std::numeric_limits<float>::quiet_NaN()};
Expand All @@ -121,8 +122,10 @@ struct App {

void App::frame() {

GlfwFrame glfwFrame(glfwWindow.window());
ImGuiGlfwFrame imguiFrame;
SDLFrame sdlFrame(sdlWindow.window());
ImGuiSDLFrame imguiFrame(sdlWindow);

shouldClose |= sdlFrame.shouldClose();

ImVec2 srcWindowSize = {500.0f, 640.0f};
ImGui::SetNextWindowSize(srcWindowSize, ImGuiCond_Once);
Expand Down Expand Up @@ -216,19 +219,20 @@ std::function<void()> frame_global;
void call_frame_global() { frame_global(); }

int main(int argc, char *argv[]) {
SafeGlfwCtx glfwCtx;
SafeGlfwWindow glfwWindow;
glfwWindow.makeContextCurrent();
SafeSDLSession sdlSession;
SafeSDLWindow sdlWindow;
sdlWindow.makeContextCurrent();

// It would seem it's not neccessary to glewInit() after all o_0
// SafeGlew glewCtx;

SafeGlew glew;
SafeImGui imguiContext(glfwWindow.window());
SafeImGui imguiContext(sdlWindow.window(), sdlWindow.context());

std::cout << "glGetString(GL_VERSION): " << glGetString(GL_VERSION)
<< std::endl;

App app = {.glfwCtx = glfwCtx,
.glfwWindow = glfwWindow,
.glew = glew,
App app = {.initSDL = sdlSession,
.sdlWindow = sdlWindow,
.imguiContext = imguiContext,
.editCoeffs = ImEditVec2("coeffs", ImVec2(-nyquist, nyquist),
ImVec2(-nyquist, nyquist))};
Expand All @@ -237,7 +241,7 @@ int main(int argc, char *argv[]) {
frame_global = [&]() { app.frame(); };
emscripten_set_main_loop(call_frame_global, 0, true);
#else
while (!glfwWindowShouldClose(glfwWindow.window())) {
while (!app.shouldClose) {
app.frame();
}
#endif
Expand Down

0 comments on commit cf8b8e4

Please sign in to comment.