Browse Source

core: try to merge Ticker and Emcee. Still not very good.

legacy
Sam Hocevar sam 13 years ago
parent
commit
0161879a84
15 changed files with 169 additions and 263 deletions
  1. +1
    -1
      src/Makefile.am
  2. +0
    -2
      src/application/application.cpp
  3. +0
    -1
      src/core.h
  4. +0
    -5
      src/eglapp.cpp
  5. +0
    -82
      src/emcee.cpp
  6. +0
    -41
      src/emcee.h
  7. +2
    -2
      src/entity.cpp
  8. +1
    -0
      src/entity.h
  9. +0
    -2
      src/platform/android/androidapp.cpp
  10. +0
    -3
      src/platform/nacl/nacl_instance.cpp
  11. +0
    -5
      src/platform/nacl/naclapp.cpp
  12. +0
    -5
      src/platform/ps3/ps3app.cpp
  13. +0
    -4
      src/platform/sdl/sdlapp.cpp
  14. +161
    -108
      src/ticker.cpp
  15. +4
    -2
      src/ticker.h

+ 1
- 1
src/Makefile.am View File

@@ -11,7 +11,7 @@ liblol_a_SOURCES = \
text.cpp text.h emitter.cpp emitter.h numeric.h hash.cpp hash.h \
worldentity.cpp worldentity.h gradient.cpp gradient.h half.cpp half.h \
platform.cpp platform.h sprite.cpp sprite.h trig.cpp trig.h \
real.cpp real.h emcee.cpp emcee.h \
real.cpp real.h \
\
lol/unit.h \
\


+ 0
- 2
src/application/application.cpp View File

@@ -59,7 +59,6 @@ class ApplicationData

Application::Application(char const *name, ivec2 resolution, float framerate)
{
Emcee::Setup();
data = new ApplicationData(name, resolution, framerate);
}

@@ -76,7 +75,6 @@ void Application::Run()
Application::~Application()
{
delete data;
Emcee::Shutdown();
}

} /* namespace lol */


+ 0
- 1
src/core.h View File

@@ -103,7 +103,6 @@ static inline int isnan(float f)
#include "application/application.h"

// Managers
#include "emcee.h"
#include "ticker.h"
#include "forge.h"
#include "tiler.h"


+ 0
- 5
src/eglapp.cpp View File

@@ -158,16 +158,11 @@ void EglApp::Run()
{
while (!Ticker::Finished())
{
/* Tick the game */
Ticker::TickGame();

/* Tick the renderer, show the frame and clamp to desired framerate. */
Ticker::TickDraw();
#if defined USE_EGL
eglSwapBuffers(data->egl_dpy, data->egl_surf);
#endif

Ticker::ClampFps();
}
}



+ 0
- 82
src/emcee.cpp View File

@@ -1,82 +0,0 @@
//
// Lol Engine
//
// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://sam.zoy.org/projects/COPYING.WTFPL for more details.
//

#if defined HAVE_CONFIG_H
# include "config.h"
#endif

#include <cstdlib>
#include <stdint.h>

#include "core.h"

namespace lol
{

/*
* Emcee implementation class
*/

static Thread *GameThread, *DrawThread;

static Queue gametick, drawtick;

static void *GameThreadMain(void *data)
{
while (!Ticker::Finished())
for (;;)
{
int tick = gametick.Pop();
if (!tick)
break;

Ticker::TickGame();

drawtick.Push(1);
}

drawtick.Push(0);
}

static void *DrawThreadMain(void *data)
{
for (;;)
{
int tick = drawtick.Pop();
if (!tick)
break;

Ticker::TickDraw();
}
}

void Emcee::Setup()
{
GameThread = new Thread(GameThreadMain, NULL);
DrawThread = new Thread(DrawThreadMain, NULL);
}

void Emcee::Shutdown()
{
}

void Emcee::SetState(Entity *entity, uint32_t state)
{

}

void Emcee::SetStateWhenMatch(Entity *entity, uint32_t state,
Entity *other_entity, uint32_t other_state)
{

}

} /* namespace lol */


+ 0
- 41
src/emcee.h View File

@@ -1,41 +0,0 @@
//
// Lol Engine
//
// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://sam.zoy.org/projects/COPYING.WTFPL for more details.
//

//
// The Emcee class
// ---------------
// The Emcee manages tasks and their dependencies
//

#if !defined __LOL_EMCEE_H__
#define __LOL_EMCEE_H__

#include <stdint.h>

#include "entity.h"

namespace lol
{

class Emcee
{
public:
static void Setup();
static void Shutdown();

static void SetState(Entity *entity, uint32_t state);
static void SetStateWhenMatch(Entity *entity, uint32_t state,
Entity *other_entity, uint32_t other_state);
};

} /* namespace lol */

#endif // __LOL_EMCEE_H__


+ 2
- 2
src/entity.cpp View File

@@ -70,13 +70,13 @@ void Entity::TickDraw(float deltams)

void Entity::SetState(uint32_t state)
{
Emcee::SetState(this, state);
Ticker::SetState(this, state);
}

void Entity::SetStateWhenMatch(uint32_t state,
Entity *other_entity, uint32_t other_state)
{
Emcee::SetStateWhenMatch(this, state, other_entity, other_state);
Ticker::SetStateWhenMatch(this, state, other_entity, other_state);
}

} /* namespace lol */


+ 1
- 0
src/entity.h View File

@@ -29,6 +29,7 @@ class Entity
friend class Ticker;
friend class TickerData;
friend class Dict;
friend class Emcee;

protected:
Entity();


+ 0
- 2
src/platform/android/androidapp.cpp View File

@@ -96,8 +96,6 @@ Java_org_zoy_LolEngine_LolView_nativeMove(JNIEnv* env, jobject thiz,
extern "C" void
Java_org_zoy_LolEngine_LolRenderer_nativeRender(JNIEnv* env)
{
Ticker::ClampFps();
Ticker::TickGame();
Ticker::TickDraw();
}


+ 0
- 3
src/platform/nacl/nacl_instance.cpp View File

@@ -126,9 +126,6 @@ void NaClInstance::DrawSelf()
if (opengl_context_ == NULL)
return;

Ticker::ClampFps();
Ticker::TickGame();

opengl_context_->MakeContextCurrent(this);
Ticker::TickDraw();
opengl_context_->FlushContext();


+ 0
- 5
src/platform/nacl/naclapp.cpp View File

@@ -58,16 +58,11 @@ void NaClApp::Run()
{
while (!Ticker::Finished())
{
/* Tick the game */
Ticker::TickGame();

/* Tick the renderer, show the frame and clamp to desired framerate. */
Ticker::TickDraw();

#if defined __native_client__
#endif

Ticker::ClampFps();
}
}



+ 0
- 5
src/platform/ps3/ps3app.cpp View File

@@ -118,9 +118,6 @@ void Ps3App::Run()
{
while (!Ticker::Finished())
{
/* Tick the game */
Ticker::TickGame();

/* Tick the renderer, show the frame and clamp to desired framerate. */
Ticker::TickDraw();

@@ -130,8 +127,6 @@ void Ps3App::Run()
/* Check if exit callback was called */
cellSysutilCheckCallback();
#endif

Ticker::ClampFps();
}
}



+ 0
- 4
src/platform/sdl/sdlapp.cpp View File

@@ -84,15 +84,11 @@ void SdlApp::Run()
{
while (!Ticker::Finished())
{
/* Tick the game */
Ticker::TickGame();

/* Tick the renderer, show the frame and clamp to desired framerate. */
Ticker::TickDraw();
#if defined USE_SDL
SDL_GL_SwapBuffers();
#endif
Ticker::ClampFps();
}
}



+ 161
- 108
src/ticker.cpp View File

@@ -67,6 +67,12 @@ private:
Timer timer;
float deltams, bias, fps;

/* Background threads */
static void *GameThreadMain(void *p);
static void *DrawThreadMain(void *p); /* unused */
Thread *gamethread, *drawthread;
Queue gametick, drawtick;

/* Shutdown management */
int quit, quitframe, quitdelay, panic;
}
@@ -141,145 +147,188 @@ int Ticker::Unref(Entity *entity)
return --entity->ref;
}

