make dp_doom send out framebuffers via nng
This commit is contained in:
parent
366bf9b75c
commit
236652be35
4 changed files with 304 additions and 9 deletions
|
@ -25,6 +25,7 @@ target_link_libraries(dp_common
|
||||||
PUBLIC nng
|
PUBLIC nng
|
||||||
PUBLIC Threads::Threads
|
PUBLIC Threads::Threads
|
||||||
)
|
)
|
||||||
|
target_include_directories(dp_common INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
add_executable(doompanning doompanning.cc)
|
add_executable(doompanning doompanning.cc)
|
||||||
target_compile_features(doompanning PRIVATE cxx_std_17)
|
target_compile_features(doompanning PRIVATE cxx_std_17)
|
||||||
|
|
|
@ -213,13 +213,18 @@ elseif(BACKEND STREQUAL "SDL2")
|
||||||
target_compile_definitions(dp_doom PRIVATE INCLUDE_SDL2_MAIN)
|
target_compile_definitions(dp_doom PRIVATE INCLUDE_SDL2_MAIN)
|
||||||
elseif(BACKEND STREQUAL "nng")
|
elseif(BACKEND STREQUAL "nng")
|
||||||
target_sources(dp_doom PRIVATE
|
target_sources(dp_doom PRIVATE
|
||||||
"linuxdoom-1.10/ib_sound/sdl.c"
|
#"linuxdoom-1.10/ib_sound/sdl.c"
|
||||||
|
"linuxdoom-1.10/ib_sound/ib_sound_nng.c"
|
||||||
"linuxdoom-1.10/ib_system/ib_system_nng.c"
|
"linuxdoom-1.10/ib_system/ib_system_nng.c"
|
||||||
"linuxdoom-1.10/ib_video/ib_video_nng.c"
|
"linuxdoom-1.10/ib_video/ib_video_nng.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
find_package(SDL2 REQUIRED)
|
find_package(SDL2 REQUIRED)
|
||||||
target_link_libraries(dp_doom PRIVATE SDL2::SDL2 m)
|
target_link_libraries(dp_doom
|
||||||
|
PRIVATE SDL2::SDL2
|
||||||
|
PRIVATE m
|
||||||
|
PRIVATE dp_common
|
||||||
|
)
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "Invalid BACKEND")
|
message(FATAL_ERROR "Invalid BACKEND")
|
||||||
endif()
|
endif()
|
||||||
|
|
22
src/dp_doom/linuxdoom-1.10/ib_sound/ib_sound_nng.c
Normal file
22
src/dp_doom/linuxdoom-1.10/ib_sound/ib_sound_nng.c
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include "../ib_sound.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
int IB_StartupSound(void (*initial_callback)(unsigned int output_sample_rate, void *user_data), void (*_audio_callback)(short* output_buffer, size_t frames_to_do, void *user_data), void *user_data)
|
||||||
|
{
|
||||||
|
unsigned int freq = 48000;
|
||||||
|
initial_callback(freq, user_data);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IB_ShutdownSound(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void IB_LockSound(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void IB_UnlockSound(void)
|
||||||
|
{
|
||||||
|
}
|
|
@ -33,22 +33,179 @@
|
||||||
#include "../v_video.h"
|
#include "../v_video.h"
|
||||||
#include "../m_argv.h"
|
#include "../m_argv.h"
|
||||||
#include "../d_main.h"
|
#include "../d_main.h"
|
||||||
|
|
||||||
#include "../doomdef.h"
|
#include "../doomdef.h"
|
||||||
|
|
||||||
#include "../ib_video.h"
|
#include "../ib_video.h"
|
||||||
|
|
||||||
#define BYTES_PER_PIXEL 3
|
#include <assert.h>
|
||||||
|
#include <nng/nng.h>
|
||||||
|
#include <nng/protocol/pubsub0/pub.h>
|
||||||
|
#include <nng/protocol/pubsub0/sub.h>
|
||||||
|
#include <dp_common.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
//uint8_t frameBuffer[SCREENWIDTH * SCREENHEIGHT * BYTES_PER_PIXEL];
|
typedef struct DoomContext DoomContext;
|
||||||
|
|
||||||
|
#define DEF_DOOM_STATE_FUNC(fn) int fn(DoomContext *ctx)
|
||||||
|
|
||||||
|
typedef DEF_DOOM_STATE_FUNC(DoomStateFunc);
|
||||||
|
|
||||||
|
struct DoomContext
|
||||||
|
{
|
||||||
|
nng_socket pub;
|
||||||
|
nng_socket sub;
|
||||||
|
doomid_t id;
|
||||||
|
DP_DoomState state;
|
||||||
|
DoomStateFunc *f;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int publish_state(DoomContext *ctx)
|
||||||
|
{
|
||||||
|
nng_msg *msg = NULL;
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
if ((res = nng_msg_alloc(&msg, sizeof(MsgDoomState))))
|
||||||
|
dp_nng_fatal("doom/nng_msg_alloc", res);
|
||||||
|
|
||||||
|
MsgDoomState *dmsg = DP_NNG_BODY_AS(msg, MsgDoomState);
|
||||||
|
dmsg->head.msgType = DP_MT_DoomState;
|
||||||
|
dmsg->doomId = ctx->id;
|
||||||
|
dmsg->doomState = ctx->state;
|
||||||
|
|
||||||
|
res = nng_sendmsg(ctx->pub, msg, 0);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEF_DOOM_STATE_FUNC(do_doom_ready);
|
||||||
|
DEF_DOOM_STATE_FUNC(do_doom_running);
|
||||||
|
|
||||||
|
DEF_DOOM_STATE_FUNC(do_doom_ready)
|
||||||
|
{
|
||||||
|
assert(ctx->state == DP_DS_Ready);
|
||||||
|
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
if ((res = publish_state(ctx)))
|
||||||
|
dp_nng_fatal("doom/publish_sate", res);
|
||||||
|
|
||||||
|
nng_msg *msg = NULL;
|
||||||
|
|
||||||
|
if ((res = dp_recv_new_msg_nonblock(ctx->sub, &msg)))
|
||||||
|
{
|
||||||
|
if (!dp_nng_is_timeout(res))
|
||||||
|
dp_nng_fatal("doom/recvmsg", res);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_trace("do_doom_ready received message of size %zu", nng_msg_len(msg));
|
||||||
|
|
||||||
|
MessageBase *msgBase = DP_NNG_BODY_AS(msg, MessageBase);
|
||||||
|
|
||||||
|
DP_DoomCommand cmd = DP_DC_Noop;
|
||||||
|
|
||||||
|
if (msgBase->msgType == DP_MT_Command)
|
||||||
|
{
|
||||||
|
MsgCommand *msgCmd = DP_NNG_BODY_AS(msg, MsgCommand);
|
||||||
|
|
||||||
|
if (msgCmd->doomId == ctx->id)
|
||||||
|
cmd = msgCmd->cmd;
|
||||||
|
}
|
||||||
|
else if (msgBase->msgType == DP_MT_McstCommand)
|
||||||
|
{
|
||||||
|
MsgMcstCommand *msgCmd = DP_NNG_BODY_AS(msg, MsgMcstCommand);
|
||||||
|
cmd = msgCmd->cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == DP_DC_RunDoom)
|
||||||
|
{
|
||||||
|
ctx->state = DP_DS_Running;
|
||||||
|
ctx->f = do_doom_running;
|
||||||
|
|
||||||
|
if ((res = publish_state(ctx)))
|
||||||
|
dp_nng_fatal("doom/publish_sate", res);
|
||||||
|
}
|
||||||
|
else if (cmd == DP_DC_Endoom)
|
||||||
|
{
|
||||||
|
ctx->state = DP_DS_Endoom;
|
||||||
|
|
||||||
|
if ((res = publish_state(ctx)))
|
||||||
|
dp_nng_fatal("doom/publish_sate", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
nng_msg_free(msg);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEF_DOOM_STATE_FUNC(do_doom_running)
|
||||||
|
{
|
||||||
|
|
||||||
|
assert(ctx->state == DP_DS_Running);
|
||||||
|
|
||||||
|
// Non-blocking receive of incoming messages.
|
||||||
|
// Check if we should quit.
|
||||||
|
// Handle incoming input.
|
||||||
|
// Let doom render a new frame.
|
||||||
|
// Publish the frame.
|
||||||
|
|
||||||
|
int res = 0;
|
||||||
|
nng_msg *msg = NULL;
|
||||||
|
|
||||||
|
if ((res = dp_recv_new_msg_nonblock(ctx->sub, &msg)))
|
||||||
|
{
|
||||||
|
if (!dp_nng_is_timeout(res))
|
||||||
|
dp_nng_fatal("doom/recvmsg", res);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_trace("do_doom_running received message of size %zu", nng_msg_len(msg));
|
||||||
|
|
||||||
|
MessageBase *msgBase = DP_NNG_BODY_AS(msg, MessageBase);
|
||||||
|
|
||||||
|
DP_DoomCommand cmd = DP_DC_Noop;
|
||||||
|
|
||||||
|
if (msgBase->msgType == DP_MT_Command)
|
||||||
|
{
|
||||||
|
MsgCommand *msgCmd = DP_NNG_BODY_AS(msg, MsgCommand);
|
||||||
|
|
||||||
|
if (msgCmd->doomId == ctx->id)
|
||||||
|
cmd = msgCmd->cmd;
|
||||||
|
}
|
||||||
|
else if (msgBase->msgType == DP_MT_McstCommand)
|
||||||
|
{
|
||||||
|
MsgMcstCommand *msgCmd = DP_NNG_BODY_AS(msg, MsgMcstCommand);
|
||||||
|
cmd = msgCmd->cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == DP_DC_Endoom)
|
||||||
|
{
|
||||||
|
ctx->state = DP_DS_Endoom;
|
||||||
|
|
||||||
|
if ((res = publish_state(ctx)))
|
||||||
|
dp_nng_fatal("doom/publish_sate", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
nng_msg_free(msg);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t g_frameBufferSize;
|
||||||
static uint8_t *g_frameBuffer;
|
static uint8_t *g_frameBuffer;
|
||||||
static size_t g_pitch;
|
static size_t g_pitch;
|
||||||
|
DoomContext g_doomContext;
|
||||||
|
|
||||||
//
|
//
|
||||||
// IB_StartTic
|
// IB_StartTic
|
||||||
//
|
//
|
||||||
void IB_StartTic (void)
|
void IB_StartTic (void)
|
||||||
{
|
{
|
||||||
|
/* TODO: post input events (could this be done in IB_FinishUpdate? try it)
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
event.type = ev_keydown;
|
||||||
|
event.data1 = xlatekey(sdl_event.key.keysym.sym);
|
||||||
|
D_PostEvent(&event);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void IB_GetFramebuffer(unsigned char **pixels, size_t *pitch)
|
void IB_GetFramebuffer(unsigned char **pixels, size_t *pitch)
|
||||||
|
@ -59,6 +216,71 @@ void IB_GetFramebuffer(unsigned char **pixels, size_t *pitch)
|
||||||
|
|
||||||
void IB_FinishUpdate (void)
|
void IB_FinishUpdate (void)
|
||||||
{
|
{
|
||||||
|
DoomContext *ctx = &g_doomContext;
|
||||||
|
|
||||||
|
assert(ctx->state == DP_DS_Running);
|
||||||
|
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
nng_msg *msg = NULL;
|
||||||
|
|
||||||
|
if ((res = dp_recv_new_msg_nonblock(ctx->sub, &msg)))
|
||||||
|
{
|
||||||
|
if (!dp_nng_is_timeout(res))
|
||||||
|
dp_nng_fatal("doom/recvmsg", res);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageBase *msgBase = DP_NNG_BODY_AS(msg, MessageBase);
|
||||||
|
|
||||||
|
DP_DoomCommand cmd = DP_DC_Noop;
|
||||||
|
|
||||||
|
if (msgBase->msgType == DP_MT_Command)
|
||||||
|
{
|
||||||
|
MsgCommand *msgCmd = DP_NNG_BODY_AS(msg, MsgCommand);
|
||||||
|
|
||||||
|
if (msgCmd->doomId == ctx->id)
|
||||||
|
cmd = msgCmd->cmd;
|
||||||
|
}
|
||||||
|
else if (msgBase->msgType == DP_MT_McstCommand)
|
||||||
|
{
|
||||||
|
MsgMcstCommand *msgCmd = DP_NNG_BODY_AS(msg, MsgMcstCommand);
|
||||||
|
cmd = msgCmd->cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
nng_msg_free(msg);
|
||||||
|
|
||||||
|
if (cmd == DP_DC_Endoom)
|
||||||
|
{
|
||||||
|
ctx->state = DP_DS_Endoom;
|
||||||
|
|
||||||
|
if ((res = publish_state(ctx)))
|
||||||
|
dp_nng_fatal("doom/publish_sate", res);
|
||||||
|
|
||||||
|
I_Quit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
nng_msg *msg = NULL;
|
||||||
|
|
||||||
|
if ((res = nng_msg_alloc(&msg, sizeof(MsgDoomFrame))))
|
||||||
|
dp_nng_fatal("doom/nng_msg_alloc", res);
|
||||||
|
|
||||||
|
MsgDoomFrame *dpmsg = DP_NNG_BODY_AS(msg, MsgDoomFrame);
|
||||||
|
dpmsg->head.msgType = DP_MT_DoomFrame;
|
||||||
|
dpmsg->doomId = ctx->id;
|
||||||
|
assert(g_frameBufferSize == DoomFrameSize);
|
||||||
|
memcpy(dpmsg->frame, g_frameBuffer, g_frameBufferSize);
|
||||||
|
|
||||||
|
if ((res = nng_sendmsg(ctx->pub, msg, 0)))
|
||||||
|
dp_nng_fatal("ctrl/sendmsg", res);
|
||||||
|
|
||||||
|
log_debug("doom(%d) published frame", ctx->id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IB_GetColor(unsigned char *bytes, unsigned char red, unsigned char green, unsigned char blue)
|
void IB_GetColor(unsigned char *bytes, unsigned char red, unsigned char green, unsigned char blue)
|
||||||
|
@ -78,15 +300,60 @@ static void I_Quit_Wrapper(int dummy)
|
||||||
void IB_InitGraphics(const char *title, size_t screen_width, size_t screen_height, size_t *bytes_per_pixel)
|
void IB_InitGraphics(const char *title, size_t screen_width, size_t screen_height, size_t *bytes_per_pixel)
|
||||||
{
|
{
|
||||||
(void) title;
|
(void) title;
|
||||||
g_frameBuffer = malloc(screen_width * screen_height * BYTES_PER_PIXEL);
|
g_frameBufferSize = screen_width * screen_height * DoomBytesPerPixel;
|
||||||
g_pitch = screen_width * BYTES_PER_PIXEL;
|
assert(g_frameBufferSize == DoomFrameSize);
|
||||||
*bytes_per_pixel = BYTES_PER_PIXEL;
|
g_frameBuffer = malloc(g_frameBufferSize);
|
||||||
|
g_pitch = screen_width * DoomBytesPerPixel;
|
||||||
|
*bytes_per_pixel = DoomBytesPerPixel;
|
||||||
|
|
||||||
|
log_debug("IB_InitGraphics: w=%zu, h=%zu -> bytesPerPixel=%zu, frameBufferSize=%zu",
|
||||||
|
screen_width, screen_height, *bytes_per_pixel, g_frameBufferSize);
|
||||||
|
|
||||||
signal(SIGINT, I_Quit_Wrapper);
|
signal(SIGINT, I_Quit_Wrapper);
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
log_set_level(LOG_DEBUG);
|
||||||
|
#else
|
||||||
|
log_set_level(LOG_INFO);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dp_nng_init_limits(1, 1, 1);
|
||||||
|
|
||||||
|
g_doomContext.pub = make_doom_pub(DoomUrl);
|
||||||
|
g_doomContext.sub = make_doom_sub(CtrlUrl);
|
||||||
|
g_doomContext.id = getpid();
|
||||||
|
g_doomContext.state = DP_DS_Ready;
|
||||||
|
g_doomContext.f = do_doom_ready;
|
||||||
|
|
||||||
|
DoomContext *ctx = &g_doomContext;
|
||||||
|
|
||||||
|
log_info("waiting for go from doompanning");
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
DP_DoomState prevState = ctx->state;
|
||||||
|
ctx->f(ctx);
|
||||||
|
if (prevState != ctx->state)
|
||||||
|
{
|
||||||
|
log_info("transition %s -> %s",
|
||||||
|
doomstate_to_string(prevState), doomstate_to_string(ctx->state));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->state != DP_DS_Endoom && ctx->state != DP_DS_Running)
|
||||||
|
usleep(10 * 1000);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->state == DP_DS_Endoom)
|
||||||
|
I_Quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IB_ShutdownGraphics(void)
|
void IB_ShutdownGraphics(void)
|
||||||
{
|
{
|
||||||
|
nng_close(g_doomContext.pub);
|
||||||
|
nng_close(g_doomContext.sub);
|
||||||
|
|
||||||
free(g_frameBuffer);
|
free(g_frameBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue