diff --git a/binding-mri/binding-util.h b/binding-mri/binding-util.h index 8bc4c93..1eb5dd5 100644 --- a/binding-mri/binding-util.h +++ b/binding-mri/binding-util.h @@ -195,17 +195,6 @@ rb_bool_new(bool value) return objectLoad(argc, argv, self, Typ##Type); \ } -#define CLONE_FUNC(Klass) \ - static mrb_value \ - Klass##Clone(mrb_state *mrb, mrb_value self) \ - { \ - Klass *k = getPrivateData(mrb, self); \ - mrb_value dupObj = mrb_obj_clone(mrb, self); \ - Klass *dupK = new Klass(*k); \ - setPrivateData(mrb, dupObj, dupK, Klass##Type); \ - return dupObj; \ - } - #define CLONE_FUN(Klass) \ RB_METHOD(Klass##Clone) \ { \ @@ -217,6 +206,18 @@ rb_bool_new(bool value) return dupObj; \ } +#define INITCOPY_FUN(Klass) \ + RB_METHOD(Klass##InitCopy) \ + { \ + VALUE original; \ + rb_get_args(argc, argv, "o", &original); \ + if (!OBJ_INIT_COPY(self, original)) \ + return self; \ + Klass *k = getPrivateData(original); \ + setPrivateData(self, new Klass(*k), Klass##Type); \ + return self; \ + } + /* If we're not binding a disposable class, * we want to #undef DEF_PROP_CHK_DISP */ #define DEF_PROP_CHK_DISP \ diff --git a/binding-mri/etc-binding.cpp b/binding-mri/etc-binding.cpp index f57e3c7..046a241 100644 --- a/binding-mri/etc-binding.cpp +++ b/binding-mri/etc-binding.cpp @@ -148,9 +148,9 @@ MARSH_LOAD_FUN(Color) MARSH_LOAD_FUN(Tone) MARSH_LOAD_FUN(Rect) -CLONE_FUN(Tone) -CLONE_FUN(Color) -CLONE_FUN(Rect) +INITCOPY_FUN(Tone) +INITCOPY_FUN(Color) +INITCOPY_FUN(Rect) #define INIT_BIND(Klass) \ { \ @@ -159,8 +159,8 @@ CLONE_FUN(Rect) rb_define_class_method(klass, "_load", Klass##Load); \ serializableBindingInit(klass); \ _rb_define_method(klass, "initialize", Klass##Initialize); \ + _rb_define_method(klass, "initialize_copy", Klass##InitCopy); \ _rb_define_method(klass, "set", Klass##Set); \ - _rb_define_method(klass, "clone", Klass##Clone); \ _rb_define_method(klass, "==", Klass##Equal); \ _rb_define_method(klass, "to_s", Klass##Stringify); \ _rb_define_method(klass, "inspect", Klass##Stringify); \ diff --git a/shader/bitmapBlit.frag b/shader/bitmapBlit.frag index 1510e7e..2e75e65 100644 --- a/shader/bitmapBlit.frag +++ b/shader/bitmapBlit.frag @@ -27,7 +27,8 @@ void main() float at = ab*as; resFrag.a = at + ad - ad*at; - resFrag.rgb = as*srcFrag.rgb + (1-at) * ad * dstFrag.rgb; + resFrag.rgb = mix(dstFrag.rgb, srcFrag.rgb, ab*as); + resFrag.rgb = mix(srcFrag.rgb, resFrag.rgb, ad*resFrag.a); gl_FragColor = resFrag; } diff --git a/src/eventthread.cpp b/src/eventthread.cpp index a3f5a56..babf7e0 100644 --- a/src/eventthread.cpp +++ b/src/eventthread.cpp @@ -394,7 +394,7 @@ void EventThread::notifyFrame() static uint64_t freq = SDL_GetPerformanceFrequency(); - double currFPS = (double) freq / diff; + int32_t currFPS = freq / diff; fps.acc += currFPS; ++fps.accDiv; diff --git a/src/eventthread.h b/src/eventthread.h index f81922e..a8016d3 100644 --- a/src/eventthread.h +++ b/src/eventthread.h @@ -99,7 +99,7 @@ private: bool displaying; bool immInitFlag; bool immFiniFlag; - double acc; + uint64_t acc; uint32_t accDiv; } fps; }; diff --git a/src/graphics.cpp b/src/graphics.cpp index 8a7c66c..fd78535 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -38,8 +38,6 @@ #include "SDL_video.h" #include "SDL_timer.h" -#include - struct PingPong { TEXFBO rt[2]; @@ -246,105 +244,32 @@ private: struct FPSLimiter { - uint64_t lastTickCount; + unsigned lastTickCount; + unsigned mspf; /* ms per frame */ - /* ticks per frame */ - int64_t tpf; - - /* Ticks per second */ - const uint64_t tickFreq; - - /* Ticks per milisecond */ - const uint64_t tickFreqMS; - - /* Ticks per nanosecond */ - const double tickFreqNS; - - /* Data for frame timing adjustment */ - struct - { - /* Last tick count */ - uint64_t last; - - /* How far behind/in front we are for ideal frame timing */ - int64_t idealDiff; - - bool resetFlag; - } adj; - - FPSLimiter(uint16_t desiredFPS) - : lastTickCount(SDL_GetPerformanceCounter()), - tickFreq(SDL_GetPerformanceFrequency()), - tickFreqMS(tickFreq / 1000), - tickFreqNS(tickFreq / 1000000000) + FPSLimiter(unsigned desiredFPS) + : lastTickCount(SDL_GetTicks()) { setDesiredFPS(desiredFPS); - - adj.last = SDL_GetPerformanceCounter(); - adj.idealDiff = 0; - adj.resetFlag = false; } - void setDesiredFPS(uint16_t value) + void setDesiredFPS(unsigned value) { - tpf = tickFreq / value; + mspf = 1000 / value; } void delay() { - int64_t tickDelta = SDL_GetPerformanceCounter() - lastTickCount; - int64_t toDelay = tpf - tickDelta; - - /* Compensate for the last delta - * to the ideal timestep */ - toDelay -= adj.idealDiff; + unsigned tmpTicks = SDL_GetTicks(); + unsigned tickDelta = tmpTicks - lastTickCount; + lastTickCount = tmpTicks; + int toDelay = mspf - tickDelta; if (toDelay < 0) toDelay = 0; - delayTicks(toDelay); - - uint64_t now = lastTickCount = SDL_GetPerformanceCounter(); - int64_t diff = now - adj.last; - adj.last = now; - - /* Recalculate our temporal position - * relative to the ideal timestep */ - adj.idealDiff = diff - tpf + adj.idealDiff; - - if (adj.resetFlag) - { - adj.idealDiff = 0; - adj.resetFlag = false; - } - } - - void resetFrameAdjust() - { - adj.resetFlag = true; - } - - /* If we're more than a full frame's worth - * of ticks behind the ideal timestep, - * there's no choice but to skip frame(s) - * to catch up */ - bool frameSkipRequired() const - { - return adj.idealDiff > tpf; - } - -private: - void delayTicks(uint64_t ticks) - { -#ifdef HAVE_NANOSLEEP - struct timespec req; - req.tv_sec = 0; - req.tv_nsec = ticks / tickFreqNS; - while (nanosleep(&req, &req) == -1) - ; -#else - SDL_Delay(ticks / tickFreqMS); -#endif + SDL_Delay(toDelay); + lastTickCount = SDL_GetTicks(); } }; @@ -483,8 +408,8 @@ struct GraphicsPrivate void swapGLBuffer() { - fpsLimiter.delay(); SDL_GL_SwapWindow(threadData->window); + fpsLimiter.delay(); ++frameCount; @@ -546,16 +471,6 @@ void Graphics::update() if (p->frozen) return; - if (p->fpsLimiter.frameSkipRequired()) - { - /* Skip frame */ - p->fpsLimiter.delay(); - ++p->frameCount; - p->threadData->ethread->notifyFrame(); - - return; - } - p->checkResize(); p->redrawScreen(); @@ -652,7 +567,7 @@ void Graphics::transition(int duration, void Graphics::frameReset() { - p->fpsLimiter.resetFrameAdjust(); + } #undef RET_IF_DISP diff --git a/src/sharedstate.cpp b/src/sharedstate.cpp index c79ed3a..d85dd1f 100644 --- a/src/sharedstate.cpp +++ b/src/sharedstate.cpp @@ -92,8 +92,6 @@ struct SharedStatePrivate TEXFBO gpTexFBO; - TEXFBO atlasTex; - Quad gpQuad; unsigned int stampCounter; @@ -145,7 +143,6 @@ struct SharedStatePrivate { TEX::del(globalTex); TEXFBO::fini(gpTexFBO); - TEXFBO::fini(atlasTex); } }; @@ -269,36 +266,6 @@ TEXFBO &SharedState::gpTexFBO(int minW, int minH) return p->gpTexFBO; } -void SharedState::requestAtlasTex(int w, int h, TEXFBO &out) -{ - TEXFBO tex; - - if (w == p->atlasTex.width && h == p->atlasTex.height) - { - tex = p->atlasTex; - p->atlasTex = TEXFBO(); - } - else - { - TEXFBO::init(tex); - TEXFBO::allocEmpty(tex, w, h); - TEXFBO::linkFBO(tex); - } - - out = tex; -} - -void SharedState::releaseAtlasTex(TEXFBO &tex) -{ - /* No point in caching an invalid object */ - if (tex.tex == TEX::ID(0)) - return; - - TEXFBO::fini(p->atlasTex); - - p->atlasTex = tex; -} - void SharedState::checkShutdown() { if (!p->rtData.rqTerm) diff --git a/src/sharedstate.h b/src/sharedstate.h index ecd2ee3..b98c8f0 100644 --- a/src/sharedstate.h +++ b/src/sharedstate.h @@ -123,11 +123,6 @@ struct SharedState Quad &gpQuad(); - /* Basically just a simple "TexPool" - * replacement for Tilemap atlas use */ - void requestAtlasTex(int w, int h, TEXFBO &out); - void releaseAtlasTex(TEXFBO &tex); - /* Checks EventThread's shutdown request flag and if set, * requests the binding to terminate. In this case, this * function will most likely not return */ diff --git a/src/tilemap.cpp b/src/tilemap.cpp index f97a5e9..c9a5d83 100644 --- a/src/tilemap.cpp +++ b/src/tilemap.cpp @@ -440,7 +440,7 @@ struct TilemapPrivate { destroyElements(); - shState->releaseAtlasTex(atlas.gl); + shState->texPool().release(atlas.gl); VAO::del(tiles.vao); VBO::del(tiles.vbo); @@ -607,8 +607,8 @@ struct TilemapPrivate updateAtlasInfo(); /* Aquire atlas tex */ - shState->releaseAtlasTex(atlas.gl); - shState->requestAtlasTex(atlas.size.x, atlas.size.y, atlas.gl); + shState->texPool().release(atlas.gl); + atlas.gl = shState->texPool().request(atlas.size.x, atlas.size.y); atlasDirty = true; }