void Ticker::Setup(float fps)
void *TickerData::GameThreadMain(void *p)
{
data->fps = fps;
}
for (;;)
{
int tick = data->gametick.Pop();
if (!tick)
break;

void Ticker::TickGame()
{
Profiler::Stop(Profiler::STAT_TICK_FRAME);
Profiler::Start(Profiler::STAT_TICK_FRAME);
Profiler::Stop(Profiler::STAT_TICK_FRAME);
Profiler::Start(Profiler::STAT_TICK_FRAME);

Profiler::Start(Profiler::STAT_TICK_GAME);
Profiler::Start(Profiler::STAT_TICK_GAME);

#if 0
Log::Debug("-------------------------------------\n");
for (int i = 0; i < Entity::ALLGROUP_END; i++)
{
Log::Debug("%s Group %i\n",
(i < Entity::GAMEGROUP_END) ? "Game" : "Draw", i);

for (Entity *e = data->list[i]; e; )
Log::Debug("-------------------------------------\n");
for (int i = 0; i < Entity::ALLGROUP_END; i++)
{
Log::Debug(" \\-- %s (ref %i, destroy %i)\n", e->GetName(), e->ref, e->destroy);
e = (i < Entity::GAMEGROUP_END) ? e->gamenext : e->drawnext;
Log::Debug("%s Group %i\n",
(i < Entity::GAMEGROUP_END) ? "Game" : "Draw", i);

for (Entity *e = data->list[i]; e; )
{
Log::Debug(" \\-- %s (ref %i, destroy %i)\n", e->GetName(), e->ref, e->destroy);
e = (i < Entity::GAMEGROUP_END) ? e->gamenext : e->drawnext;
}
}
}
#endif

data->frame++;
data->frame++;

/* If recording with fixed framerate, set deltams to a fixed value */
if (data->recording && data->fps)
{
data->deltams = 1000.0f / data->fps;
}
else
{
data->deltams = data->timer.GetMs();
data->bias += data->deltams;
}
/* If recording with fixed framerate, set deltams to a fixed value */
if (data->recording && data->fps)
{
data->deltams = 1000.0f / data->fps;
}
else
{
data->deltams = data->timer.GetMs();
data->bias += data->deltams;
}

/* If shutdown is stuck, kick the first entity we meet and see
* whether it makes things better. Note that it is always a bug to
* have referenced entities after 20 frames, but at least this
* safeguard makes it possible to exit the program cleanly. */
if (data->quit && !((data->frame - data->quitframe) % data->quitdelay))
{
int n = 0;
data->panic = 2 * (data->panic + 1);
/* If shutdown is stuck, kick the first entity we meet and see
* whether it makes things better. Note that it is always a bug to
* have referenced entities after 20 frames, but at least this
* safeguard makes it possible to exit the program cleanly. */
if (data->quit && !((data->frame - data->quitframe) % data->quitdelay))
{
int n = 0;
data->panic = 2 * (data->panic + 1);

for (int i = 0; i < Entity::ALLGROUP_END && n < data->panic; i++)
for (Entity *e = data->list[i]; e && n < data->panic; e = e->gamenext)
if (e->ref)
{
for (int i = 0; i < Entity::ALLGROUP_END && n < data->panic; i++)
for (Entity *e = data->list[i]; e && n < data->panic; e = e->gamenext)
if (e->ref)
{
#if !LOL_RELEASE
Log::Error("poking %s\n", e->GetName());
Log::Error("poking %s\n", e->GetName());
#endif
e->ref--;
n++;
}
e->ref--;
n++;
}

#if !LOL_RELEASE
if (n)
Log::Error("%i entities stuck after %i frames, poked %i\n",
data->nentities, data->quitdelay, n);
if (n)
Log::Error("%i entities stuck after %i frames, poked %i\n",
data->nentities, data->quitdelay, n);
#endif

data->quitdelay = data->quitdelay > 1 ? data->quitdelay / 2 : 1;
}
data->quitdelay = data->quitdelay > 1 ? data->quitdelay / 2 : 1;
}

/* Garbage collect objects that can be destroyed. We can do this
* before inserting awaiting objects, because only objects already in
* the tick lists can be marked for destruction. */
for (int i = 0; i < Entity::ALLGROUP_END; i++)
for (Entity *e = data->list[i], *prev = NULL; e; )
{
if (e->destroy && i < Entity::GAMEGROUP_END)
/* Garbage collect objects that can be destroyed. We can do this
* before inserting awaiting objects, because only objects already
* inthe tick lists can be marked for destruction. */
for (int i = 0; i < Entity::ALLGROUP_END; i++)
for (Entity *e = data->list[i], *prev = NULL; e; )
{
/* If entity is to be destroyed, remove it from the
* game tick list. */
(prev ? prev->gamenext : data->list[i]) = e->gamenext;

e = e->gamenext;
if (e->destroy && i < Entity::GAMEGROUP_END)
{
/* If entity is to be destroyed, remove it from the
* game tick list. */
(prev ? prev->gamenext : data->list[i]) = e->gamenext;

e = e->gamenext;
}
else if (e->destroy)
{
/* If entity is to be destroyed, remove it from the
* draw tick list and destroy it. */
(prev ? prev->drawnext : data->list[i]) = e->drawnext;

Entity *tmp = e;
e = e->drawnext; /* Can only be in a draw group list */
delete tmp;

data->nentities--;
}
else
{
if (e->ref <= 0 && i >= Entity::DRAWGROUP_BEGIN)
e->destroy = 1;
prev = e;
e = (i < Entity::GAMEGROUP_END) ? e->gamenext : e->drawnext;
}
}
else if (e->destroy)
{
/* If entity is to be destroyed, remove it from the
* draw tick list and destroy it. */
(prev ? prev->drawnext : data->list[i]) = e->drawnext;

Entity *tmp = e;
e = e->drawnext; /* Can only be in a draw group list */
delete tmp;
/* Insert waiting objects into the appropriate lists */
while (data->todolist)
{
Entity *e = data->todolist;
data->todolist = e->gamenext;

data->nentities--;
}
else
{
if (e->ref <= 0 && i >= Entity::DRAWGROUP_BEGIN)
e->destroy = 1;
prev = e;
e = (i < Entity::GAMEGROUP_END) ? e->gamenext : e->drawnext;
}
e->gamenext = data->list[e->gamegroup];
data->list[e->gamegroup] = e;
e->drawnext = data->list[e->drawgroup];
data->list[e->drawgroup] = e;
}

/* Insert waiting objects into the appropriate lists */
while (data->todolist)
{
Entity *e = data->todolist;
data->todolist = e->gamenext;

e->gamenext = data->list[e->gamegroup];
data->list[e->gamegroup] = e;
e->drawnext = data->list[e->drawgroup];
data->list[e->drawgroup] = e;
}

/* Tick objects for the game loop */
for (int i = Entity::GAMEGROUP_BEGIN; i < Entity::GAMEGROUP_END; i++)
for (Entity *e = data->list[i]; e; e = e->gamenext)
if (!e->destroy)
{
/* Tick objects for the game loop */
for (int i = Entity::GAMEGROUP_BEGIN; i < Entity::GAMEGROUP_END; i++)
for (Entity *e = data->list[i]; e; e = e->gamenext)
if (!e->destroy)
{
#if !LOL_RELEASE
if (e->state != Entity::STATE_IDLE)
Log::Error("entity not idle for game tick\n");
e->state = Entity::STATE_PRETICK_GAME;
if (e->state != Entity::STATE_IDLE)
Log::Error("entity not idle for game tick\n");
e->state = Entity::STATE_PRETICK_GAME;
#endif
e->TickGame(data->deltams);
e->TickGame(data->deltams);
#if !LOL_RELEASE
if (e->state != Entity::STATE_POSTTICK_GAME)
Log::Error("entity missed super game tick\n");
e->state = Entity::STATE_IDLE;
if (e->state != Entity::STATE_POSTTICK_GAME)
Log::Error("entity missed super game tick\n");
e->state = Entity::STATE_IDLE;
#endif
}
}

Profiler::Stop(Profiler::STAT_TICK_GAME);

data->drawtick.Push(1);
}

data->drawtick.Push(0);

return NULL;
}

void *TickerData::DrawThreadMain(void *p)
{
for (;;)
{
int tick = data->drawtick.Pop();
if (!tick)
break;

data->gametick.Push(1);
}

Profiler::Stop(Profiler::STAT_TICK_GAME);
return NULL;
}

void Ticker::SetState(Entity *entity, uint32_t state)
{

}

void Ticker::SetStateWhenMatch(Entity *entity, uint32_t state,
Entity *other_entity, uint32_t other_state)
{

}

void Ticker::Setup(float fps)
{
data->fps = fps;

data->gamethread = new Thread(TickerData::GameThreadMain, NULL);
data->gametick.Push(1);
}

void Ticker::TickDraw()
{
data->drawtick.Pop();

Profiler::Start(Profiler::STAT_TICK_DRAW);

Video::Clear();
@@ -322,10 +371,11 @@ void Ticker::TickDraw()

Profiler::Stop(Profiler::STAT_TICK_DRAW);
Profiler::Start(Profiler::STAT_TICK_BLIT);
}

void Ticker::ClampFps()
{
/* Signal game thread that it can carry on */
data->gametick.Push(1);

/* Clamp FPS */
Profiler::Stop(Profiler::STAT_TICK_BLIT);

/* If framerate is fixed, force wait time to 1/FPS. Otherwise, set wait
@@ -368,6 +418,9 @@ void Ticker::Shutdown()

data->quit = 1;
data->quitframe = data->frame;

data->gametick.Push(0);
delete data->gamethread;
}

int Ticker::Finished()


+ 4
- 2
src/ticker.h View File

@@ -32,15 +32,17 @@ public:
static int Unref(Entity *entity);

static void Setup(float fps);
static void TickGame();
static void TickDraw();
static void ClampFps();
static void StartBenchmark();
static void StopBenchmark();
static void StartRecording();
static void StopRecording();
static int GetFrameNum();

static void SetState(Entity *entity, uint32_t state);
static void SetStateWhenMatch(Entity *entity, uint32_t state,
Entity *other_entity, uint32_t other_state);

static void Shutdown();
static int Finished();
};


Loading…
Cancel
Save