소스 검색

Add internal integer monotonic time helpers

Jakob Bornecrantz 7 년 전
부모
커밋
8ffd6cdd8d
4개의 변경된 파일89개의 추가작업 그리고 0개의 파일을 삭제
  1. 21 0
      src/openhmd.c
  2. 6 0
      src/openhmdi.h
  3. 47 0
      src/platform-posix.c
  4. 15 0
      src/platform-win32.c

+ 21 - 0
src/openhmd.c

@@ -26,6 +26,8 @@ ohmd_context* OHMD_APIENTRY ohmd_ctx_create(void)
 		return NULL;
 	}
 
+	ohmd_monotonic_init(ctx);
+
 #if DRIVER_OCULUS_RIFT
 	ctx->drivers[ctx->num_drivers++] = ohmd_create_oculus_rift_drv(ctx);
 #endif
@@ -578,3 +580,22 @@ void ohmd_set_universal_aberration_k(ohmd_device_properties* props, float r, flo
 	props->universal_aberration_k[1] = g;
 	props->universal_aberration_k[2] = b;
 }
+
+uint64_t ohmd_monotonic_per_sec(ohmd_context* ctx)
+{
+	return ctx->monotonic_ticks_per_sec;
+}
+
+/*
+ * Grabbed from druntime, good thing its BOOST v1.0 as well.
+ */
+uint64_t ohmd_monotonic_conv(uint64_t ticks, uint64_t srcTicksPerSecond, uint64_t dstTicksPerSecond)
+{
+	// This would be more straightforward with floating point arithmetic,
+	// but we avoid it here in order to avoid the rounding errors that that
+	// introduces. Also, by splitting out the units in this way, we're able
+	// to deal with much larger values before running into problems with
+	// integer overflow.
+	return ticks / srcTicksPerSecond * dstTicksPerSecond +
+		ticks % srcTicksPerSecond * dstTicksPerSecond / srcTicksPerSecond;
+}

+ 6 - 0
src/openhmdi.h

@@ -128,10 +128,16 @@ struct ohmd_context {
 
 	bool update_request_quit;
 
+	uint64_t monotonic_ticks_per_sec;
+
 	char error_msg[OHMD_STR_SIZE];
 };
 
 // helper functions
+void ohmd_monotonic_init(ohmd_context* ctx);
+uint64_t ohmd_monotonic_get(ohmd_context* ctx);
+uint64_t ohmd_monotonic_per_sec(ohmd_context* ctx);
+uint64_t ohmd_monotonic_conv(uint64_t ticks, uint64_t srcTicksPerSecond, uint64_t dstTicksPerSecond);
 void ohmd_set_default_device_properties(ohmd_device_properties* props);
 void ohmd_calc_default_proj_matrices(ohmd_device_properties* props);
 void ohmd_set_universal_distortion_k(ohmd_device_properties* props, float a, float b, float c, float d);

+ 47 - 0
src/platform-posix.c

@@ -41,6 +41,53 @@ double ohmd_get_tick()
 }
 #endif
 
+#ifndef CLOCK_MONOTONIC
+
+static const uint64_t NUM_1_000_000 = 1000000;
+
+void ohmd_monotonic_init(ohmd_context* ctx)
+{
+	ctx->monotonic_ticks_per_sec = NUM_1_000_000;
+}
+
+uint64_t ohmd_monotonic_get(ohmd_context* ctx)
+{
+	struct timeval now;
+	gettimeofday(&now, NULL);
+	return now.tv_sec * NUM_1_000_000 + now.tv_usec;
+}
+
+#else
+
+static const uint64_t NUM_1_000_000_000 = 1000000000;
+
+void ohmd_monotonic_init(ohmd_context* ctx)
+{
+		struct timespec ts;
+		if (clock_getres(CLOCK_MONOTONIC, &ts) !=  0) {
+			ctx->monotonic_ticks_per_sec = NUM_1_000_000_000;
+			return;
+		}
+
+		ctx->monotonic_ticks_per_sec =
+			ts.tv_nsec >= 1000 ?
+			NUM_1_000_000_000 :
+			NUM_1_000_000_000 / ts.tv_nsec;
+}
+
+uint64_t ohmd_monotonic_get(ohmd_context* ctx)
+{
+	struct timespec now;
+	clock_gettime(CLOCK_MONOTONIC, &now);
+
+	return ohmd_monotonic_conv(
+		now.tv_sec * NUM_1_000_000_000 + now.tv_nsec,
+		NUM_1_000_000_000,
+		ctx->monotonic_ticks_per_sec);
+}
+
+#endif
+
 void ohmd_sleep(double seconds)
 {
 	struct timespec sleepfor;

+ 15 - 0
src/platform-win32.c

@@ -30,6 +30,21 @@ double ohmd_get_tick()
 	return (high * 4294967296.0 + low) / 10000000;
 }
 
+static const uint64_t NUM_10_000_000 = 10000000;
+
+void ohmd_monotonic_init(ohmd_context* ctx)
+{
+	ctx->monotonic_ticks_per_sec = NUM_10_000_000;
+}
+
+uint64_t ohmd_monotonic_get(ohmd_context* ctx)
+{
+	FILETIME filetime;
+	GetSystemTimeAsFileTime(&filetime);
+
+	return ((uint64_t)filetime.dwHighDateTime << 32) | filetime.dwLowDateTime;
+}
+
 // TODO higher resolution
 void ohmd_sleep(double seconds)
 {