Skip to content

Commit

Permalink
Refactor: LegacyCore now controls the game loop frequency
Browse files Browse the repository at this point in the history
  • Loading branch information
skyjake committed Mar 15, 2012
1 parent 5296df1 commit e6809ae
Show file tree
Hide file tree
Showing 12 changed files with 61 additions and 32 deletions.
6 changes: 3 additions & 3 deletions doomsday/engine/portable/include/canvas.h
Expand Up @@ -47,7 +47,7 @@ class Canvas : public QGLWidget
*
* @param canvasInitializeFunc Callback.
*/
void setInitCallback(void (*canvasInitializeFunc)(Canvas&));
void setInitFunc(void (*canvasInitializeFunc)(Canvas&));

/**
* Sets a callback function that is responsible for drawing the canvas
Expand All @@ -56,14 +56,14 @@ class Canvas : public QGLWidget
*
* @param canvasDrawFunc Callback.
*/
void setDrawCallback(void (*canvasDrawFunc)(Canvas&));
void setDrawFunc(void (*canvasDrawFunc)(Canvas&));

/**
* Sets a callback function that gets called after the size of the canvas changes.
*
* @param canvasResizedFunc Callback.
*/
void setResizedCallback(void (*canvasResizedFunc)(Canvas&));
void setResizedFunc(void (*canvasResizedFunc)(Canvas&));

/**
* Forces immediate repainting of the canvas. The draw callback gets called.
Expand Down
2 changes: 1 addition & 1 deletion doomsday/engine/portable/include/window.h
Expand Up @@ -217,7 +217,7 @@ boolean Window_ChangeAttributes(Window* wnd, int* attribs);
* @param win Window instance.
* @param drawFunc Callback function.
*/
void Window_SetDrawFunction(Window* win, void (*drawFunc)(void));
void Window_SetDrawFunc(Window* win, void (*drawFunc)(void));

/**
* Request drawing the contents of the window as soon as possible.
Expand Down
6 changes: 3 additions & 3 deletions doomsday/engine/portable/src/canvas.cpp
Expand Up @@ -89,17 +89,17 @@ Canvas::~Canvas()
delete d;
}

void Canvas::setInitCallback(void (*canvasInitializeFunc)(Canvas&))
void Canvas::setInitFunc(void (*canvasInitializeFunc)(Canvas&))
{
d->initCallback = canvasInitializeFunc;
}

void Canvas::setDrawCallback(void (*canvasDrawFunc)(Canvas&))
void Canvas::setDrawFunc(void (*canvasDrawFunc)(Canvas&))
{
d->drawCallback = canvasDrawFunc;
}

void Canvas::setResizedCallback(void (*canvasResizedFunc)(Canvas&))
void Canvas::setResizedFunc(void (*canvasResizedFunc)(Canvas&))
{
d->resizedCallback = canvasResizedFunc;
}
Expand Down
6 changes: 3 additions & 3 deletions doomsday/engine/portable/src/con_busy.c
Expand Up @@ -191,7 +191,7 @@ int Con_Busy2(BusyTask* task)
DD_ResetTimer();

// Resume drawing with the game loop drawer.
Window_SetDrawFunction(Window_Main(), !Sys_IsShuttingDown()? DD_GameLoopDrawer : 0);
Window_SetDrawFunc(Window_Main(), !Sys_IsShuttingDown()? DD_GameLoopDrawer : 0);

return result;
}
Expand Down Expand Up @@ -436,7 +436,7 @@ static void Con_BusyLoop(void)
glLoadIdentity();
glOrtho(0, Window_Width(theWindow), Window_Height(theWindow), 0, -1, 1);

Window_SetDrawFunction(Window_Main(), Con_BusyDrawer);
Window_SetDrawFunc(Window_Main(), Con_BusyDrawer);
}

Sys_Lock(busy_Mutex);
Expand Down Expand Up @@ -492,7 +492,7 @@ static void Con_BusyLoop(void)
glPopMatrix();

// Must not call the busy drawer outside of this loop.
Window_SetDrawFunction(Window_Main(), 0);
Window_SetDrawFunc(Window_Main(), 0);
}
}

Expand Down
15 changes: 12 additions & 3 deletions doomsday/engine/portable/src/dd_init.cpp
Expand Up @@ -49,6 +49,16 @@ LegacyCore* de2LegacyCore;

}

static void continueInitWithEventLoopRunning(void)
{
// This function only needs to be called once, so clear the callback.
LegacyCore_SetLoopFunc(de2LegacyCore, 0);

// Show the main window. This causes initialization to finish (in busy mode)
// as the canvas is visible and ready for initialization.
Window_Show(Window_Main(), true);
}

/**
* Application entry point.
*/
Expand Down Expand Up @@ -93,10 +103,9 @@ int main(int argc, char** argv)
// Create the main window.
char title[256];
DD_ComposeMainWindowTitle(title);
Window* win = Window_New(novideo? WT_CONSOLE : WT_NORMAL, title);
Window_New(novideo? WT_CONSOLE : WT_NORMAL, title);

// Show the main window. This also causes initialization to finish.
Window_Show(win, true);
LegacyCore_SetLoopFunc(de2LegacyCore, continueInitWithEventLoopRunning);

// Run the main loop.
int result = DD_GameLoop();
Expand Down
9 changes: 1 addition & 8 deletions doomsday/engine/portable/src/dd_loop.c
Expand Up @@ -111,12 +111,6 @@ int DD_GameLoopExitCode(void)

int DD_GameLoop(void)
{
// Limit the frame rate to 35 when running in dedicated mode.
if(isDedicated)
{
maxFrameRate = 35;
}

// Start the deng2 event loop.
return LegacyCore_RunEventLoop(de2LegacyCore);
}
Expand All @@ -129,8 +123,7 @@ void DD_GameLoopCallback(void)
// Frame syncronous I/O operations.
startFrame();

// Run at least one tic. If no tics are available (maxfps interval
// not reached yet), the function blocks.
// Run at least one (fractional) tic.
runTics();

// We may have received a Quit message from the windowing system
Expand Down
13 changes: 9 additions & 4 deletions doomsday/engine/portable/src/dd_main.c
Expand Up @@ -1453,18 +1453,18 @@ void DD_FinishInitializationAfterWindowReady(void)
Window_SetTitle(theWindow, buf);
}

// Now we can start executing the engine's main loop.
LegacyCore_SetLoopFunc(de2LegacyCore, DD_GameLoopCallback);

// Initialize engine subsystems and initial state.
if(!DD_Init())
{
exit(2); // Cannot continue...
return;
}

// Now we can start executing the engine's main loop.
LegacyCore_SetLoopFunc(de2LegacyCore, DD_GameLoopCallback);

// Start drawing with the game loop drawer.
Window_SetDrawFunction(Window_Main(), DD_GameLoopDrawer);
Window_SetDrawFunc(Window_Main(), DD_GameLoopDrawer);
}

/**
Expand Down Expand Up @@ -1850,8 +1850,13 @@ static int DD_StartupWorker(void* parm)
// In dedicated mode the console must be opened, so all input events
// will be handled by it.
if(isDedicated)
{
Con_Open(true);

// Also make sure the game loop isn't running needlessly often.
LegacyCore_SetLoopRate(de2LegacyCore, 35);
}

Con_SetProgress(199);

DD_CallHooks(HOOK_INIT, 0, 0); // Any initialization hooks?
Expand Down
8 changes: 4 additions & 4 deletions doomsday/engine/portable/src/window.cpp
Expand Up @@ -771,9 +771,9 @@ static Window* createWindow(ddwindowtype_t type, const char* title)
mainWindow.widget->setMinimumSize(QSize(WINDOW_MIN_WIDTH, WINDOW_MIN_HEIGHT));

// After the main window is created, we can finish with the engine init.
mainWindow.widget->canvas().setInitCallback(finishMainWindowInit);
mainWindow.widget->canvas().setInitFunc(finishMainWindowInit);

mainWindow.widget->canvas().setResizedCallback(windowWasResized);
mainWindow.widget->canvas().setResizedFunc(windowWasResized);

// Let's see if there are command line options overriding the previous state.
mainWindow.modifyAccordingToOptions();
Expand Down Expand Up @@ -986,15 +986,15 @@ HWND Sys_GetWindowHandle(uint idx)

#endif

void Window_SetDrawFunction(Window* win, void (*drawFunc)(void))
void Window_SetDrawFunc(Window* win, void (*drawFunc)(void))
{
if(win->type == WT_CONSOLE) return;

assert(win);
assert(win->widget);

win->drawFunc = drawFunc;
win->widget->canvas().setDrawCallback(drawFunc? drawCanvasWithCallback : 0);
win->widget->canvas().setDrawFunc(drawFunc? drawCanvasWithCallback : 0);
}

void Window_Draw(Window* win)
Expand Down
1 change: 1 addition & 0 deletions doomsday/libdeng2/include/de/c_wrapper.h
Expand Up @@ -41,6 +41,7 @@ extern "C" {
DENG2_OPAQUE(LegacyCore)

DENG2_PUBLIC LegacyCore* LegacyCore_New(void* dengApp);
DENG2_PUBLIC void LegacyCore_SetLoopRate(LegacyCore* lc, int freqHz);
DENG2_PUBLIC void LegacyCore_SetLoopFunc(LegacyCore* lc, void (*callback)(void));
DENG2_PUBLIC int LegacyCore_RunEventLoop(LegacyCore* lc);
DENG2_PUBLIC void LegacyCore_Stop(LegacyCore* lc, int exitCode);
Expand Down
9 changes: 9 additions & 0 deletions doomsday/libdeng2/include/de/legacy/legacycore.h
Expand Up @@ -55,6 +55,15 @@ class LegacyCore : public QObject
*/
int runEventLoop();

/**
* Sets the frequency for calling the loop function (e.g., 35 Hz for a
* dedicated server). Not very accurate: the actual rate at which the
* function is called is probably less.
*
* @param freqHz Frequency in Hz.
*/
void setLoopRate(int freqHz);

/**
* Sets the callback function that gets called periodically from the main
* loop. The calls are made as often as possible without blocking the loop.
Expand Down
6 changes: 6 additions & 0 deletions doomsday/libdeng2/src/c_wrapper.cpp
Expand Up @@ -38,6 +38,12 @@ int LegacyCore_RunEventLoop(LegacyCore* lc)
return self->runEventLoop();
}

void LegacyCore_SetLoopRate(LegacyCore* lc, int freqHz)
{
DENG2_SELF(LegacyCore, lc);
self->setLoopRate(freqHz);
}

void LegacyCore_SetLoopFunc(LegacyCore* lc, void (*callback)(void))
{
DENG2_SELF(LegacyCore, lc);
Expand Down
12 changes: 9 additions & 3 deletions doomsday/libdeng2/src/legacy/legacycore.cpp
Expand Up @@ -37,8 +37,9 @@ struct LegacyCore::Instance
LegacyNetwork network;
void (*loopFunc)(void);
LogBuffer logBuffer;
int loopInterval;

Instance() : app(0), loopFunc(0) {}
Instance() : app(0), loopFunc(0), loopInterval(1) {}
~Instance() {}
};

Expand Down Expand Up @@ -82,7 +83,7 @@ void LegacyCore::setLoopFunc(void (*func)(void))
if(func)
{
// Start the periodic callback calls.
QTimer::singleShot(1, this, SLOT(callback()));
QTimer::singleShot(d->loopInterval, this, SLOT(callback()));
}
}

Expand All @@ -98,6 +99,11 @@ int LegacyCore::runEventLoop()
return code;
}

void LegacyCore::setLoopRate(int freqHz)
{
d->loopInterval = qMax(1, 1000/freqHz);
}

void LegacyCore::stop(int exitCode)
{
d->app->exit(exitCode);
Expand All @@ -108,6 +114,6 @@ void LegacyCore::callback()
if(d->loopFunc)
{
d->loopFunc();
QTimer::singleShot(1, this, SLOT(callback()));
QTimer::singleShot(d->loopInterval, this, SLOT(callback()));
}
}

0 comments on commit e6809ae

Please sign in to comment.