double __hxcpp_time_stamp() { #ifdef HX_WINDOWS static __int64 t0=0; static double period=0; __int64 now; if (QueryPerformanceCounter((LARGE_INTEGER*)&now)) { if (t0==0) { t0 = now; __int64 freq; QueryPerformanceFrequency((LARGE_INTEGER*)&freq); if (freq!=0) period = 1.0/freq; } if (period!=0) return (now-t0)*period; } return (double)clock() / ( (double)CLOCKS_PER_SEC); #elif defined(HX_MACOS) static double time_scale = 0.0; if (time_scale==0.0) { mach_timebase_info_data_t info; mach_timebase_info(&info); time_scale = 1e-9 * (double)info.numer / info.denom; } double r = mach_absolute_time() * time_scale; return mach_absolute_time() * time_scale; #else #if defined(IPHONE) || defined(APPLETV) double t = CACurrentMediaTime(); #elif defined(USE_GETTIMEOFDAY) struct timeval tv; if( gettimeofday(&tv,NULL) ) return 0; double t = ( tv.tv_sec + ((double)tv.tv_usec) / 1000000.0 ); #elif defined(USE_CLOCK_GETTIME) struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); double t = ( ts.tv_sec + ((double)ts.tv_nsec)*1e-9 ); #else double t = (double)clock() * (1.0 / CLOCKS_PER_SEC); #endif if (t0==0) t0 = t; return t-t0; #endif }
double now() { #if defined(HX_MACOS) static double time_scale = 0.0; if (time_scale == 0.0) { mach_timebase_info_data_t info; mach_timebase_info(&info); time_scale = 1e-9 * (double)info.numer / info.denom; } return mach_absolute_time() * time_scale; #else #if defined(IPHONE) double t = CACurrentMediaTime(); #elif defined(GPH) || defined(HX_LINUX) || defined(EMSCRIPTEN) struct timeval tv; if( gettimeofday(&tv,NULL) ) { return 0; } double t = ( tv.tv_sec + ((double)tv.tv_usec) / 1000000.0 ); #else struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); double t = ( ts.tv_sec + ((double)ts.tv_nsec)*1e-9 ); #endif if (t0 == 0) { t0 = t; } return t - t0; #endif } //now()
static unsigned int Example_GetTicks() { #if defined(__APPLE__) return (unsigned int)((CACurrentMediaTime()-s_ticksBaseTime)*1000.0); #elif defined(_WIN32) LARGE_INTEGER current_time; QueryPerformanceCounter(¤t_time); return (unsigned int)((current_time.QuadPart - s_ticksBaseTime.QuadPart) * 1000 * s_hiResSecondsPerTick); #else /* assuming POSIX */ /* clock_gettime is POSIX.1-2001 */ struct timespec current_time; clock_gettime(CLOCK_MONOTONIC, ¤t_time); return (unsigned int)((current_time.tv_sec - s_ticksBaseTime.tv_sec)*1000.0 + (current_time.tv_nsec - s_ticksBaseTime.tv_nsec) / 1000000); #endif }
static void Example_InitTime() { #if defined(__APPLE__) s_ticksBaseTime = CACurrentMediaTime(); #elif defined(_WIN32) LARGE_INTEGER hi_res_ticks_per_second; if(TRUE == QueryPerformanceFrequency(&hi_res_ticks_per_second)) { QueryPerformanceCounter(&s_ticksBaseTime); s_hiResSecondsPerTick = 1.0 / hi_res_ticks_per_second; } else { fprintf(stderr, "Windows error: High resolution clock failed. Audio will not work correctly.\n"); } #else /* clock_gettime is POSIX.1-2001 */ clock_gettime(CLOCK_MONOTONIC, &s_ticksBaseTime); #endif }
void LegacyCACFLayerTreeHost::render(const Vector<CGRect>& windowDirtyRects) { ASSERT(m_d3dDevice); if (m_mustResetLostDeviceBeforeRendering && !resetDevice(LostDevice)) { // We can't reset the device right now. Try again soon. renderSoon(); return; } CGRect bounds = this->bounds(); // Give the renderer some space to use. This needs to be valid until the // wkCACFContextFinishUpdate() call below. char space[4096]; if (!wkCACFContextBeginUpdate(m_context, space, sizeof(space), CACurrentMediaTime(), bounds, windowDirtyRects.data(), windowDirtyRects.size())) return; HRESULT err = S_OK; CFTimeInterval timeToNextRender = numeric_limits<CFTimeInterval>::infinity(); do { // FIXME: don't need to clear dirty region if layer tree is opaque. WKCACFUpdateRectEnumerator* e = wkCACFContextCopyUpdateRectEnumerator(m_context); if (!e) break; Vector<D3DRECT, 64> rects; for (const CGRect* r = wkCACFUpdateRectEnumeratorNextRect(e); r; r = wkCACFUpdateRectEnumeratorNextRect(e)) { D3DRECT rect; rect.x1 = r->origin.x; rect.x2 = rect.x1 + r->size.width; rect.y1 = bounds.origin.y + bounds.size.height - (r->origin.y + r->size.height); rect.y2 = rect.y1 + r->size.height; rects.append(rect); } wkCACFUpdateRectEnumeratorRelease(e); timeToNextRender = wkCACFContextGetNextUpdateTime(m_context); if (rects.isEmpty()) break; m_d3dDevice->Clear(rects.size(), rects.data(), D3DCLEAR_TARGET, 0, 1.0f, 0); m_d3dDevice->BeginScene(); wkCACFContextRenderUpdate(m_context); m_d3dDevice->EndScene(); err = m_d3dDevice->Present(0, 0, 0, 0); if (err == D3DERR_DEVICELOST) { wkCACFContextAddUpdateRect(m_context, bounds); if (!resetDevice(LostDevice)) { // We can't reset the device right now. Try again soon. renderSoon(); return; } } } while (err == D3DERR_DEVICELOST); wkCACFContextFinishUpdate(m_context); #ifndef NDEBUG if (m_printTree) rootLayer()->printTree(); #endif // If timeToNextRender is not infinity, it means animations are running, so queue up to render again if (timeToNextRender != numeric_limits<CFTimeInterval>::infinity()) renderSoon(); }
void WKCACFLayerRenderer::render(const Vector<CGRect>& dirtyRects) { ASSERT(m_d3dDevice); if (m_mustResetLostDeviceBeforeRendering && !resetDevice(LostDevice)) { // We can't reset the device right now. Try again soon. renderSoon(); return; } if (m_client && !m_client->shouldRender()) { renderSoon(); return; } // Flush the root layer to the render tree. WKCACFContextFlusher::shared().flushAllContexts(); CGRect bounds = this->bounds(); CFTimeInterval t = CACurrentMediaTime(); // Give the renderer some space to use. This needs to be valid until the // CARenderUpdateFinish() call below. char space[4096]; CARenderUpdate* u = CARenderUpdateBegin(space, sizeof(space), t, 0, 0, &bounds); if (!u) return; CARenderContextLock(m_renderContext); CARenderUpdateAddContext(u, m_renderContext); CARenderContextUnlock(m_renderContext); for (size_t i = 0; i < dirtyRects.size(); ++i) CARenderUpdateAddRect(u, &dirtyRects[i]); HRESULT err = S_OK; do { CGSRegionObj rgn = CARenderUpdateCopyRegion(u); if (!rgn) break; // FIXME: don't need to clear dirty region if layer tree is opaque. Vector<D3DRECT, 64> rects; CGSRegionEnumeratorObj e = CGSRegionEnumerator(rgn); for (const CGRect* r = CGSNextRect(e); r; r = CGSNextRect(e)) { D3DRECT rect; rect.x1 = r->origin.x; rect.x2 = rect.x1 + r->size.width; rect.y1 = bounds.origin.y + bounds.size.height - (r->origin.y + r->size.height); rect.y2 = rect.y1 + r->size.height; rects.append(rect); } CGSReleaseRegionEnumerator(e); CGSReleaseRegion(rgn); if (rects.isEmpty()) break; m_d3dDevice->Clear(rects.size(), rects.data(), D3DCLEAR_TARGET, 0, 1.0f, 0); m_d3dDevice->BeginScene(); CARenderOGLRender(m_renderer, u); m_d3dDevice->EndScene(); err = m_d3dDevice->Present(0, 0, 0, 0); if (err == D3DERR_DEVICELOST) { CARenderUpdateAddRect(u, &bounds); if (!resetDevice(LostDevice)) { // We can't reset the device right now. Try again soon. renderSoon(); return; } } } while (err == D3DERR_DEVICELOST); CARenderUpdateFinish(u); #ifndef NDEBUG if (m_printTree) m_rootLayer->printTree(); #endif }
void WKCACFLayerRenderer::render(const Vector<CGRect>& windowDirtyRects) { ASSERT(m_d3dDevice); if (m_mustResetLostDeviceBeforeRendering && !resetDevice(LostDevice)) { // We can't reset the device right now. Try again soon. renderSoon(); return; } if (m_client && !m_client->shouldRender()) { renderSoon(); return; } // Sync the layer if needed if (m_syncLayerChanges) { m_client->syncCompositingState(); m_syncLayerChanges = false; } // Flush the root layer to the render tree. wkCACFContextFlush(m_context); // All pending animations will have been started with the flush. Fire the animationStarted calls double currentTime = WTF::currentTime(); double currentMediaTime = CACurrentMediaTime(); double t = currentTime + wkCACFContextGetLastCommitTime(m_context) - currentMediaTime; ASSERT(t <= currentTime); HashSet<RefPtr<PlatformCALayer> >::iterator end = m_pendingAnimatedLayers.end(); for (HashSet<RefPtr<PlatformCALayer> >::iterator it = m_pendingAnimatedLayers.begin(); it != end; ++it) { PlatformCALayerClient* owner = (*it)->owner(); owner->platformCALayerAnimationStarted(t); } m_pendingAnimatedLayers.clear(); CGRect bounds = this->bounds(); // Give the renderer some space to use. This needs to be valid until the // wkCACFContextFinishUpdate() call below. char space[4096]; if (!wkCACFContextBeginUpdate(m_context, space, sizeof(space), currentMediaTime, bounds, windowDirtyRects.data(), windowDirtyRects.size())) return; HRESULT err = S_OK; CFTimeInterval timeToNextRender = numeric_limits<CFTimeInterval>::infinity(); do { // FIXME: don't need to clear dirty region if layer tree is opaque. WKCACFUpdateRectEnumerator* e = wkCACFContextCopyUpdateRectEnumerator(m_context); if (!e) break; Vector<D3DRECT, 64> rects; for (const CGRect* r = wkCACFUpdateRectEnumeratorNextRect(e); r; r = wkCACFUpdateRectEnumeratorNextRect(e)) { D3DRECT rect; rect.x1 = r->origin.x; rect.x2 = rect.x1 + r->size.width; rect.y1 = bounds.origin.y + bounds.size.height - (r->origin.y + r->size.height); rect.y2 = rect.y1 + r->size.height; rects.append(rect); } wkCACFUpdateRectEnumeratorRelease(e); timeToNextRender = wkCACFContextGetNextUpdateTime(m_context); if (rects.isEmpty()) break; m_d3dDevice->Clear(rects.size(), rects.data(), D3DCLEAR_TARGET, 0, 1.0f, 0); m_d3dDevice->BeginScene(); wkCACFContextRenderUpdate(m_context); m_d3dDevice->EndScene(); err = m_d3dDevice->Present(0, 0, 0, 0); if (err == D3DERR_DEVICELOST) { wkCACFContextAddUpdateRect(m_context, bounds); if (!resetDevice(LostDevice)) { // We can't reset the device right now. Try again soon. renderSoon(); return; } } } while (err == D3DERR_DEVICELOST); wkCACFContextFinishUpdate(m_context); #ifndef NDEBUG if (m_printTree) m_rootLayer->printTree(); #endif // If timeToNextRender is not infinity, it means animations are running, so queue up to render again if (timeToNextRender != numeric_limits<CFTimeInterval>::infinity()) renderSoon(); }
double nowInSeconds() const { return CACurrentMediaTime(); }