Uncommitted changes.

Quite a bit going on in here.

- Messing with shaders
- Move ShaderProgram to std::unique_ptr

These are part of efforts to clean up the ShaderProgram class to have a
better interface.

- Working on shell-ing out commands.

This is pointless but getting me in the state of thinking about the
system as a whole - e.g. "stop" at the "prompt" should "stop the
server," so the prompt thread will need to communicate with the main
thread. We already have event signalling in place for this.

- Triangle strip cube

Performance testing reasons. Not being used for now.

- Remove TCP stuff from UDPbase. It only does UDP now.
This commit is contained in:
Bubblegumdrop 2022-01-13 12:15:07 -05:00
parent 2403f060eb
commit dcbd011582
16 changed files with 356 additions and 109 deletions

View File

@ -38,6 +38,7 @@ COMMON_OBJS := \
SERVER_OBJS := \
$(OBJDIR)/src/server_main.o \
$(OBJDIR)/src/Server.o \
$(OBJDIR)/src/Commands.o \
$(COMMON_OBJS)
CLIENT_OBJS := \

View File

@ -2,14 +2,21 @@
/* <https://www.shadertoy.com/new> */
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;
void
mainImage (out vec4 fragColor, in vec2 fragCoord)
{
// Normalized pixel coordinates (from 0 to 1)
// vec2 uv = fragCoord.xy / iResolution.xy;
// Time varying pixel color
vec3 col = 0.5 + 0.5 * cos(iTime + fract (1.5 * (0.5 - uv.xyx) / (0.5 - uv.yxy) + iTime) + vec3(0, 2, 4));
// Texture coordinates
vec2 uv = TexCoords;
// Output to screen
fragColor = vec4(col, 1.0);
// float du = 1.0 / iResolution.y;
// vec2 uv = du * (fragCoord.xy - (0.5 * iResolution.xy));
// Time varying pixel color
vec3 col = 0.5 + 0.5 * cos (iTime + uv.xyx + vec3 (0, 2, 4));
// Output to screen
fragColor = vec4 (col, 1.0);
}

36
include/Commands.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#include <string>
#include <map>
class
Command
{
std::string m_name;
Command (const std::string& name)
: m_name (name)
{
}
};
/*
* Function pointer type that returns true if we should stop processing input,
* false otherwise.
*/
#define COMMANDHELPERFUNC(x) bool x (const std::string&)
typedef COMMANDHELPERFUNC((*CommandHelperFunc));
COMMANDHELPERFUNC(command_Quit);
COMMANDHELPERFUNC(command_Help);
COMMANDHELPERFUNC(command_Echo);
COMMANDHELPERFUNC(command_Shell);
const std::map <const std::string, CommandHelperFunc> CommandFunctionList =
{
{ "quit", command_Quit, },
{ "help", command_Help, },
{ "echo", command_Echo, },
{ "shell", command_Shell, },
};

View File

@ -13,8 +13,6 @@ class Server : public UDPbase
SDL_mutex* mProcessPacketMutex;
SDL_TimerID mFetchPacketsCallbackTimerID;
std::vector<TCPsocket> TCPsocks;
std::vector<UDPsocket> UDPsocks;
SDLNet_SocketSet SocketSet;
UDPpacket** packetV;
lua_State *mLuaState;
@ -31,11 +29,13 @@ class Server : public UDPbase
static Uint32 FetchPacketsCallback (Uint32 interval, void* param);
void ProcessPacketHelper (UDPpacket* packet);
void RunLua (const std::string& buf);
int AllocateApproximateResources (const int nclients);
int Start (void);
int Stop (void);
void CloseAllSockets (void);
int Lock (void)
{
return SDL_LockMutex (mProcessPacketMutex);
@ -44,8 +44,8 @@ class Server : public UDPbase
{
return SDL_UnlockMutex (mProcessPacketMutex);
}
lua_State* getLuaState(void) { return mLuaState; }
TCPsocket getTCPsock (size_t idx) { return TCPsocks.at (idx); }
UDPsocket getUDPsock (size_t idx) { return UDPsocks.at (idx); }
UDPpacket** getPacketV (void) { return packetV; }
SDLNet_SocketSet getSocketSet (void) { return SocketSet; }

View File

@ -1,21 +1,36 @@
#pragma once
#include <string>
#include <vector>
#include <SDL_net.h>
#define DEFAULT_MAX_PACKET_SIZE 250
class UDPbase
{
int mChannel;
IPaddress mIPAddress;
protected:
std::vector<UDPsocket> UDPsocks;
public:
UDPbase (const char* host, const Uint16 port);
UDPbase (const char* host, const Uint16 port, const int channel);
~UDPbase (void);
UDPsocket Open (void);
UDPsocket Open (const Uint16 port);
void Close (UDPsocket sock);
int Bind (UDPsocket sock, const int channel);
void Unbind (UDPsocket sock, const int channel);
int ResolveHost (IPaddress*, const char*, const Uint16);
UDPsocket UDP_Open (void);
UDPsocket UDP_Open (const Uint16 port);
void UDP_Close (UDPsocket sock);
int UDP_Bind (UDPsocket sock, const int channel);
void UDP_Unbind (UDPsocket sock, const int channel);
IPaddress* UDP_GetPeerAddress (UDPsocket sock, const int channel);
void CloseAllSockets (void);
int getChannel (void) const { return mChannel; }
UDPsocket getSocket (const size_t idx) const { return UDPsocks.at (idx); }
std::string toString (void);
IPaddress* GetPeerAddress (UDPsocket sock, const int channel);
};

View File

@ -50,8 +50,11 @@ class UDPpacketVBuffer
}
int Send (UDPsocket sock)
{
int numsent;
numsent = SDLNet_UDP_SendV (sock, packetV, npackets);
int numsent = 0;
if (packetV)
{
numsent = SDLNet_UDP_SendV (sock, packetV, npackets);
}
return numsent;
}
};

