Ever wondered why anything derived from the TDK_Samples sometimes freeze on other phones?

It’s because there’s a bug in nv_egl_util.cpp when it checks for
eglGetSystemTimeNV and eglGetSystemTimeFrequencyNV. The correct way to do this is to FIRST check whether the extension name exists in the EGL_EXTENSIONS string, and THEN ask for the function pointer.

Here’s a quick patch to fix it:

Source: http://jangutter.com/files/tdk-samples-extension-check-fix.patch

No guarantees that the forum won’t mangle it, but here it is just in case you’re afraid to click on the link.

--- TDK_Samples/tegra_android_native_samples_v10p12/libs/jni/nv_egl_util/nv_egl_util.cpp.orig	2013-09-18 16:29:38.007711196 +0200
+++ TDK_Samples/tegra_android_native_samples_v10p12/libs/jni/nv_egl_util/nv_egl_util.cpp	2013-09-18 16:29:47.735759466 +0200
@@ -254,6 +254,33 @@
 	return false;
 }
 
+bool NvEGLUtil::checkExtension(const char* extName)
+{
+	/*
+	 ** This code is adapted from http://www.mesa3d.org/brianp/sig97/exten.htm
+	 **
+	 ** Search for extName in the extensions string.  Use of strstr()
+	 ** is not sufficient because extension names can be prefixes of
+	 ** other extension names.  Could use strtok() but the constant
+	 ** string returned by glGetString can be in read-only memory.
+	 **
+	 ** This code is relatively safe, as long as extName is a well-behaved string
+	 */
+
+	const char *p = (const char *) eglQueryString(getDisplay(),EGL_EXTENSIONS);
+	size_t extNameLen = strlen(extName);
+	const char *end = p + strlen(p);
+
+	while (p < end) {
+		size_t n = strcspn(p, " ");
+		if ((extNameLen == n) && (strncmp(extName, p, n) == 0)) {
+			return true;
+		}
+		p += (n + 1);
+	}
+	return false;
+}
+
 bool NvEGLUtil::createSurface()
 {
 	if (m_status >= NV_HAS_SURFACE)
@@ -437,8 +464,13 @@
 
     m_nvTimeExtensionQueried = true;
 
-	m_eglGetSystemTimeFrequencyNVProc = (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) eglGetProcAddress("eglGetSystemTimeFrequencyNV");
-	m_eglGetSystemTimeNVProc = (PFNEGLGETSYSTEMTIMENVPROC) eglGetProcAddress("eglGetSystemTimeNV");
+	if (checkExtension("EGL_NV_system_time")) {
+		m_eglGetSystemTimeFrequencyNVProc = (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) eglGetProcAddress("eglGetSystemTimeFrequencyNV");
+		m_eglGetSystemTimeNVProc = (PFNEGLGETSYSTEMTIMENVPROC) eglGetProcAddress("eglGetSystemTimeNV");
+	} else {
+		m_eglGetSystemTimeFrequencyNVProc = (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) NULL;
+		m_eglGetSystemTimeNVProc = (PFNEGLGETSYSTEMTIMENVPROC) NULL;
+	}
 
 	// now, we'll proceed through a series of sanity checking.
 	// if they all succeed, we'll return.
@@ -456,6 +488,7 @@
 			if (time1 != time2) // quick sanity only...
 			{
 				// we've sanity checked:
+				// - extension is advertised
 				// - fn pointers non-null
 				// - freq non-zero
 				// - two calls to time sep'd by sleep non-equal

thanks for the bug report - we’ll update that in the next release

Whoops, I noticed a glaring mistake: I forgot to include the update for the .h file. The link’s been updated, and here it is:

--- TDK_Samples/tegra_android_native_samples_v10p12/libs/jni/nv_egl_util/nv_egl_util.h.orig	2013-10-02 11:01:45.584414503 +0200
+++ TDK_Samples/tegra_android_native_samples_v10p12/libs/jni/nv_egl_util/nv_egl_util.h	2013-10-02 11:04:31.905239268 +0200
@@ -115,6 +115,11 @@
 	// Returns true if the app has an allocated surface (bound or not)
 	// returns false otherwise
 	bool hasSurface() { return m_status >= NV_HAS_SURFACE; }
+	
+	// Returns true if the specified EGL extension is available on the
+	// system. Requires a well-behaved string for extName: do input
+	// checking first!
+	bool checkExtension(const char* extName);
 
 	// Accessors for the low-level EGL/Android objects
 	EGLDisplay getDisplay() { return m_display; }