From 2403f060eba6fdb7ba0704fe5ff2f95156bbf3a1 Mon Sep 17 00:00:00 2001 From: Bubblegumdrop Date: Sun, 9 Jan 2022 23:37:48 -0500 Subject: [PATCH] Add SHADER_PROGRAM_REFRESH, and a bunch of debug crap because of events. So when PACKET_SDL_EVENT was SDL_USEREVENT, things worked fine in the main loop it would see SDL_USEREVENT and send it off to my_SDL_UserEvent. But when I started adding more events, the SDL_UserEvent paradigm given in the SDL Wiki stopped working. The example here is broken: https://wiki.libsdl.org/SDL_AddTimer The example here is working and "correct": https://wiki.libsdl.org/SDL_UserEvent All SDL_RegisterEvents is increase a static counter. SDL doesn't actually use these events anyway. It's purely symbolic, as far as I can tell. So anyway. Now events work after a bunch of debugging. SHADER_PROGRAM_REFRESH is the second user event I've done. The ShaderProgram runs an SDL_TimerID that looks at mVertexPath, mGeometryPath if present, and mFragmentPath. mVertexPath and mFragmentPath are required by Compile3ShaderBuffers. In the future I'd like to change the way this class behaves. --- Makefile | 1 + glsl/camera.v.glsl | 4 +- glsl/header.f.glsl | 6 +- glsl/new.f.glsl | 6 +- include/FileIO.h | 1 - include/UDPbase.h | 3 +- include/UDPpacketVBuffer.h | 32 +++++++++ include/events_common.h | 7 +- include/lib_SDL_Log.h | 15 ++++ include/shader.h | 39 ++++++++++- include/util.h | 2 - src/FileIO.cpp | 32 +++------ src/Server.cpp | 16 ++--- src/UDPbase.cpp | 41 +++++++---- src/UDPpacketVBuffer.cpp | 8 +-- src/client_main.cpp | 167 ++++++++++++++++++++++++++++----------------- src/lib_GL_common.cpp | 17 +++++ src/lib_SDL_Log.cpp | 24 +++++++ src/lib_SDL_common.cpp | 21 +++++- src/quad.cpp | 4 +- src/server_main.cpp | 14 ++-- src/shader.cpp | 147 ++++++++++++++++++++++++++++++++------- src/signal_common.cpp | 2 + src/util.cpp | 6 +- test/test_FileIO.cpp | 12 ++-- test/test_lua.cpp | 53 +++++++++++--- 26 files changed, 502 insertions(+), 178 deletions(-) create mode 100644 include/lib_SDL_Log.h create mode 100644 src/lib_SDL_Log.cpp diff --git a/Makefile b/Makefile index 32a22ef..bb7b660 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,7 @@ DEPS := $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))) COMMON_OBJS := \ $(OBJDIR)/src/lib_lua_common.o \ $(OBJDIR)/src/lib_SDL_common.o \ + $(OBJDIR)/src/lib_SDL_Log.o \ $(OBJDIR)/src/signal_common.o \ $(OBJDIR)/src/UDPbase.o \ $(OBJDIR)/src/UDPpacketVBuffer.o \ diff --git a/glsl/camera.v.glsl b/glsl/camera.v.glsl index c76ebfd..20504d6 100644 --- a/glsl/camera.v.glsl +++ b/glsl/camera.v.glsl @@ -5,7 +5,7 @@ layout(location = 0) in vec3 aPos; layout(location = 1) in vec2 aTexCoord; -out vec2 iTexCoord; +out vec2 TexCoords; uniform mat4 Model; uniform mat4 View; @@ -13,5 +13,5 @@ uniform mat4 Projection; void main(void) { gl_Position = Projection * View * Model * vec4(aPos, 1.0f); - iTexCoord = aTexCoord; + TexCoords = aTexCoord; } diff --git a/glsl/header.f.glsl b/glsl/header.f.glsl index 9f059a8..b36c964 100644 --- a/glsl/header.f.glsl +++ b/glsl/header.f.glsl @@ -39,8 +39,8 @@ out vec4 fragColor; in vec2 TexCoords; -void mainImage(out vec4, in vec2); +void mainImage (out vec4, in vec2); -void main(void) { - mainImage(fragColor, gl_FragCoord.xy); +void main (void) { + mainImage (fragColor, gl_FragCoord.xy); } diff --git a/glsl/new.f.glsl b/glsl/new.f.glsl index 2691092..18463e9 100644 --- a/glsl/new.f.glsl +++ b/glsl/new.f.glsl @@ -4,11 +4,11 @@ void mainImage(out vec4 fragColor, in vec2 fragCoord) { // Normalized pixel coordinates (from 0 to 1) - // vec2 uv = TexCoords; // fragCoord / iResolution.xy; - vec2 uv = fragCoord / iResolution.xy; + vec2 uv = TexCoords; // fragCoord / iResolution.xy; + // vec2 uv = fragCoord / iResolution.xy; // Time varying pixel color - vec3 col = 0.5 + 0.5 * cos(iTime + uv.xyx + vec3(0, 2, 4)); + vec3 col = 0.5 + 0.5 * cos(iTime + fract (1.5 * (0.5 - uv.xyx) / (0.5 - uv.yxy) + iTime) + vec3(0, 2, 4)); // Output to screen fragColor = vec4(col, 1.0); diff --git a/include/FileIO.h b/include/FileIO.h index 6a26326..5e89f3f 100644 --- a/include/FileIO.h +++ b/include/FileIO.h @@ -26,7 +26,6 @@ class FileIO size_t Write (const void *, const size_t); void Rewind (void); /* I added these. */ - time_t Mtime (void); off_t Size (void); std::string ReadToString (void); }; diff --git a/include/UDPbase.h b/include/UDPbase.h index 18b7a86..743543d 100644 --- a/include/UDPbase.h +++ b/include/UDPbase.h @@ -7,7 +7,7 @@ class UDPbase { - IPaddress addr; + IPaddress mIPAddress; public: UDPbase (const char* host, const Uint16 port); ~UDPbase (void); @@ -17,4 +17,5 @@ class UDPbase int Bind (UDPsocket sock, const int channel); void Unbind (UDPsocket sock, const int channel); std::string toString (void); + IPaddress* GetPeerAddress (UDPsocket sock, const int channel); }; diff --git a/include/UDPpacketVBuffer.h b/include/UDPpacketVBuffer.h index f3c6448..f47dbdd 100644 --- a/include/UDPpacketVBuffer.h +++ b/include/UDPpacketVBuffer.h @@ -2,6 +2,38 @@ #include +/** + +# UDPpacketVBuffer + +Create your `UDPsocket` somewhere: + + UDPsocket sock; + ... + +You have a buffer: + + FileIO f (path, "r"); + std::string buf = f.ReadToString (); + +Allocate a setup packet and set `len` to your MTU, set your destination `address`, and the destination `channel`. +I'm not sure -1 will work as a channel, be sure to set it to your active channel. + + UDPpacket* packet = SDL_AllocPacket (buf.length ()); + packet->len = DEFAULT_MAX_PACKET_SIZE; + packet->channel = -1; + packet->address = GetPeerAddress (sock, packet->channel); + +Use `UDPpacketVBuffer` wrapper to send the data, the destructor will automatically free the `UDPpacket**`: + + UDPpacketVBuffer packetV (&buf[0], buf.length ()); + packetV.Send (sock); + +Then free the leftover setup packet: + + SDLNet_FreePacket (packet); + +*/ class UDPpacketVBuffer { int npackets; diff --git a/include/events_common.h b/include/events_common.h index 350985a..84216fb 100644 --- a/include/events_common.h +++ b/include/events_common.h @@ -3,5 +3,10 @@ #include enum { - PACKET_SDL_EVENT = SDL_USEREVENT, + SDL_USEREVENT_FIRST = SDL_USEREVENT, + + PACKET_SDL_EVENT, + SHADER_PROGRAM_REFRESH, + + SDL_USEREVENT_LAST, }; diff --git a/include/lib_SDL_Log.h b/include/lib_SDL_Log.h new file mode 100644 index 0000000..1c99236 --- /dev/null +++ b/include/lib_SDL_Log.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include +#include + +struct LogWrapper +{ + void* userdata; + SDL_mutex* mutex; + SDL_LogOutputFunction fn; +}; + +// static void my_SDL_Log (void* userdata, int category, SDL_LogPriority priority, const char* message); +void my_SDL_Log_Init (void); diff --git a/include/shader.h b/include/shader.h index 30516c9..8eb3eef 100644 --- a/include/shader.h +++ b/include/shader.h @@ -3,20 +3,43 @@ #include #include +#include #include #include #include +#include + class ShaderProgram { + /* TODO there's gotta be a better way of doing this! */ + std::string mVertexPath, mGeometryPath, mFragmentPath; + SDL_TimerID mShaderWatchTimer; + /* most recent modification times for the three in order */ + time_t mMtime[3]; + bool mUniformLocationsNeedRefresh; std::map UniformLocationCache; + static GLint my_checkCompileSuccess (const GLuint, const GLenum); + static Uint32 my_WatchShaderHelper (Uint32 interval, void* param); + + GLint getCachedLoc (const std::string&); + public: + /* + * Set-able + */ GLuint ID; + ShaderProgram (const std::string&, const std::string&, const std::string&); - GLint getCachedLoc (const std::string&); + + ~ShaderProgram (void); + + /* + * gl* stuff. These modify the current `ID`. + */ void RefreshUniformLocations (void); void Use (void); void Bool (const std::string&, const bool&); @@ -29,8 +52,22 @@ class ShaderProgram void Mat3 (const std::string&, const glm::mat3&); void Mat4 (const std::string&, const glm::mat4&); + /* + * Program/util stuff + */ GLuint CompileShaderBuffer (const std::string&, const GLenum); GLuint Compile3ShaderBuffers (const std::string&, const std::string&, const std::string&); GLuint CompileShaderPath (const std::string&, const GLenum); GLint LinkProgram (void); + + /* + * Monitor the modification time of the loaded shaders + */ + void StartWatchingShader (void); + void StopWatchingShader (void); + bool NeedsReloading (bool); + + const std::string& getVertexPath (void) const { return mVertexPath; } + const std::string& getGeometryPath (void) const { return mGeometryPath; } + const std::string& getFragmentPath (void) const { return mFragmentPath; } }; diff --git a/include/util.h b/include/util.h index 7363904..3ca2bc1 100644 --- a/include/util.h +++ b/include/util.h @@ -12,5 +12,3 @@ int util_IsProbablyAscii (const void *, const size_t); void util_HexDump (const void *, const size_t); void util_UDP_DumpPacket (UDPpacket*); - -UDPpacket** Buffer_To_UDPPacketV (UDPpacket* src, const void* buf, const size_t size); diff --git a/src/FileIO.cpp b/src/FileIO.cpp index cc630dc..3d9d363 100644 --- a/src/FileIO.cpp +++ b/src/FileIO.cpp @@ -3,6 +3,7 @@ #include #include +#include /* strerror */ #include /* errno */ #include /* FILE* */ #include /* stat */ @@ -12,12 +13,12 @@ FileIO::FileIO (const std::string& filename, const std::string& mode) { if (!(fp = Open (filename, mode))) - throw errno; + throw "FileIO::FileIO: " + std::string (strerror (errno)); path = filename; } -FileIO::~FileIO(void) +FileIO::~FileIO (void) { if (fp) { @@ -48,22 +49,21 @@ FileIO::Seek (const off_t offset, const int whence) } -off_t -FileIO::Tell (void) +off_t FileIO::Tell (void) { return ftello (fp); } size_t -FileIO::Read (void *dst, const size_t size) +FileIO::Read (void* dst, const size_t size) { return fread (dst, sizeof (char), size, fp); } size_t -FileIO::Write (const void *dst, const size_t size) +FileIO::Write (const void* dst, const size_t size) { return fwrite (dst, sizeof (char), size, fp); } @@ -76,22 +76,7 @@ FileIO::Rewind (void) } -time_t -FileIO::Mtime (void) -{ - time_t rc; - struct stat sb; - rc = 0; - if (!stat (path.c_str (),&sb)) - rc = sb.st_mtime; - else - throw errno; - return rc; -} - - -off_t -FileIO::Size (void) +off_t FileIO::Size (void) { off_t rc; Seek (0, SEEK_END); @@ -101,8 +86,7 @@ FileIO::Size (void) } -std::string -FileIO::ReadToString (void) +std::string FileIO::ReadToString (void) { off_t size = Size (); std::string b (size, 0); diff --git a/src/Server.cpp b/src/Server.cpp index 1ac5f4b..1cb3770 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -23,6 +23,8 @@ Server::Server (const char *host, const Uint16 port) Server::~Server (void) { + Stop (); + CloseAllSockets (); if (packetV) @@ -187,7 +189,6 @@ void Server::ProcessPacketHelper (UDPpacket* src) { SDL_Event event; - SDL_UserEvent userevent; UDPpacket *dst; dst = SDLNet_AllocPacket (src->len); @@ -200,13 +201,8 @@ Server::ProcessPacketHelper (UDPpacket* src) SDL_memcpy (dst->data, src->data, src->len); SDL_zero (event); - SDL_zero (userevent); - userevent.type = PACKET_SDL_EVENT; - userevent.code = 0; - userevent.data1 = (void *) dst; - userevent.data2 = (void *) NULL; - event.type = SDL_USEREVENT; - event.user = userevent; + event.type = PACKET_SDL_EVENT; + event.user.data1 = (void *) dst; SDL_PushEvent (&event); } @@ -216,9 +212,10 @@ Uint32 Server::FetchPacketsCallback (Uint32 interval, void *param) int i, j; int numrecv, numready; UDPpacket** packetV; + Server* server; SDL_assert (NULL != param); - Server* server = (Server *) param; + server = (Server *) param; if (server->Lock () < 0) { @@ -226,6 +223,7 @@ Uint32 Server::FetchPacketsCallback (Uint32 interval, void *param) return 0; } + /* TODO Make this interruptable */ numready = SDLNet_CheckSockets (server->getSocketSet (), 1); if (numready < 0) { diff --git a/src/UDPbase.cpp b/src/UDPbase.cpp index 9466d13..8cdcaba 100644 --- a/src/UDPbase.cpp +++ b/src/UDPbase.cpp @@ -2,7 +2,7 @@ UDPbase::UDPbase (const char* host, const Uint16 port) { - if (SDLNet_ResolveHost (&addr, host, port) < 0) + if (SDLNet_ResolveHost (&mIPAddress, host, port) < 0) { throw "SDLNet_ResolveHost: " + std::string (SDLNet_GetError ()); } @@ -14,29 +14,43 @@ UDPbase::~UDPbase (void) } -UDPsocket UDPbase::Open (void) +UDPsocket +UDPbase::Open (void) { - return Open (addr.port); + return Open (mIPAddress.port); } -UDPsocket UDPbase::Open (const Uint16 port) +UDPsocket +UDPbase::Open (const Uint16 port) { - IPaddress* addr = NULL; UDPsocket sock = NULL; if (NULL == (sock = SDLNet_UDP_Open (port))) { throw "SDLNet_UDP_Open: " + std::string (SDLNet_GetError ()); } - if (NULL != (addr = SDLNet_UDP_GetPeerAddress (sock, -1))) + if (NULL != GetPeerAddress (sock, -1)) { - SDL_Log ("Opened UDP port %d", SDLNet_Read16 (&addr->port)); + SDL_Log ("Opened UDP port %d", SDLNet_Read16 (&mIPAddress.port)); } return sock; } -void UDPbase::Close (UDPsocket sock) +IPaddress* +UDPbase::GetPeerAddress (UDPsocket sock, const int channel) +{ + IPaddress* addr = NULL; + if (NULL == (addr = SDLNet_UDP_GetPeerAddress (sock, channel))) + { + throw "SDLNet_UDP_GetPeerAddress: " + std::string (SDLNet_GetError ()); + } + return addr; +} + + +void +UDPbase::Close (UDPsocket sock) { SDL_assert (NULL != sock); SDLNet_UDP_Close (sock); @@ -44,11 +58,12 @@ void UDPbase::Close (UDPsocket sock) } -int UDPbase::Bind (UDPsocket sock, const int channel) +int +UDPbase::Bind (UDPsocket sock, const int channel) { int binding; SDL_assert (NULL != sock); - if (-1 == (binding = SDLNet_UDP_Bind (sock, channel, &addr))) + if (-1 == (binding = SDLNet_UDP_Bind (sock, channel, &mIPAddress))) { throw "SDLNet_UDP_Bind: " + std::string (SDLNet_GetError ()); } @@ -57,7 +72,8 @@ int UDPbase::Bind (UDPsocket sock, const int channel) } -void UDPbase::Unbind (UDPsocket sock, const int channel) +void +UDPbase::Unbind (UDPsocket sock, const int channel) { SDLNet_UDP_Unbind (sock, channel); } @@ -65,5 +81,6 @@ void UDPbase::Unbind (UDPsocket sock, const int channel) std::string UDPbase::toString (void) { - return std::string (SDLNet_ResolveIP (&addr)) + ":" + std::to_string (SDLNet_Read16 (&addr.port)); + return std::string (SDLNet_ResolveIP (&mIPAddress)) + ":" + + std::to_string (SDLNet_Read16 (&mIPAddress.port)); } diff --git a/src/UDPpacketVBuffer.cpp b/src/UDPpacketVBuffer.cpp index 25e2ebd..53b80d5 100644 --- a/src/UDPpacketVBuffer.cpp +++ b/src/UDPpacketVBuffer.cpp @@ -8,14 +8,14 @@ UDPpacketVBuffer::UDPpacketVBuffer (UDPpacket* src, const void* buf, const size_ const uint8_t* bufPtr; const uint8_t* bufPtrEnd; - SDL_assert (NULL != src); SDL_assert (NULL != buf); + SDL_assert (NULL != src); mtu = src->len; SDL_assert (mtu > 0); + npackets = (int) ceil ((double) size / (double) mtu); + // SDL_Log ("%d", npackets); - npackets = (int)ceil ((double) size / (double) mtu); - SDL_Log ("%d", npackets); if (NULL == (packetV = SDLNet_AllocPacketV (npackets, mtu))) { throw "SDLNet_AllocPacketV: " + std::string (SDLNet_GetError ()); @@ -23,7 +23,7 @@ UDPpacketVBuffer::UDPpacketVBuffer (UDPpacket* src, const void* buf, const size_ i = 0; nsent = size; - bufPtr = (const uint8_t*)buf; + bufPtr = (const uint8_t*) buf; bufPtrEnd = bufPtr + size; while ((i < npackets) && (bufPtr < bufPtrEnd) && (nsent > 0)) { diff --git a/src/client_main.cpp b/src/client_main.cpp index c3383bb..6c9b075 100644 --- a/src/client_main.cpp +++ b/src/client_main.cpp @@ -10,6 +10,7 @@ #include "unused.h" #include "UDPbase.h" #include "UDPpacketVBuffer.h" +#include "events_common.h" #include #include @@ -26,16 +27,17 @@ #define MIN_FRAME_MS 7 /* 144 Hz */ -static int my_AnalogInput (void); -static int my_Input (SDL_Event *); -static int my_Input_Key (SDL_Event *); -static int my_SDL_WindowEvent (SDL_Event *); +static bool my_AnalogInput (void); +static bool my_Input_Key (SDL_Event*); +static bool my_Input (SDL_Event*); +static bool my_SDL_UserEvent (SDL_Event*); +static bool my_SDL_WindowEvent (SDL_Event*); -static void my_GetOpt (int, char **); +static void my_GetOpt (int, char**); static void my_Init (int, char**); static void my_Render (void); static void my_UpdateValues (void); -static void my_Usage (const char *); +static void my_Usage (const char*); struct Uniform_Values { @@ -54,7 +56,7 @@ struct Uniform_Values struct Client_State { - int quit; + bool done; Uint64 start, end; double diff; @@ -66,7 +68,7 @@ struct Client_State int mtu; SDL_GLContext GLContext; - SDL_Window *Window; + SDL_Window* Window; int Window_Height; int Window_Width; @@ -91,7 +93,7 @@ static struct Client_State state; static struct Uniform_Values values; int -main (int argc, char **argv) +main (int argc, char** argv) { glm::mat4 model, view, projection; SDL_Event event; @@ -114,7 +116,7 @@ main (int argc, char **argv) quad = std::make_unique (1); state.mtu = 1450; - state.quit = 0; + state.done = false; client = std::make_unique (state.host, state.port); if (NULL == (state.udpsock = client->Open (0))) { @@ -127,7 +129,7 @@ main (int argc, char **argv) goto _out; } - while (!state.quit) + while (!state.done) { state.end = SDL_GetPerformanceCounter (); state.diff = Perf_Diff (state.start, state.end); @@ -142,9 +144,9 @@ main (int argc, char **argv) SDL_SetRelativeMouseMode ((SDL_bool) state.InputRelativeMouseMode); SDL_CaptureMouse ((SDL_bool) state.InputCaptureMouse); - while (!state.quit && SDL_PollEvent (&event)) + while (!state.done && SDL_PollEvent (&event)) { - state.quit = my_Input (&event); + state.done = my_Input (&event); } my_AnalogInput (); @@ -234,19 +236,19 @@ my_Render (void) cube->Draw (); } else - quad->Draw (); + quad->Draw (); } -static int -my_SDL_MouseMotion (SDL_Event * event) +static bool +my_SDL_MouseMotion (SDL_Event* event) { SDL_assert (NULL != event); const float xpos = event->motion.x; const float ypos = event->motion.y; if (!state.InputCaptureMouse || state.ImGuiEnabled) - return SDL_FALSE; + return false; if (state.InputFirstMouse) { @@ -264,36 +266,34 @@ my_SDL_MouseMotion (SDL_Event * event) camera.ProcessMouseMovement (Xoffset, Yoffset, 0.1); - return SDL_FALSE; + return false; } -static int -my_SDL_MouseButton (SDL_Event * event) +static bool +my_SDL_MouseButton (SDL_Event* event) { int down; - int quit; + bool done = false; SDL_assert (NULL != event); down = event->type == SDL_MOUSEBUTTONDOWN; - quit = SDL_FALSE; - return quit; + return done; } -static int -my_Input (SDL_Event * event) +static bool +my_Input (SDL_Event* event) { - int quit; + bool done = false; SDL_assert (NULL != event); - quit = SDL_FALSE; switch (event->type) { case SDL_QUIT: - quit = SDL_TRUE; + done = true; break; case SDL_KEYDOWN: case SDL_KEYUP: - quit = my_Input_Key (event); + done = my_Input_Key (event); break; case SDL_MOUSEMOTION: my_SDL_MouseMotion (event); @@ -302,17 +302,21 @@ my_Input (SDL_Event * event) case SDL_MOUSEBUTTONUP: my_SDL_MouseButton (event); break; + case SHADER_PROGRAM_REFRESH: + my_SDL_UserEvent (event); + break; + break; case SDL_WINDOWEVENT: my_SDL_WindowEvent (event); break; default: break; } - return quit; + return done; } -static int +static bool my_AnalogInput (void) { const Uint8* kbd = SDL_GetKeyboardState (NULL); @@ -320,7 +324,7 @@ my_AnalogInput (void) (void) state; if (!state.AnalogInputEnabled) - return SDL_FALSE; + return false; camera.ProcessKeyboard (kbd[SDL_SCANCODE_W] ? Camera::Movement::FORWARD : Camera::Movement::NONE, dt); camera.ProcessKeyboard (kbd[SDL_SCANCODE_S] ? Camera::Movement::BACKWARD : Camera::Movement::NONE, dt); @@ -332,48 +336,54 @@ my_AnalogInput (void) camera.ProcessKeyboard (kbd[SDL_SCANCODE_Q] ? Camera::Movement::CW : Camera::Movement::NONE, dt); camera.ProcessKeyboard (kbd[SDL_SCANCODE_E] ? Camera::Movement::CCW : Camera::Movement::NONE, dt); - return SDL_FALSE; + return false; } -static int -my_Input_Key (SDL_Event * event) +static bool +my_Input_Key (SDL_Event* event) { int down; - int quit; + bool done = false; + SDL_Keycode key; + SDL_assert (NULL != event); + down = event->type == SDL_KEYDOWN; - quit = SDL_FALSE; + key = event->key.keysym.sym; + if (!state.ImpulseInputEnabled) { - switch (event->key.keysym.sym) + switch (key) { case SDLK_i: state.ImpulseInputEnabled = true; break; case SDLK_ESCAPE: - quit = SDL_TRUE; + done = true; break; case SDLK_F11: + { + if (down) { - if (down) - { - state.InputFirstMouse = true; - state.InputCaptureMouse = true; - state.InputRelativeMouseMode = true; - common_SDL_ToggleFullscreen (SDL_GetWindowFromID (event->key.windowID)); - } + state.InputFirstMouse = true; + state.InputCaptureMouse = true; + state.InputRelativeMouseMode = true; + common_SDL_ToggleFullscreen (SDL_GetWindowFromID (event->key.windowID)); } - break; + } + break; default: break; } - return SDL_FALSE; + + return done; } - switch (event->key.keysym.sym) + + switch (key) { case SDLK_ESCAPE: - quit = SDL_TRUE; + done = true; break; case SDLK_F11: { @@ -422,28 +432,61 @@ my_Input_Key (SDL_Event * event) IPaddress* addr = SDLNet_UDP_GetPeerAddress (state.udpsock, state.channel); if (addr) { - SDL_Log ("%s:%d", SDLNet_ResolveIP (addr), SDLNet_Read16(&addr->port)); + // SDL_Log ("%s:%d", SDLNet_ResolveIP (addr), SDLNet_Read16(&addr->port)); packet->address = *addr; UDPpacketVBuffer packetV (packet, (const void*)event, sizeof (SDL_Event)); packetV.Send (state.udpsock); } SDLNet_FreePacket (packet); } - - // SDL_Log ("%d %d %ld", state.channel, state.mtu, sizeof (SDL_Event)); - // Buffer_Write_UDP (state.udpsock, state.channel, state.mtu, (const void*)event, sizeof (SDL_Event)); } } - return quit; + + return done; } -static int -my_SDL_WindowEvent (SDL_Event * event) +static bool +my_SDL_UserEvent (SDL_Event* event) { - int quit; + bool done = false; + SDL_assert (NULL != event); + switch (event->user.type) + { + case SHADER_PROGRAM_REFRESH: + { + SDL_Log ("SHADER_PROGRAM_REFRESH"); + /* Actually do the refresh */ + GLuint id; + try { + id = shader->Compile3ShaderBuffers (shader->getVertexPath (), shader->getGeometryPath (), shader->getFragmentPath ()); + } + catch (const std::string& e) + { + SDL_Log ("%s", e.c_str ()); + id = 0; + } + if (id) + { + glUseProgram (0); + glDeleteProgram (shader->ID); + shader->ID = id; + shader->Use (); + shader->NeedsReloading (true); + shader->RefreshUniformLocations (); + } + } + break; + } + return done; +} + + +static bool +my_SDL_WindowEvent (SDL_Event* event) +{ + bool done = false; SDL_assert (NULL != event); - quit = SDL_FALSE; switch (event->window.event) { case SDL_WINDOWEVENT_RESIZED: @@ -456,19 +499,19 @@ my_SDL_WindowEvent (SDL_Event * event) default: break; } - return quit; + return done; } static void -my_Usage (const char *argv0) +my_Usage (const char* argv0) { fprintf (stderr, "Usage: %s [-h] [-s host] [-p port]\n", argv0); } static void -my_GetOpt (int argc, char **argv) +my_GetOpt (int argc, char** argv) { int opt; state.host = "localhost"; diff --git a/src/lib_GL_common.cpp b/src/lib_GL_common.cpp index f99bbc7..278ee5e 100644 --- a/src/lib_GL_common.cpp +++ b/src/lib_GL_common.cpp @@ -1,3 +1,4 @@ +#include "debug.h" #include "FileIO.h" #include "lib_SDL_common.h" #include "lib_GL_common.h" @@ -10,6 +11,8 @@ #include #include +static void common_GL_DebugInfo (void); + void common_GL_Init (SDL_Window * wind, SDL_GLContext * ctx, int SwapInterval) { @@ -26,6 +29,7 @@ common_GL_Init (SDL_Window * wind, SDL_GLContext * ctx, int SwapInterval) exit (EXIT_FAILURE); } SDL_assert (err == GLEW_OK); + common_GL_DebugInfo (); glCheckErrors (); } @@ -102,3 +106,16 @@ common_GL_LoadTexturePath (const char *path) } return id; } + + +static void common_GL_DebugInfo (void) +{ + GLint i, n; + + glGetIntegerv (GL_NUM_EXTENSIONS, &n); + + for (i = 0; i < n; i++) + { + DEBUG_LOG ("%d %s", i, (const char*)glGetStringi (GL_EXTENSIONS, i)); + } +} diff --git a/src/lib_SDL_Log.cpp b/src/lib_SDL_Log.cpp new file mode 100644 index 0000000..a3a98ca --- /dev/null +++ b/src/lib_SDL_Log.cpp @@ -0,0 +1,24 @@ +#include "lib_SDL_Log.h" +#include "unused.h" + +static struct LogWrapper LogWrapper { }; + +static void +my_SDL_Log (void* userdata, int category, SDL_LogPriority priority, const char* message) +{ + // struct LogWrapper* LogWrapper = (struct LogWrapper*) userdata; + // SDL_assert (NULL != LogWrapper); + UNUSED (userdata); + SDL_LockMutex (LogWrapper.mutex); + LogWrapper.fn (LogWrapper.userdata, category, priority, message); + SDL_UnlockMutex (LogWrapper.mutex); +} + + +void +my_SDL_Log_Init (void) +{ + LogWrapper.mutex = SDL_CreateMutex (); + SDL_LogGetOutputFunction (&LogWrapper.fn, &LogWrapper.userdata); + SDL_LogSetOutputFunction (my_SDL_Log, &LogWrapper); +} diff --git a/src/lib_SDL_common.cpp b/src/lib_SDL_common.cpp index a5244c7..beca651 100644 --- a/src/lib_SDL_common.cpp +++ b/src/lib_SDL_common.cpp @@ -2,6 +2,8 @@ #include "lib_SDL_common.h" #include "unused.h" #include "signal_common.h" +#include "lib_SDL_Log.h" +#include "events_common.h" #include /* exit */ @@ -16,8 +18,8 @@ my_SDL_Linked_Version (const char* lib, const SDL_version* compile_version, cons SDL_assert (NULL != lib); SDL_assert (NULL != compile_version); SDL_assert (NULL != link_version); - SDL_Log (msg, "compiled", lib, compile_version->major, compile_version->minor, compile_version->patch); - SDL_Log (msg, "linked", lib, link_version->major, link_version->minor, link_version->patch); + DEBUG_LOG (msg, "compiled", lib, compile_version->major, compile_version->minor, compile_version->patch); + DEBUG_LOG (msg, "linked", lib, link_version->major, link_version->minor, link_version->patch); } static void @@ -112,7 +114,7 @@ common_SDL_Init (void) { Uint32 Flags; - // common_Signal_Init (); + common_Signal_Init (); Flags = SDL_INIT_EVERYTHING; if (SDL_Init (Flags) < 0) @@ -120,12 +122,25 @@ common_SDL_Init (void) SDL_Log ("SDL_Init: %s", SDL_GetError ()); exit (EXIT_FAILURE); } + + /* TODO SDL_GL_SetAttribute */ + + my_SDL_Log_Init (); + my_SDLNet_Init (); my_IMG_Init (IMG_INIT_JPG | IMG_INIT_PNG); my_TTF_Init (); my_Mix_Init (MIX_INIT_OGG); + SDL_LogSetPriority (SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG); my_SDL_Assert_Init (); + + Flags = SDL_RegisterEvents (SDL_USEREVENT_LAST - SDL_USEREVENT); + if ( (Flags == ((Uint32)-1)) || (Flags != SDL_USEREVENT_FIRST) ) + { + SDL_Log ("SDL_RegisterEvents: %s", SDL_GetError ()); + exit (EXIT_FAILURE); + } } diff --git a/src/quad.cpp b/src/quad.cpp index 956f26f..8f694be 100644 --- a/src/quad.cpp +++ b/src/quad.cpp @@ -13,9 +13,9 @@ Quad::Quad (const GLsizei size) { // positions // texture coords // top right - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // bottom right - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom left -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // top left diff --git a/src/server_main.cpp b/src/server_main.cpp index cad8a72..1df6876 100644 --- a/src/server_main.cpp +++ b/src/server_main.cpp @@ -66,7 +66,7 @@ main (int argc, char **argv) case SDL_QUIT: done = true; break; - case SDL_USEREVENT: + case PACKET_SDL_EVENT: { done = my_SDL_UserEvent (&ev); } @@ -99,7 +99,7 @@ my_SDL_UserEvent (SDL_Event * ev) UDPpacket* packet = (UDPpacket *) ev->user.data1; if (packet) { - SDL_Log ("PACKET_SDL_EVENT"); + // SDL_Log ("PACKET_SDL_EVENT"); my_ProcessPacket (packet); SDLNet_FreePacket (packet); } @@ -286,19 +286,23 @@ static int my_StdinThread(void* param) { std::string buf; UNUSED (param); +_top: while (!done) { - my_ShowPrompt (); try { + my_ShowPrompt (); while (!done && getline (std::cin, buf)) { buf = trim (buf); - if (buf.empty () || my_StdinThread_Helper (buf)) + if (buf.empty ()) + { + goto _top; + } + if (my_StdinThread_Helper (buf)) { done = true; break; } - my_ShowPrompt (); } } catch (std::ifstream::failure& e) { diff --git a/src/shader.cpp b/src/shader.cpp index 4e3c38d..794ac93 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -2,6 +2,13 @@ #include "shader.h" #include "FileIO.h" #include "lib_GL_common.h" +#include "events_common.h" +#include "glCheckErrors.h" +#include "util.h" + +#include /* stat */ +#include /* stat */ +#include /* stat */ #include @@ -13,11 +20,28 @@ #define DEFAULT_FRAGMENT_HEADER "./glsl/header.f.glsl" ShaderProgram::ShaderProgram (const std::string& vertexPath, const std::string& geometryPath, const std::string& fragmentPath) +: mVertexPath (vertexPath) +, mGeometryPath (geometryPath) +, mFragmentPath (fragmentPath) { - GLuint id = Compile3ShaderBuffers (vertexPath, geometryPath, fragmentPath); + SDL_memset (&mMtime, 0, sizeof mMtime); + GLuint id = Compile3ShaderBuffers (mVertexPath, mGeometryPath, mFragmentPath); if (id) { ID = id; + NeedsReloading (true); + StartWatchingShader (); + } +} + + +ShaderProgram::~ShaderProgram (void) +{ + StopWatchingShader (); + if (ID) + { + glDeleteProgram (ID); + ID = 0; } } @@ -31,19 +55,25 @@ ShaderProgram::Use (void) GLint ShaderProgram::getCachedLoc (const std::string& name) { - if (mUniformLocationsNeedRefresh) - RefreshUniformLocations (); + GLint loc; auto const& ref = UniformLocationCache.find (name); + if (ref == UniformLocationCache.end ()) { - /* It didn't exist */ - int loc = glGetUniformLocation (ID, name.c_str ()); - if (loc == -1) + /* It didn't exist, have to get it */ + loc = glGetUniformLocation (ID, name.c_str ()); + if (loc != -1) { + UniformLocationCache[name] = loc; } - UniformLocationCache[name] = loc; } - return UniformLocationCache[name]; + else + { + /* Got cache ref */ + loc = ref->second; + } + + return loc; } @@ -149,7 +179,7 @@ GLuint ShaderProgram::CompileShaderBuffer (const std::string& buf, const GLenum glCompileShader (id); if (!my_checkCompileSuccess (id, type)) { - DEBUG_LOG ("CompileShaderBuffer error"); + SDL_Log ("CompileShaderBuffer error"); id = 0; } } @@ -162,20 +192,34 @@ GLuint ShaderProgram::Compile3ShaderBuffers (const std::string& vertexPath, cons { GLuint vertex, geometry, fragment, id; + glCheckErrors (); id = glCreateProgram (); if (!id) return 0; + glCheckErrors (); vertex = CompileShaderPath (vertexPath, GL_VERTEX_SHADER); + if (!vertex) + { + SDL_Log ("Compile3ShaderBuffers requires vertex shader"); + return 0; + } + glCheckErrors (); geometry = 0; if (!geometryPath.empty ()) geometry = CompileShaderPath (geometryPath, GL_GEOMETRY_SHADER); + glCheckErrors (); FileIO f1 (DEFAULT_FRAGMENT_HEADER, "r"); FileIO f2 (fragmentPath, "r"); std::string buf = f1.ReadToString () + "\n" + f2.ReadToString (); fragment = CompileShaderBuffer (buf, GL_FRAGMENT_SHADER); + if (!fragment) + { + SDL_Log ("Compile3ShaderBuffers requires fragment shader"); + goto _out; + } if (vertex) glAttachShader (id, vertex); @@ -186,20 +230,17 @@ GLuint ShaderProgram::Compile3ShaderBuffers (const std::string& vertexPath, cons glLinkProgram (id); - if (!my_checkCompileSuccess (id, GL_PROGRAM)) - { - throw "glLinkProgram error"; - id = 0; - } - else - { - RefreshUniformLocations (); - } - +_out: glDeleteShader (vertex); glDeleteShader (geometry); glDeleteShader (fragment); + if (!my_checkCompileSuccess (id, GL_PROGRAM)) + { + glDeleteProgram (id); + id = 0; + } + return id; } @@ -223,15 +264,15 @@ ShaderProgram::my_checkCompileSuccess (const GLuint id, const GLenum type) case GL_FRAGMENT_SHADER: typeName = "GL_FRAGMENT_SHADER"; HANDLE_SHADER: - glGetShaderiv (id, GL_COMPILE_STATUS,&success); + glGetShaderiv (id, GL_COMPILE_STATUS, &success); if (GL_FALSE == success) - glGetShaderiv (id, GL_INFO_LOG_LENGTH,&infoLogLength); + glGetShaderiv (id, GL_INFO_LOG_LENGTH, &infoLogLength); break; case GL_PROGRAM: typeName = "PROGRAM"; - glGetProgramiv (id, GL_LINK_STATUS,&success); + glGetProgramiv (id, GL_LINK_STATUS, &success); if (GL_FALSE == success) - glGetProgramiv (id, GL_INFO_LOG_LENGTH,&success); + glGetProgramiv (id, GL_INFO_LOG_LENGTH, &success); break; default: break; @@ -256,7 +297,65 @@ ShaderProgram::my_checkCompileSuccess (const GLuint id, const GLenum type) } if (infoLog[0] != '\0') { - DEBUG_LOG ("%8s ERROR ============================================================\n%s", typeName.c_str (), infoLog.c_str ()); + DEBUG_LOG ("%8s ERROR\n%s", typeName.c_str (), infoLog.c_str ()); } return success; } + + +bool +ShaderProgram::NeedsReloading (bool update) +{ + bool needs = false; + time_t mtime[3]; + struct stat sb; + + SDL_memset (&mtime, 0, sizeof mtime); + + if (!stat (mVertexPath.c_str (), &sb)) mtime[0] = sb.st_mtime; + if (!stat (mGeometryPath.c_str (), &sb)) mtime[1] = sb.st_mtime; + if (!stat (mFragmentPath.c_str (), &sb)) mtime[2] = sb.st_mtime; + + needs = (mMtime[0] < mtime[0]) || (mMtime[1] < mtime[1]) || (mMtime[2] < mtime[2]); + + // SDL_Log ("%ld %ld %ld %ld %ld %ld %d", mMtime[0], mMtime[1], mMtime[2], mtime[0], mtime[1], mtime[2], needs); + + if (update) { + mMtime[0] = mtime[0]; + mMtime[1] = mtime[1]; + mMtime[2] = mtime[2]; + } + + return needs; +} + + +Uint32 ShaderProgram::my_WatchShaderHelper (Uint32 interval, void* param) +{ + SDL_Event event; + ShaderProgram* shader; + + SDL_assert (NULL != param); + shader = (ShaderProgram*) param; + + if (shader->NeedsReloading (false)) + { + SDL_zero (event); + event.type = SHADER_PROGRAM_REFRESH; + SDL_PushEvent (&event); + } + + return interval; +} + + +void ShaderProgram::StartWatchingShader (void) +{ + mShaderWatchTimer = SDL_AddTimer (1000, ShaderProgram::my_WatchShaderHelper, (void *) this); +} + + +void ShaderProgram::StopWatchingShader (void) +{ + SDL_RemoveTimer (mShaderWatchTimer); +} diff --git a/src/signal_common.cpp b/src/signal_common.cpp index c64f80b..872c91e 100644 --- a/src/signal_common.cpp +++ b/src/signal_common.cpp @@ -4,6 +4,7 @@ #include /* fputs */ #include /* struct sigaction */ #include /* exit */ +#include /* strsignal */ #include @@ -20,6 +21,7 @@ my_Signal_Handler (int sig, siginfo_t* si, void* uap) UNUSED (sig); UNUSED (uap); UNUSED (si); + SDL_Log ("Got %s", strsignal (sig)); SDL_PushEvent (&QUIT_EVENT); if (signal_requested++ > 0) { diff --git a/src/util.cpp b/src/util.cpp index d753319..126369c 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -79,9 +79,9 @@ util_UDP_DumpPacket (UDPpacket* packet) if (packet->len > 0) { buf = (const uint8_t*)packet->data; - // if (util_IsProbablyAscii (buf, packet->len)) - // SDL_Log ("data:\n%s\n", buf); - // else + if (util_IsProbablyAscii (buf, packet->len)) + SDL_Log ("data:\n%s\n", buf); + else util_HexDump (buf, packet->len); } else diff --git a/test/test_FileIO.cpp b/test/test_FileIO.cpp index ddcc3fe..d6aed77 100644 --- a/test/test_FileIO.cpp +++ b/test/test_FileIO.cpp @@ -1,13 +1,13 @@ #include "FileIO.h" #include "util.h" +#include +#include + #include /* uint8_t */ #include #include -#include /* errno */ -#include /* strerror */ - int main (int argc, char **argv) { @@ -20,15 +20,15 @@ main (int argc, char **argv) FileIO f (argv[argc], "r"); std::string buf = f.ReadToString (); if (util_IsProbablyAscii (buf.c_str (), buf.size ())) - printf ("%s", buf.c_str ()); + std::cout << buf << std::endl; else util_HexDump (buf.c_str (), buf.size ()); rc = 0; } } - catch (int err) + catch (const std::string& e) { - puts (strerror (errno)); + std::cerr << e << std::endl; } return rc; diff --git a/test/test_lua.cpp b/test/test_lua.cpp index d598c41..e16af03 100644 --- a/test/test_lua.cpp +++ b/test/test_lua.cpp @@ -1,24 +1,57 @@ #include "lib_lua_common.h" +#include "trim.h" -#include +#include +#include +#include -int main(int argc, char** argv) +static const char* prompt_str = "> "; + +static void my_ShowPrompt (void) { - char buf[8192]; + printf ("\n%s", prompt_str); + fflush (stdout); +} + + +int main (int argc, char** argv) +{ + std::string buf; + bool done = false; + lua_State* L; L = luaL_newstate (); luaL_openlibs (L); - while (fgets (buf, 8191, stdin)) + + while (!done) { - if (buf[strlen(buf)-1] == '\n') - buf[strlen(buf)-1] = 0; - if (strlen (buf) > 0) + my_ShowPrompt (); + try { - printf (" => "); - fflush (stdout); - common_lua_run (L, "line", buf, strlen (buf)); + getline (std::cin, buf); } + catch (std::ifstream::failure& e) + { + done = true; + break; + } + if (std::cin.eof ()) + { + done = true; + break; + } + buf = trim (buf); + if (buf.empty ()) + { + std::cin.clear(); + std::cin.ignore(); + continue; + } + printf (" => "); + fflush (stdout); + common_lua_run (L, "line", buf.c_str (), buf.length ()); } + lua_close (L); return 0; }