View File

@ -0,0 +1,12 @@
#include "object.h"
class CubeTriangleStrip : Object
{
public:
CubeTriangleStrip (void)
{
}
CubeTriangleStrip (const GLsizei);
void Draw (void);
};

42
src/Commands.cpp Normal file
View File

@ -0,0 +1,42 @@
#include "Commands.h"
#include "unused.h"
#include <SDL_log.h>
bool command_Quit (const std::string& args)
{
UNUSED (args);
SDL_Log ("byebye!");
return true;
}
bool command_Help (const std::string& args)
{
UNUSED (args);
SDL_Log ("I'm helping!");
return false;
}
bool command_Echo (const std::string& args)
{
SDL_Log ("%s", args.c_str ());
return false;
}
bool command_Shell (const std::string& args)
{
int rc;
if (args.empty ())
{
}
else
{
c = system (args.c_str ());
switch (rc)
{
}
}
return false;
}

View File

@ -9,15 +9,15 @@ Server::Server (const char *host, const Uint16 port)
: UDPbase (host, port)
{
UDPsocket sock;
if (NULL != (sock = Open (port)))
if (NULL != (sock = UDP_Open (port)))
{
Bind (sock, -1);
UDPsocks.push_back (sock);
UDP_Bind (sock, -1);
}
SocketSet = NULL;
mFetchPacketsCallbackTimerID = 0;
mLuaState = NULL;
packetV = NULL;
mProcessPacketMutex = SDL_CreateMutex ();
packetV = NULL;
SocketSet = NULL;
}
@ -25,8 +25,6 @@ Server::~Server (void)
{
Stop ();
CloseAllSockets ();
if (packetV)
{
SDLNet_FreePacketV (packetV);
@ -41,21 +39,6 @@ Server::~Server (void)
}
void
Server::CloseAllSockets (void)
{
size_t i, n;
n = TCPsocks.size ();
for (i = 0; i < n; i++)
SDLNet_TCP_Close (TCPsocks[i]);
TCPsocks.clear ();
n = UDPsocks.size ();
for (i = 0; i < n; i++)
SDLNet_UDP_Close (UDPsocks[i]);
UDPsocks.clear ();
}
int
Server::AllocateApproximateResources (const int nclients)
{
@ -150,6 +133,7 @@ Server::Stop (void)
}
SDL_RemoveTimer (mFetchPacketsCallbackTimerID);
mFetchPacketsCallbackTimerID = 0;
if (mLuaState)
{
@ -164,11 +148,6 @@ Server::Stop (void)
{
SDLNet_UDP_DelSocket (SocketSet, UDPsocks[i]);
}
nclients = TCPsocks.size ();
for (i = 0; i < nclients; i++)
{
SDLNet_TCP_DelSocket (SocketSet, TCPsocks[i]);
}
SDLNet_FreeSocketSet (SocketSet);
SocketSet = NULL;
@ -217,14 +196,27 @@ Uint32 Server::FetchPacketsCallback (Uint32 interval, void *param)
SDL_assert (NULL != param);
server = (Server *) param;
/*
* Need to have some kind of "thread enabled" condition before the Lock().
* Checking the timer ID is sufficient for now.
*/
if (!server->mFetchPacketsCallbackTimerID)
{
return 0;
}
if (server->Lock () < 0)
{
DEBUG_LOG ("Lock failed");
return 0;
}
/* TODO Make this interruptable */
numready = SDLNet_CheckSockets (server->getSocketSet (), 1);
/*
* TODO fix this wait timeout blocking issue
*
* I want this to block, but also to be stoppable.
*/
numready = SDLNet_CheckSockets (server->getSocketSet (), (1000 * DEFAULT_SOCKET_TIMEOUT / 3) / 1000);
if (numready < 0)
{
DEBUG_LOG ("SDLNet_CheckSockets: %s", SDLNet_GetError ());

View File

@ -2,55 +2,83 @@
UDPbase::UDPbase (const char* host, const Uint16 port)
{
if (SDLNet_ResolveHost (&mIPAddress, host, port) < 0)
if (ResolveHost (&mIPAddress, host, port) < 0)
{
throw "SDLNet_ResolveHost: " + std::string (SDLNet_GetError ());
throw "ResolveHost failed";
}
mChannel = -1;
}
/*
* Shortcut for clients who want to open a single channel
* The channel will be available in client->getChannel ()
*/
UDPbase::UDPbase (const char* host, const Uint16 port, const int channel)
{
UDPsocket sock;
if (ResolveHost (&mIPAddress, host, port) < 0)
{
throw "ResolveHost failed";
}
if (NULL == (sock = UDP_Open (0)))
{
throw "Unable to open client port";
}
if (-1 == (mChannel = UDP_Bind (sock, channel)))
{
throw "Unable to bind client port";
}
}
UDPbase::~UDPbase (void)
{
CloseAllSockets ();
}
UDPsocket
UDPbase::Open (void)
int
UDPbase::ResolveHost (IPaddress* addr, const char* host, const Uint16 port)
{
return Open (mIPAddress.port);
int rc;
if ((rc = SDLNet_ResolveHost (addr, host, port)) < 0)
{
throw "SDLNet_ResolveHost: " + std::string (SDLNet_GetError ());
}
return rc;
}
/*
* Open *our* UDP IPaddress->port
*/
UDPsocket
UDPbase::UDP_Open (void)
{
return UDP_Open (mIPAddress.port);
}
UDPsocket
UDPbase::Open (const Uint16 port)
UDPbase::UDP_Open (const Uint16 port)
{
UDPsocket sock = NULL;
if (NULL == (sock = SDLNet_UDP_Open (port)))
{
throw "SDLNet_UDP_Open: " + std::string (SDLNet_GetError ());
}
if (NULL != GetPeerAddress (sock, -1))
if (NULL != UDP_GetPeerAddress (sock, -1))
{
SDL_Log ("Opened UDP port %d", SDLNet_Read16 (&mIPAddress.port));
UDPsocks.push_back (sock);
}
return 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)
UDPbase::UDP_Close (UDPsocket sock)
{
SDL_assert (NULL != sock);
SDLNet_UDP_Close (sock);
@ -59,7 +87,7 @@ UDPbase::Close (UDPsocket sock)
int
UDPbase::Bind (UDPsocket sock, const int channel)
UDPbase::UDP_Bind (UDPsocket sock, const int channel)
{
int binding;
SDL_assert (NULL != sock);
@ -73,12 +101,37 @@ UDPbase::Bind (UDPsocket sock, const int channel)
void
UDPbase::Unbind (UDPsocket sock, const int channel)
UDPbase::UDP_Unbind (UDPsocket sock, const int channel)
{
SDLNet_UDP_Unbind (sock, channel);
}
IPaddress*
UDPbase::UDP_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::CloseAllSockets (void)
{
size_t i, n;
n = UDPsocks.size ();
for (i = 0; i < n; i++)
UDP_Close (UDPsocks.at (i));
UDPsocks.clear ();
}
std::string UDPbase::toString (void)
{
return std::string (SDLNet_ResolveIP (&mIPAddress)) + ":" +

View File

@ -85,8 +85,8 @@ struct Client_State
static std::unique_ptr<Cube> cube;
static std::unique_ptr<Quad> quad;
static std::unique_ptr<UDPbase> client;
static std::unique_ptr<ShaderProgram> shader;
static std::unique_ptr<UDPbase> client;
static Camera camera;
static struct Client_State state;
@ -117,13 +117,13 @@ main (int argc, char** argv)
state.mtu = 1450;
state.done = false;
client = std::make_unique<UDPbase> (state.host, state.port);
if (NULL == (state.udpsock = client->Open (0)))
client = std::make_unique<UDPbase> (state.host, state.port, state.channel);
if (NULL == (state.udpsock = client->getSocket (0)))
{
SDL_Log ("Unable to open client port");
goto _out;
}
if (-1 == (state.channel = client->Bind (state.udpsock, -1)))
if (-1 == (state.channel = client->getChannel ()))
{
SDL_Log ("Unable to bind client port");
goto _out;
@ -162,11 +162,20 @@ main (int argc, char** argv)
shader->Mat4 ("Model", model);
my_Render ();
model = glm::mat4 (1.0f);
model = glm::scale (model, glm::vec3 (10.0f));
shader->Use ();
shader->Mat4 ("Projection", projection);
shader->Mat4 ("View", view);
shader->Mat4 ("Model", model);
cube->Draw ();
SDL_GL_SwapWindow (state.Window);
}
_out:
client->Close (state.udpsock);
client->CloseAllSockets ();
SDL_GL_DeleteContext (state.GLContext);
SDL_DestroyWindow (state.Window);
common_SDL_Quit ();
@ -516,7 +525,7 @@ my_GetOpt (int argc, char** argv)
int opt;
state.host = "localhost";
state.port = 6666;
state.channel = 1;
state.channel = -1;
while ((opt = getopt (argc, argv, "hp:s:")) != -1)
{
switch (opt)

View File

@ -1,7 +1,7 @@
#include "cube.h"
Cube::Cube (const GLsizei size):
Object (size)
Cube::Cube (const GLsizei size)
: Object (size)
{
const float vertices[] =
{

View File

@ -0,0 +1,40 @@
#include "cube_triangle_strip.h"
CubeTriangleStrip::CubeTriangleStrip (const GLsizei size)
: Object (size)
{
static const GLfloat vertices[] =
{
0.5, 0.5, -0.5, // Back-top-right
-0.5, 0.5, -0.5, // Back-top-left
0.5, -0.5, -0.5, // Back-bottom-right
-0.5, -0.5, -0.5, // Back-bottom-left
-0.5, -0.5, 0.5, // Front-bottom-left
-0.5, 0.5, -0.5, // Back-top-left
-0.5, 0.5, 0.5, // Front-top-left
0.5, 0.5, -0.5, // Back-top-right
0.5, 0.5, 0.5, // Front-top-right
0.5, -0.5, -0.5, // Back-bottom-right
0.5, -0.5, 0.5, // Front-bottom-right
-0.5, -0.5, 0.5, // Front-bottom-left
0.5, 0.5, 0.5, // Front-top-right
-0.5, 0.5, 0.5, // Front-top-left
};
glBindVertexArray (VAO);
glBindBuffer (GL_ARRAY_BUFFER, VBO);
glBufferData (GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_STATIC_DRAW);
glBindVertexArray (VAO);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof (float), (void *) 0);
glEnableVertexAttribArray (0);
}
void
CubeTriangleStrip::Draw (void)
{
glBindVertexArray (VAO);
glDrawArrays (GL_TRIANGLE_STRIP, 0, 14);
}

View File

@ -7,12 +7,14 @@
#include "lib_lua_common.h"
#include "util.h"
#include "Server.h"
#include "Commands.h"
#include <iostream>
#include <fstream>
#include <memory>
#include <string>
#include <vector>
#include <map>
#include <stdlib.h> /* exit */
#include <unistd.h> /* getopt */
@ -52,7 +54,8 @@ main (int argc, char **argv)
done = false;
SDL_Thread* stdin_loop = SDL_CreateThread(my_StdinThread, "my_StdinThread", (void*)NULL);
if (NULL == stdin_loop) {
if (NULL == stdin_loop)
{
error ("SDL_CreateThread failed: %s\n", SDL_GetError());
}
@ -78,7 +81,7 @@ main (int argc, char **argv)
}
server->Stop ();
server->CloseAllSockets ();
// server->CloseAllSockets ();
SDL_WaitThread (stdin_loop, NULL);
@ -150,7 +153,8 @@ my_ProcessPacket (UDPpacket* packet)
// SDL_Log ("%d \"%s\"", str.length (), str.c_str ());
/* XXX ultra gross */
if (down) {
if (down)
{
if (str.length () > 1)
{
if (str == "Return")
@ -270,45 +274,72 @@ static void my_ShowPrompt (void)
fflush (stdout);
}
/*
* TODO
* Oh boy this would be our main command handler for the server stdin huh? Wowie!
*/
static bool my_StdinThread_Helper (const std::string& buf)
{
util_HexDump (buf.c_str (), buf.length ());
if (buf == "quit")
std::string argv0 = buf;
std::string args = buf;
auto const& pos = buf.find (' ');
if (pos != std::string::npos)
{
return true;
/* command <args> */
argv0 = buf.substr (0, pos);
argv0 = trim (argv0);
args = buf.substr (pos);
}
// SDL_Log ("\"%s\"", argv0.c_str ());
auto const& ref = CommandFunctionList.find (argv0);
if (ref != CommandFunctionList.end ())
{
/* It was found */
return ref->second (args);
}
SDL_Delay (100);
puts (buf.c_str ());
return false;
}
static int my_StdinThread(void* param)
{
std::string buf;
UNUSED (param);
_top:
_top:
while (!done)
{
try {
my_ShowPrompt ();
while (!done && getline (std::cin, buf))
{
buf = trim (buf);
if (buf.empty ())
{
goto _top;
}
if (my_StdinThread_Helper (buf))
{
done = true;
break;
}
}
my_ShowPrompt ();
try
{
getline (std::cin, buf);
}
catch (std::ifstream::failure& e) {
catch (std::ifstream::failure& e)
{
done = true;
}
if (std::cin.bad () || std::cin.eof ())
{
done = true;
goto _out;
}
buf = trim (buf);
if (buf.empty ())
{
goto _top;
}
if ((done = my_StdinThread_Helper (buf)))
{
goto _out;
}
}
_out:
return 0;
}

View File

@ -1,4 +1,3 @@
#include "debug.h"
#include "shader.h"
#include "FileIO.h"
#include "lib_GL_common.h"
@ -56,8 +55,8 @@ ShaderProgram::Use (void)
GLint ShaderProgram::getCachedLoc (const std::string& name)
{
GLint loc;
auto const& ref = UniformLocationCache.find (name);
auto const& ref = UniformLocationCache.find (name);
if (ref == UniformLocationCache.end ())
{
/* It didn't exist, have to get it */
@ -297,7 +296,7 @@ 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 ());
SDL_Log ("%8s ERROR\n%s", typeName.c_str (), infoLog.c_str ());
}
return success;
}
@ -338,6 +337,11 @@ Uint32 ShaderProgram::my_WatchShaderHelper (Uint32 interval, void* param)
SDL_assert (NULL != param);
shader = (ShaderProgram*) param;
if (!shader->mShaderWatchTimer)
{
return 0;
}
if (shader->NeedsReloading (false))
{
SDL_zero (event);
@ -358,4 +362,5 @@ void ShaderProgram::StartWatchingShader (void)
void ShaderProgram::StopWatchingShader (void)
{
SDL_RemoveTimer (mShaderWatchTimer);
mShaderWatchTimer = 0;
}

View File

@ -48,12 +48,12 @@ main (int argc, char **argv)
common_SDL_Init ();
client = std::make_unique<UDPbase> (host, port);
if (NULL == (udpsock = client->Open (0)))
if (NULL == (udpsock = client->UDP_Open (0)))
{
SDL_Log ("Unable to open client port");
return -1;
}
if (-1 == (channel = client->Bind (udpsock, -1)))
if (-1 == (channel = client->UDP_Bind (udpsock, -1)))
{
SDL_Log ("Unable to bind client port");
return -1;
@ -78,6 +78,7 @@ main (int argc, char **argv)
FileIO f (path, "r");
buf = f.ReadToString ();
}
UDPpacket* packet = SDLNet_AllocPacket (buf.length ());
IPaddress* addr = SDLNet_UDP_GetPeerAddress (udpsock, channel);
packet->len = DEFAULT_MAX_PACKET_SIZE;
@ -86,7 +87,7 @@ main (int argc, char **argv)
UDPpacketVBuffer packetV (packet, &buf[0], buf.length ());
packetV.Send (udpsock);
client->Close (udpsock);
client->CloseAllSockets ();
common_SDL_Quit ();