From cd4c5c75513d99ef4d5d68beb2f294a168abee7d Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Thu, 8 Dec 2016 14:04:04 -0500 Subject: [PATCH 01/43] change int to std::uint8_t. Add some logging to check value of eye index. --- OsvrRenderingPlugin.cpp | 46 ++++++++++++++++++++++++++++++++++------- OsvrRenderingPlugin.h | 9 ++++---- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 3bd7d21..b427cd2 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -677,17 +677,49 @@ void UNITY_INTERFACE_API SetIPD(double ipdMeters) { } osvr::renderkit::OSVR_ViewportDescription UNITY_INTERFACE_API -GetViewport(int eye) { - return s_renderInfo[eye].viewport; +GetViewport(std::uint8_t eye) { + osvr::renderkit::OSVR_ViewportDescription viewportDescription; + if (s_renderInfo.size() > 0 && eye <= s_renderInfo.size() - 1) + { + viewportDescription = s_renderInfo[eye].viewport; + } + else + { + std::string errorLog = "[OSVR Rendering Plugin] Index out of range in GetViewport, eye = " + eye; + DebugLog(errorLog.c_str()); + } + return viewportDescription; } osvr::renderkit::OSVR_ProjectionMatrix UNITY_INTERFACE_API -GetProjectionMatrix(int eye) { - return s_renderInfo[eye].projection; +GetProjectionMatrix(std::uint8_t eye) { + osvr::renderkit::OSVR_ProjectionMatrix pm; + if (s_renderInfo.size() > 0 && eye <= s_renderInfo.size() - 1) + { + pm = s_renderInfo[eye].projection; + } + else + { + std::string errorLog = "[OSVR Rendering Plugin] Index out of range in GetProjectionMatrix, eye = " + eye; + DebugLog(errorLog.c_str()); + } + return pm; } -OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(int eye) { - return s_renderInfo[eye].pose; +OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { + OSVR_Pose3 pose; + osvrPose3SetIdentity(&pose); + if (s_renderInfo.size() > 0 && eye <= s_renderInfo.size() - 1) + { + std::string errorLog = "[OSVR Rendering Plugin] working, eye = " + eye; + pose = s_renderInfo[eye].pose; + } + else + { + std::string errorLog = "[OSVR Rendering Plugin] Index out of range in GetEyePose, eye = " + eye; + DebugLog(errorLog.c_str()); + } + return pose; } // -------------------------------------------------------------------------- @@ -703,7 +735,7 @@ OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(int eye) { // to set up needed texture pointers only at initialization time. // For more reference, see: // http://docs.unity3d.com/ScriptReference/Texture.GetNativeTexturePtr.html -int UNITY_INTERFACE_API SetColorBufferFromUnity(void *texturePtr, int eye) { +int UNITY_INTERFACE_API SetColorBufferFromUnity(void *texturePtr, std::uint8_t eye) { if (!s_deviceType) { return OSVR_RETURN_FAILURE; } diff --git a/OsvrRenderingPlugin.h b/OsvrRenderingPlugin.h index 25e9687..57d79c2 100644 --- a/OsvrRenderingPlugin.h +++ b/OsvrRenderingPlugin.h @@ -28,6 +28,7 @@ Sensics, Inc. #include #include #include +#include typedef void(UNITY_INTERFACE_API *DebugFnPtr)(const char *); @@ -45,18 +46,18 @@ ConstructRenderBuffers(); UNITY_INTERFACE_EXPORT OSVR_ReturnCode UNITY_INTERFACE_API CreateRenderManagerFromUnity(OSVR_ClientContext context); -UNITY_INTERFACE_EXPORT OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(int eye); +UNITY_INTERFACE_EXPORT OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye); UNITY_INTERFACE_EXPORT osvr::renderkit::OSVR_ProjectionMatrix UNITY_INTERFACE_API - GetProjectionMatrix(int eye); + GetProjectionMatrix(std::uint8_t eye); UNITY_INTERFACE_EXPORT UnityRenderingEvent UNITY_INTERFACE_API GetRenderEventFunc(); UNITY_INTERFACE_EXPORT osvr::renderkit::OSVR_ViewportDescription UNITY_INTERFACE_API - GetViewport(int eye); + GetViewport(std::uint8_t eye); UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API LinkDebug(DebugFnPtr d); @@ -64,7 +65,7 @@ UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API OnRenderEvent(int eventID); /// @todo should return OSVR_ReturnCode UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API -SetColorBufferFromUnity(void *texturePtr, int eye); +SetColorBufferFromUnity(void *texturePtr, std::uint8_t eye); UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API SetFarClipDistance(double distance); From b9ad253c7dafdd4b740537d089af71494d4c95d9 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Thu, 8 Dec 2016 14:04:39 -0500 Subject: [PATCH 02/43] enable logging. --- OsvrRenderingPlugin.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index b427cd2..56b82e0 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -21,8 +21,8 @@ Sensics, Inc. // limitations under the License. /// Both of these need to be enabled to force-enable logging to files. -#undef ENABLE_LOGGING -#undef ENABLE_LOGFILE +#define ENABLE_LOGGING 1 +#define ENABLE_LOGFILE 1 // Internal includes #include "OsvrRenderingPlugin.h" @@ -634,7 +634,7 @@ inline void CleanupBufferD3D11(osvr::renderkit::RenderBuffer &rb) { OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { if (!s_deviceType) { - DebugLog("Device type not supported."); + DebugLog("[OSVR Rendering Plugin] Device type not supported."); return OSVR_RETURN_FAILURE; } UpdateRenderInfo(); From 0fe7801af418ac09e044cae924c87e6abf3b4f9f Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Thu, 8 Dec 2016 14:39:18 -0500 Subject: [PATCH 03/43] updated logging --- OsvrRenderingPlugin.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 56b82e0..89df485 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -711,12 +711,11 @@ OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { osvrPose3SetIdentity(&pose); if (s_renderInfo.size() > 0 && eye <= s_renderInfo.size() - 1) { - std::string errorLog = "[OSVR Rendering Plugin] working, eye = " + eye; pose = s_renderInfo[eye].pose; } else { - std::string errorLog = "[OSVR Rendering Plugin] Index out of range in GetEyePose, eye = " + eye; + std::string errorLog = "[OSVR Rendering Plugin] working, eye = " + std::to_string(int(eye)); DebugLog(errorLog.c_str()); } return pose; From ee115677667b7c13a93931ad607c7a1fcb2caf63 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Thu, 8 Dec 2016 15:36:56 -0500 Subject: [PATCH 04/43] added logging --- OsvrRenderingPlugin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 89df485..1a66783 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -685,7 +685,7 @@ GetViewport(std::uint8_t eye) { } else { - std::string errorLog = "[OSVR Rendering Plugin] Index out of range in GetViewport, eye = " + eye; + std::string errorLog = "[OSVR Rendering Plugin] working, eye = " + std::to_string(int(eye)); DebugLog(errorLog.c_str()); } return viewportDescription; @@ -700,7 +700,7 @@ GetProjectionMatrix(std::uint8_t eye) { } else { - std::string errorLog = "[OSVR Rendering Plugin] Index out of range in GetProjectionMatrix, eye = " + eye; + std::string errorLog = "[OSVR Rendering Plugin] working, eye = " + std::to_string(int(eye)); DebugLog(errorLog.c_str()); } return pm; From 3b2ef3050d747522338e33966de3b0f982be54a4 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Thu, 8 Dec 2016 15:49:54 -0500 Subject: [PATCH 05/43] updated logging --- OsvrRenderingPlugin.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 1a66783..2be7afd 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -685,7 +685,7 @@ GetViewport(std::uint8_t eye) { } else { - std::string errorLog = "[OSVR Rendering Plugin] working, eye = " + std::to_string(int(eye)); + std::string errorLog = "[OSVR Rendering Plugin] error in GetViewport, eye = " + std::to_string(int(eye)); DebugLog(errorLog.c_str()); } return viewportDescription; @@ -700,7 +700,7 @@ GetProjectionMatrix(std::uint8_t eye) { } else { - std::string errorLog = "[OSVR Rendering Plugin] working, eye = " + std::to_string(int(eye)); + std::string errorLog = "[OSVR Rendering Plugin] error in GetProjectionMatrix, eye = " + std::to_string(int(eye)); DebugLog(errorLog.c_str()); } return pm; @@ -715,7 +715,7 @@ OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { } else { - std::string errorLog = "[OSVR Rendering Plugin] working, eye = " + std::to_string(int(eye)); + std::string errorLog = "[OSVR Rendering Plugin] error in GetEyePose, eye = " + std::to_string(int(eye)); DebugLog(errorLog.c_str()); } return pose; From bd0edc0589cbcd9254895de277a0c04737ce9463 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Thu, 8 Dec 2016 16:24:36 -0500 Subject: [PATCH 06/43] more logging --- OsvrRenderingPlugin.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 2be7afd..a39247f 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -687,6 +687,8 @@ GetViewport(std::uint8_t eye) { { std::string errorLog = "[OSVR Rendering Plugin] error in GetViewport, eye = " + std::to_string(int(eye)); DebugLog(errorLog.c_str()); + errorLog = "[OSVR Rendering Plugin] renderInfo array size is = " + std::to_string(int(s_renderInfo.size())); + DebugLog(errorLog.c_str()); } return viewportDescription; } @@ -702,6 +704,8 @@ GetProjectionMatrix(std::uint8_t eye) { { std::string errorLog = "[OSVR Rendering Plugin] error in GetProjectionMatrix, eye = " + std::to_string(int(eye)); DebugLog(errorLog.c_str()); + errorLog = "[OSVR Rendering Plugin] renderInfo array size is = " + std::to_string(int(s_renderInfo.size())); + DebugLog(errorLog.c_str()); } return pm; } @@ -717,6 +721,8 @@ OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { { std::string errorLog = "[OSVR Rendering Plugin] error in GetEyePose, eye = " + std::to_string(int(eye)); DebugLog(errorLog.c_str()); + errorLog = "[OSVR Rendering Plugin] renderInfo array size is = " + std::to_string(int(s_renderInfo.size())); + DebugLog(errorLog.c_str()); } return pose; } From af7daac3ccf29aecf224f9b35f15e190bdd13745 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Thu, 8 Dec 2016 17:05:33 -0500 Subject: [PATCH 07/43] return default HDK2 viewport when renderInfo size=0 bug occurs --- OsvrRenderingPlugin.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index a39247f..a61e48e 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -682,6 +682,14 @@ GetViewport(std::uint8_t eye) { if (s_renderInfo.size() > 0 && eye <= s_renderInfo.size() - 1) { viewportDescription = s_renderInfo[eye].viewport; + /*std::string d0 = "[OSVR Rendering Plugin] viewportDescription, eye = " + std::to_string(int(eye)); + std::string d1 = "left = " + std::to_string(int(s_renderInfo[eye].viewport.left)); + std::string d2 = "lower = " + std::to_string(int(s_renderInfo[eye].viewport.lower)); + std::string d3 = "width = " + std::to_string(int(s_renderInfo[eye].viewport.width)); + std::string d4 = "height = " + std::to_string(int(s_renderInfo[eye].viewport.height)); + std::string d5 = d0 + "\n" + d1 + "\n" + d2 + "\n" + d3 + "\n" + d4 + "\n"; + DebugLog(d5.c_str());*/ + } else { @@ -689,6 +697,10 @@ GetViewport(std::uint8_t eye) { DebugLog(errorLog.c_str()); errorLog = "[OSVR Rendering Plugin] renderInfo array size is = " + std::to_string(int(s_renderInfo.size())); DebugLog(errorLog.c_str()); + viewportDescription.left = 0; + viewportDescription.lower = 0; + viewportDescription.width = 1080; + viewportDescription.height = 1200; } return viewportDescription; } From dad1c167bcd41c7774bc5cbac8fc377732e0ab59 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Mon, 12 Dec 2016 13:40:44 -0500 Subject: [PATCH 08/43] cache non-zero viewport values for width and height, and return them instead of a zeroed viewport when that bug appears. --- OsvrRenderingPlugin.cpp | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index a61e48e..535da94 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -92,6 +92,9 @@ static double s_nearClipDistance = 0.1; static double s_farClipDistance = 1000.0; /// @todo is this redundant? (given renderParams) static double s_ipd = 0.063; +//cached viewport values +static std::uint32_t viewportWidth = 0; +static std::uint32_t viewportHeight = 0; #if defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) static std::ofstream s_debugLogFile; @@ -682,25 +685,27 @@ GetViewport(std::uint8_t eye) { if (s_renderInfo.size() > 0 && eye <= s_renderInfo.size() - 1) { viewportDescription = s_renderInfo[eye].viewport; - /*std::string d0 = "[OSVR Rendering Plugin] viewportDescription, eye = " + std::to_string(int(eye)); - std::string d1 = "left = " + std::to_string(int(s_renderInfo[eye].viewport.left)); - std::string d2 = "lower = " + std::to_string(int(s_renderInfo[eye].viewport.lower)); - std::string d3 = "width = " + std::to_string(int(s_renderInfo[eye].viewport.width)); - std::string d4 = "height = " + std::to_string(int(s_renderInfo[eye].viewport.height)); - std::string d5 = d0 + "\n" + d1 + "\n" + d2 + "\n" + d3 + "\n" + d4 + "\n"; - DebugLog(d5.c_str());*/ + //cache the viewport width and height + //patches issue where sometimes empty viewport is returned + //@todo fix the real cause of why this method bugs out occasionally on some machines, more often on others + if (viewportWidth == 0 && s_renderInfo[eye].viewport.width != 0) + { + viewportWidth = s_renderInfo[eye].viewport.width; + } + if (viewportHeight == 0 && s_renderInfo[eye].viewport.height != 0) + { + viewportHeight = s_renderInfo[eye].viewport.height; + } } else { - std::string errorLog = "[OSVR Rendering Plugin] error in GetViewport, eye = " + std::to_string(int(eye)); - DebugLog(errorLog.c_str()); - errorLog = "[OSVR Rendering Plugin] renderInfo array size is = " + std::to_string(int(s_renderInfo.size())); + std::string errorLog = "[OSVR Rendering Plugin] Error in GetViewport, returning cached values. Eye = " + std::to_string(int(eye)); DebugLog(errorLog.c_str()); viewportDescription.left = 0; viewportDescription.lower = 0; - viewportDescription.width = 1080; - viewportDescription.height = 1200; + viewportDescription.width = viewportWidth; + viewportDescription.height = viewportHeight; } return viewportDescription; } From 629403503ae5fd2e0f43ef86f70127816f2bd1bc Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Mon, 12 Dec 2016 13:45:59 -0500 Subject: [PATCH 09/43] Disable logging and added comments. --- OsvrRenderingPlugin.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 535da94..1904406 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -21,8 +21,8 @@ Sensics, Inc. // limitations under the License. /// Both of these need to be enabled to force-enable logging to files. -#define ENABLE_LOGGING 1 -#define ENABLE_LOGFILE 1 +#undef ENABLE_LOGGING +#undef ENABLE_LOGFILE // Internal includes #include "OsvrRenderingPlugin.h" @@ -700,6 +700,7 @@ GetViewport(std::uint8_t eye) { } else { + //we shouldn't be here unless we hit a bug, in which case, we avoid error by returning cached viewport values std::string errorLog = "[OSVR Rendering Plugin] Error in GetViewport, returning cached values. Eye = " + std::to_string(int(eye)); DebugLog(errorLog.c_str()); viewportDescription.left = 0; @@ -719,9 +720,7 @@ GetProjectionMatrix(std::uint8_t eye) { } else { - std::string errorLog = "[OSVR Rendering Plugin] error in GetProjectionMatrix, eye = " + std::to_string(int(eye)); - DebugLog(errorLog.c_str()); - errorLog = "[OSVR Rendering Plugin] renderInfo array size is = " + std::to_string(int(s_renderInfo.size())); + std::string errorLog = "[OSVR Rendering Plugin] Error in GetProjectionMatrix, returning default values. Eye = " + std::to_string(int(eye)); DebugLog(errorLog.c_str()); } return pm; @@ -736,9 +735,7 @@ OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { } else { - std::string errorLog = "[OSVR Rendering Plugin] error in GetEyePose, eye = " + std::to_string(int(eye)); - DebugLog(errorLog.c_str()); - errorLog = "[OSVR Rendering Plugin] renderInfo array size is = " + std::to_string(int(s_renderInfo.size())); + std::string errorLog = "[OSVR Rendering Plugin] Error in GetEyePose, returning default values. Eye = " + std::to_string(int(eye)); DebugLog(errorLog.c_str()); } return pose; From fc16712f85c2486bf396362cbce3996729219978 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Mon, 9 Jan 2017 14:47:11 -0500 Subject: [PATCH 10/43] Change from C++ to CAPI. Works, but not complete yet. --- OsvrRenderingPlugin.cpp | 229 ++++++++++++++++++++++++++-------------- OsvrRenderingPlugin.h | 5 +- 2 files changed, 155 insertions(+), 79 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 1904406..db0541e 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -30,7 +30,6 @@ Sensics, Inc. #include "UnityRendererType.h" // Library includes -#include "osvr/RenderKit/RenderManager.h" #include #include #include @@ -54,6 +53,7 @@ Sensics, Inc. #include "Unity/IUnityGraphicsD3D11.h" #include +#include #endif // SUPPORT_D3D11 @@ -78,12 +78,14 @@ static IUnityInterfaces *s_UnityInterfaces = nullptr; static IUnityGraphics *s_Graphics = nullptr; static UnityRendererType s_deviceType = {}; -static osvr::renderkit::RenderManager::RenderParams s_renderParams; -static osvr::renderkit::RenderManager *s_render = nullptr; +static OSVR_RenderParams s_renderParams; +static OSVR_RenderManager s_render = nullptr; +static OSVR_RenderManagerD3D11 s_renderD3D = nullptr; static OSVR_ClientContext s_clientContext = nullptr; -static std::vector s_renderBuffers; -static std::vector s_renderInfo; -static osvr::renderkit::GraphicsLibrary s_library; +static std::vector s_renderBuffers; +static std::vector s_renderInfo; +static OSVR_RenderInfoCount numRenderInfo; +static OSVR_GraphicsLibraryD3D11 s_libraryD3D; static void *s_leftEyeTexturePtr = nullptr; static void *s_rightEyeTexturePtr = nullptr; /// @todo is this redundant? (given renderParams) @@ -176,11 +178,10 @@ inline void DoEventGraphicsDeviceD3D11(UnityGfxDeviceEventType eventType) { // Put the device and context into a structure to let RenderManager // know to use this one rather than creating its own. - s_library.D3D11 = new osvr::renderkit::GraphicsLibraryD3D11; - s_library.D3D11->device = d3d11->GetDevice(); + s_libraryD3D.device = d3d11->GetDevice(); ID3D11DeviceContext *ctx = nullptr; - s_library.D3D11->device->GetImmediateContext(&ctx); - s_library.D3D11->context = ctx; + s_libraryD3D.device->GetImmediateContext(&ctx); + s_libraryD3D.context = ctx; DebugLog("[OSVR Rendering Plugin] Passed Unity device/context to " "RenderManager library."); break; @@ -323,7 +324,18 @@ void UNITY_INTERFACE_API UnityPluginUnload() { } inline void UpdateRenderInfo() { - s_renderInfo = s_render->GetRenderInfo(s_renderParams); + s_renderInfo.clear(); + for (OSVR_RenderInfoCount i = 0; i < numRenderInfo; i++) { + OSVR_RenderInfoD3D11 info; + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerGetRenderInfoD3D11( + s_renderD3D, i, s_renderParams, &info))) { + DebugLog("[OSVR Rendering Plugin] Could not get render info."); + ShutdownRenderManager(); + } + s_renderInfo.push_back(info); + } + // s_renderInfo = s_render->GetRenderInfo(s_renderParams); + //osvrRenderManagerGetRenderInfoD3D11(s_renderD3D) } #if 0 @@ -366,19 +378,19 @@ UpdateDistortionMesh(float distanceScale[2], float centerOfProjection[2], // Note that this method internally calls osvrClientUpdate() to get a head pose // so your callbacks may be called during its execution! /// @todo does this actually get called from anywhere or is it dead code? -void SetRoomRotationUsingHead() { s_render->SetRoomRotationUsingHead(); } +void SetRoomRotationUsingHead() {/* s_renderD3D-> SetRoomRotationUsingHead(); */} // Clears/resets the internal "room to world" transformation back to an // identity transformation - that is, clears the effect of any other // manipulation of the room to world transform. /// @todo does this actually get called from anywhere or is it dead code? -void ClearRoomToWorldTransform() { s_render->ClearRoomToWorldTransform(); } +void ClearRoomToWorldTransform() { /*s_render->ClearRoomToWorldTransform(); */} // Called from Unity to create a RenderManager, passing in a ClientContext OSVR_ReturnCode UNITY_INTERFACE_API CreateRenderManagerFromUnity(OSVR_ClientContext context) { /// See if we're already created/running - shouldn't happen, but might. - if (s_render != nullptr) { + /* if (s_render != nullptr) { if (s_render->doingOkay()) { DebugLog("[OSVR Rendering Plugin] RenderManager already created " "and doing OK - will just return success without trying " @@ -389,7 +401,7 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context) { DebugLog("[OSVR Rendering Plugin] RenderManager already created, " "but not doing OK. Will shut down before creating again."); ShutdownRenderManager(); - } + }*/ if (s_clientContext != nullptr) { DebugLog( "[OSVR Rendering Plugin] Client context already set! Replacing..."); @@ -418,8 +430,11 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context) { #if SUPPORT_D3D11 case OSVRSupportedRenderers::D3D11: - s_render = osvr::renderkit::createRenderManager(context, "Direct3D11", - s_library); + if (OSVR_RETURN_SUCCESS != osvrCreateRenderManagerD3D11( + context, "Direct3D11", s_libraryD3D, &s_render, &s_renderD3D)) { + DebugLog("[OSVR Rendering Plugin] Could not create RenderManager"); + return OSVR_RETURN_FAILURE; + } #ifdef ATTEMPT_D3D_SHARING setLibraryFromOpenDisplayReturn = true; #endif // ATTEMPT_D3D_SHARING @@ -428,35 +443,66 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context) { #if SUPPORT_OPENGL case OSVRSupportedRenderers::OpenGL: - s_render = osvr::renderkit::createRenderManager(context, "OpenGL"); + // s_render = osvr::renderkit::createRenderManager(context, "OpenGL"); setLibraryFromOpenDisplayReturn = true; break; #endif // SUPPORT_OPENGL } - if ((s_render == nullptr) || (!s_render->doingOkay())) { + if (s_render == nullptr) { DebugLog("[OSVR Rendering Plugin] Could not create RenderManager"); ShutdownRenderManager(); return OSVR_RETURN_FAILURE; } - // Open the display and make sure this worked. - osvr::renderkit::RenderManager::OpenResults ret = s_render->OpenDisplay(); - if (ret.status == osvr::renderkit::RenderManager::OpenStatus::FAILURE) { - DebugLog("[OSVR Rendering Plugin] Could not open display"); + // Open the display and make sure this worked. + OSVR_OpenResultsD3D11 openResults; + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerOpenDisplayD3D11( + s_renderD3D, &openResults)) || + (openResults.status == OSVR_OPEN_STATUS_FAILURE)) { + DebugLog("[OSVR Rendering Plugin] Could not open display"); + ShutdownRenderManager(); + return OSVR_RETURN_FAILURE; + } + if (openResults.library.device == nullptr) { + DebugLog("[OSVR Rendering Plugin] Could not get device when opening display"); ShutdownRenderManager(); - return OSVR_RETURN_FAILURE; - } - if (setLibraryFromOpenDisplayReturn) { + return OSVR_RETURN_FAILURE; + } + if (openResults.library.context == nullptr) { + DebugLog("[OSVR Rendering Plugin] Could not get context when opening display"); + + ShutdownRenderManager(); + return OSVR_RETURN_FAILURE; + } + + /*if (setLibraryFromOpenDisplayReturn) { // Set our library from the one RenderManager created. - s_library = ret.library; - } + s_libraryD3D = ret.library; + }*/ // create a new set of RenderParams for passing to GetRenderInfo() - s_renderParams = osvr::renderkit::RenderManager::RenderParams(); - UpdateRenderInfo(); + osvrRenderManagerGetDefaultRenderParams(&s_renderParams); + if((OSVR_RETURN_SUCCESS != osvrRenderManagerGetNumRenderInfo( + s_render, s_renderParams, &numRenderInfo))) { + DebugLog("[OSVR Rendering Plugin] Could not get context number of render infos."); + ShutdownRenderManager(); + return OSVR_RETURN_FAILURE; + } + + //update renderinfo + s_renderInfo.clear(); + for (OSVR_RenderInfoCount i = 0; i < numRenderInfo; i++) { + OSVR_RenderInfoD3D11 info; + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerGetRenderInfoD3D11( + s_renderD3D, i, s_renderParams, &info))) { + DebugLog("[OSVR Rendering Plugin] Could not get render info."); + ShutdownRenderManager(); + } + s_renderInfo.push_back(info); + } DebugLog("[OSVR Rendering Plugin] CreateRenderManagerFromUnity Success!"); return OSVR_RETURN_SUCCESS; @@ -472,9 +518,9 @@ inline OSVR_ReturnCode applyRenderBufferConstructor(const int numBuffers, /// render buffers with this lambda. auto cleanupBuffers = osvr::util::finally([&] { DebugLog("[OSVR Rendering Plugin] Cleaning up render buffers."); - for (auto &rb : s_renderBuffers) { + /*for (auto &rb : s_renderBuffers) { bufferCleanup(rb); - } + }*/ s_renderBuffers.clear(); DebugLog("[OSVR Rendering Plugin] Render buffer cleanup complete."); }); @@ -490,10 +536,30 @@ inline OSVR_ReturnCode applyRenderBufferConstructor(const int numBuffers, /// Register our constructed buffers so that we can use them for /// presentation. - if (!s_render->RegisterRenderBuffers(s_renderBuffers)) { + /* if (!s_render->RegisterRenderBuffers(s_renderBuffers)) { DebugLog("RegisterRenderBuffers() returned false, cannot continue"); return OSVR_RETURN_FAILURE; - } + }*/ + // Register our constructed buffers so that we can use them for + // presentation. + OSVR_RenderManagerRegisterBufferState registerBufferState; + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerStartRegisterRenderBuffers( + ®isterBufferState))) { + DebugLog("[OSVR Rendering Plugin]Could not start registering render buffers"); + ShutdownRenderManager(); + } + for (size_t i = 0; i < numRenderInfo; i++) { + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerRegisterRenderBufferD3D11( + registerBufferState, s_renderBuffers[i]))) { + DebugLog("[OSVR Rendering Plugin]Could not register render buffers"); + ShutdownRenderManager(); + } + } + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerFinishRegisterRenderBuffers( + s_render, registerBufferState, false))) { + DebugLog("[OSVR Rendering Plugin]Could not finish registering render buffers"); + ShutdownRenderManager(); + } /// Only if we succeed, do we cancel the cleanup and carry on. cleanupBuffers.cancel(); return OSVR_RETURN_SUCCESS; @@ -502,7 +568,7 @@ inline OSVR_ReturnCode applyRenderBufferConstructor(const int numBuffers, #if SUPPORT_OPENGL inline OSVR_ReturnCode ConstructBuffersOpenGL(int eye) { // Init glew - glewExperimental = 1u; + /* glewExperimental = 1u; /// @todo doesn't rendermanager do this glewInit for us? GLenum err = glewInit(); if (err != GLEW_OK) { @@ -560,14 +626,14 @@ inline OSVR_ReturnCode ConstructBuffersOpenGL(int eye) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - + */ return OSVR_RETURN_SUCCESS; } -inline void CleanupBufferOpenGL(osvr::renderkit::RenderBuffer &rb) { +inline void CleanupBufferOpenGL(OSVR_RenderBufferOpenGL &rb) { /// @todo incomplete cleanup - but better than leaking in case of failure. - delete rb.OpenGL; - rb.OpenGL = nullptr; + // delete rb.OpenGL; + // rb.OpenGL = nullptr; } #endif // SUPPORT_OPENGL @@ -606,7 +672,7 @@ inline OSVR_ReturnCode ConstructBuffersD3D11(int eye) { // Create the render target view. ID3D11RenderTargetView *renderTargetView = nullptr; //< Pointer to our render target view - hr = s_renderInfo[eye].library.D3D11->device->CreateRenderTargetView( + hr = s_renderInfo[eye].library.device->CreateRenderTargetView( D3DTexture, &renderTargetViewDesc, &renderTargetView); if (FAILED(hr)) { DebugLog( @@ -615,23 +681,17 @@ inline OSVR_ReturnCode ConstructBuffersD3D11(int eye) { } // Push the filled-in RenderBuffer onto the stack. - std::unique_ptr rbD3D( - new osvr::renderkit::RenderBufferD3D11); - rbD3D->colorBuffer = D3DTexture; - rbD3D->colorBufferView = renderTargetView; - osvr::renderkit::RenderBuffer rb; - rb.D3D11 = rbD3D.get(); - s_renderBuffers.push_back(rb); - - // OK, we succeeded, must release ownership of that pointer now that it's in - // RenderManager's hands. - rbD3D.release(); + OSVR_RenderBufferD3D11 rbD3D; + rbD3D.colorBuffer = D3DTexture; + rbD3D.colorBufferView = renderTargetView; + s_renderBuffers.push_back(rbD3D); + return OSVR_RETURN_SUCCESS; } -inline void CleanupBufferD3D11(osvr::renderkit::RenderBuffer &rb) { - delete rb.D3D11; - rb.D3D11 = nullptr; +inline void CleanupBufferD3D11(OSVR_RenderBufferD3D11 &rb) { + // delete rb.D3D11; + //rb.D3D11 = nullptr; } #endif // SUPPORT_D3D11 @@ -676,12 +736,12 @@ void UNITY_INTERFACE_API SetFarClipDistance(double distance) { void UNITY_INTERFACE_API SetIPD(double ipdMeters) { s_ipd = ipdMeters; - s_renderParams.IPDMeters = s_ipd; + // s_renderParams.IPDMeters = s_ipd; } -osvr::renderkit::OSVR_ViewportDescription UNITY_INTERFACE_API +OSVR_ViewportDescription UNITY_INTERFACE_API GetViewport(std::uint8_t eye) { - osvr::renderkit::OSVR_ViewportDescription viewportDescription; + OSVR_ViewportDescription viewportDescription; if (s_renderInfo.size() > 0 && eye <= s_renderInfo.size() - 1) { viewportDescription = s_renderInfo[eye].viewport; @@ -711,9 +771,9 @@ GetViewport(std::uint8_t eye) { return viewportDescription; } -osvr::renderkit::OSVR_ProjectionMatrix UNITY_INTERFACE_API +OSVR_ProjectionMatrix UNITY_INTERFACE_API GetProjectionMatrix(std::uint8_t eye) { - osvr::renderkit::OSVR_ProjectionMatrix pm; + OSVR_ProjectionMatrix pm; if (s_renderInfo.size() > 0 && eye <= s_renderInfo.size() - 1) { pm = s_renderInfo[eye].projection; @@ -771,14 +831,14 @@ int UNITY_INTERFACE_API SetColorBufferFromUnity(void *texturePtr, std::uint8_t e #if SUPPORT_D3D11 // Renders the view from our Unity cameras by copying data at // Unity.RenderTexture.GetNativeTexturePtr() to RenderManager colorBuffers -void RenderViewD3D11(const osvr::renderkit::RenderInfo &ri, +void RenderViewD3D11(const OSVR_RenderInfoD3D11 &ri, ID3D11RenderTargetView *renderTargetView, int eyeIndex) { - auto context = ri.library.D3D11->context; + auto context = ri.library.context; // Set up to render to the textures for this eye context->OMSetRenderTargets(1, &renderTargetView, NULL); // copy the updated RenderTexture from Unity to RenderManager colorBuffer - s_renderBuffers[eyeIndex].D3D11->colorBuffer = GetEyeTextureD3D11(eyeIndex); + s_renderBuffers[eyeIndex].colorBuffer = GetEyeTextureD3D11(eyeIndex); } #endif // SUPPORT_D3D11 @@ -786,12 +846,12 @@ void RenderViewD3D11(const osvr::renderkit::RenderInfo &ri, // Render the world from the specified point of view. //@todo This is not functional yet. inline void RenderViewOpenGL( - const osvr::renderkit::RenderInfo &ri, //< Info needed to render + const OSVR_RenderInfoOpenGL &ri, //< Info needed to render GLuint frameBufferObj, //< Frame buffer object to bind our buffers to GLuint colorBuffer, //< Color buffer to render into int eyeIndex) { // Render to our framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObj); + /* glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObj); // Set color and depth buffers for the frame buffer glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorBuffer, 0); @@ -853,6 +913,7 @@ inline void RenderViewOpenGL( // delete[] data; // Draw a cube with a 5-meter radius as the room we are floating in. // draw_cube(5.0); + */ } #endif // SUPPORT_OPENGL @@ -868,19 +929,33 @@ inline void DoRender() { // Render into each buffer using the specified information. for (int i = 0; i < n; ++i) { RenderViewD3D11(s_renderInfo[i], - s_renderBuffers[i].D3D11->colorBufferView, i); + s_renderBuffers[i].colorBufferView, i); + } + + // Send the rendered results to the screen + OSVR_RenderManagerPresentState presentState; + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerStartPresentRenderBuffers( + &presentState))) { + DebugLog("[OSVR Rendering Plugin] Could not start presenting render buffers"); + ShutdownRenderManager(); + } + OSVR_ViewportDescription fullView; + fullView.left = fullView.lower = 0; + fullView.width = fullView.height = 1; + for (size_t i = 0; i < numRenderInfo; i++) { + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerPresentRenderBufferD3D11( + presentState, s_renderBuffers[i], s_renderInfo[i], fullView))) { + DebugLog("[OSVR Rendering Plugin] Could not present render buffer "); + ShutdownRenderManager(); + } + } + + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerFinishPresentRenderBuffers( + s_render, presentState, s_renderParams, false))) { + DebugLog("[OSVR Rendering Plugin] Could not finish presenting render buffers");; + ShutdownRenderManager(); } - // Send the rendered results to the screen - // Flip Y because Unity RenderTextures are upside-down on D3D11 - if (!s_render->PresentRenderBuffers( - s_renderBuffers, s_renderInfo, - osvr::renderkit::RenderManager::RenderParams(), - std::vector(), - true)) { - DebugLog("[OSVR Rendering Plugin] PresentRenderBuffers() returned " - "false, maybe because it was asked to quit"); - } break; } #endif // SUPPORT_D3D11 @@ -891,7 +966,7 @@ inline void DoRender() { //@todo OpenGL path is not working yet // Render into each buffer using the specified information. - for (int i = 0; i < n; ++i) { + /* for (int i = 0; i < n; ++i) { RenderViewOpenGL(s_renderInfo[i], s_frameBuffer, s_renderBuffers[i].OpenGL->colorBufferName, i); } @@ -901,7 +976,7 @@ inline void DoRender() { DebugLog("PresentRenderBuffers() returned false, maybe because " "it was asked to quit"); } - break; + break;*/ } #endif // SUPPORT_OPENGL diff --git a/OsvrRenderingPlugin.h b/OsvrRenderingPlugin.h index 57d79c2..aed78ec 100644 --- a/OsvrRenderingPlugin.h +++ b/OsvrRenderingPlugin.h @@ -26,6 +26,7 @@ Sensics, Inc. #include "Unity/IUnityGraphics.h" #include "Unity/IUnityInterface.h" #include +#include "osvr/RenderKit/RenderManagerC.h" #include #include #include @@ -48,14 +49,14 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context); UNITY_INTERFACE_EXPORT OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye); -UNITY_INTERFACE_EXPORT osvr::renderkit::OSVR_ProjectionMatrix +UNITY_INTERFACE_EXPORT OSVR_ProjectionMatrix UNITY_INTERFACE_API GetProjectionMatrix(std::uint8_t eye); UNITY_INTERFACE_EXPORT UnityRenderingEvent UNITY_INTERFACE_API GetRenderEventFunc(); -UNITY_INTERFACE_EXPORT osvr::renderkit::OSVR_ViewportDescription +UNITY_INTERFACE_EXPORT OSVR_ViewportDescription UNITY_INTERFACE_API GetViewport(std::uint8_t eye); From 6c731778e65edaa149c1907661e40d2d7bc3002a Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Thu, 9 Feb 2017 18:01:03 -0500 Subject: [PATCH 11/43] Corrects the upside-down image. --- OsvrRenderingPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index db0541e..275f0aa 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -951,7 +951,7 @@ inline void DoRender() { } if ((OSVR_RETURN_SUCCESS != osvrRenderManagerFinishPresentRenderBuffers( - s_render, presentState, s_renderParams, false))) { + s_render, presentState, s_renderParams, true))) { DebugLog("[OSVR Rendering Plugin] Could not finish presenting render buffers");; ShutdownRenderManager(); } From c17ed661ca73faf7404211b590641fc0aaeb7ac3 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Mon, 13 Feb 2017 04:42:54 -0500 Subject: [PATCH 12/43] Removes flickering issue when combined with Unity changes --- OsvrRenderingPlugin.cpp | 50 ++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 275f0aa..236c81d 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -21,8 +21,8 @@ Sensics, Inc. // limitations under the License. /// Both of these need to be enabled to force-enable logging to files. -#undef ENABLE_LOGGING -#undef ENABLE_LOGFILE +#define ENABLE_LOGGING 1 +#define ENABLE_LOGFILE 1 // Internal includes #include "OsvrRenderingPlugin.h" @@ -98,6 +98,10 @@ static double s_ipd = 0.063; static std::uint32_t viewportWidth = 0; static std::uint32_t viewportHeight = 0; +static OSVR_ProjectionMatrix lastGoodProjMatrix; +static OSVR_Pose3 lastGoodPose; +static OSVR_ViewportDescription lastGoodViewportDescription; + #if defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) static std::ofstream s_debugLogFile; static std::streambuf *s_oldCout = nullptr; @@ -149,12 +153,11 @@ inline void DebugLog(const char *str) { void UNITY_INTERFACE_API ShutdownRenderManager() { DebugLog("[OSVR Rendering Plugin] Shutting down RenderManager."); if (s_render != nullptr) { - delete s_render; - s_render = nullptr; - s_rightEyeTexturePtr = nullptr; - s_leftEyeTexturePtr = nullptr; + osvrDestroyRenderManager(s_render); + // s_rightEyeTexturePtr = nullptr; + // s_leftEyeTexturePtr = nullptr; } - s_clientContext = nullptr; + // s_clientContext = nullptr; } // -------------------------------------------------------------------------- @@ -324,6 +327,11 @@ void UNITY_INTERFACE_API UnityPluginUnload() { } inline void UpdateRenderInfo() { + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerGetNumRenderInfo( + s_render, s_renderParams, &numRenderInfo))) { + DebugLog("[OSVR Rendering Plugin] Could not get context number of render infos."); + ShutdownRenderManager(); + } s_renderInfo.clear(); for (OSVR_RenderInfoCount i = 0; i < numRenderInfo; i++) { OSVR_RenderInfoD3D11 info; @@ -516,14 +524,14 @@ inline OSVR_ReturnCode applyRenderBufferConstructor(const int numBuffers, G &&bufferCleanup) { /// If we bail any time before the end, we'll automatically clean up the /// render buffers with this lambda. - auto cleanupBuffers = osvr::util::finally([&] { + /* auto cleanupBuffers = osvr::util::finally([&] { DebugLog("[OSVR Rendering Plugin] Cleaning up render buffers."); - /*for (auto &rb : s_renderBuffers) { + for (auto &rb : s_renderBuffers) { bufferCleanup(rb); - }*/ + } s_renderBuffers.clear(); DebugLog("[OSVR Rendering Plugin] Render buffer cleanup complete."); - }); + });*/ /// Construct all the buffers as isntructed for (int i = 0; i < numBuffers; ++i) { @@ -542,6 +550,9 @@ inline OSVR_ReturnCode applyRenderBufferConstructor(const int numBuffers, }*/ // Register our constructed buffers so that we can use them for // presentation. + + UpdateRenderInfo(); + OSVR_RenderManagerRegisterBufferState registerBufferState; if ((OSVR_RETURN_SUCCESS != osvrRenderManagerStartRegisterRenderBuffers( ®isterBufferState))) { @@ -561,7 +572,7 @@ inline OSVR_ReturnCode applyRenderBufferConstructor(const int numBuffers, ShutdownRenderManager(); } /// Only if we succeed, do we cancel the cleanup and carry on. - cleanupBuffers.cancel(); + // cleanupBuffers.cancel(); return OSVR_RETURN_SUCCESS; } @@ -690,8 +701,8 @@ inline OSVR_ReturnCode ConstructBuffersD3D11(int eye) { } inline void CleanupBufferD3D11(OSVR_RenderBufferD3D11 &rb) { - // delete rb.D3D11; - //rb.D3D11 = nullptr; + delete &rb; + } #endif // SUPPORT_D3D11 @@ -757,31 +768,36 @@ GetViewport(std::uint8_t eye) { { viewportHeight = s_renderInfo[eye].viewport.height; } + lastGoodViewportDescription = viewportDescription; } else { //we shouldn't be here unless we hit a bug, in which case, we avoid error by returning cached viewport values std::string errorLog = "[OSVR Rendering Plugin] Error in GetViewport, returning cached values. Eye = " + std::to_string(int(eye)); DebugLog(errorLog.c_str()); - viewportDescription.left = 0; + /*viewportDescription.left = 0; viewportDescription.lower = 0; viewportDescription.width = viewportWidth; - viewportDescription.height = viewportHeight; + viewportDescription.height = viewportHeight;*/ + lastGoodViewportDescription = viewportDescription; } return viewportDescription; } + OSVR_ProjectionMatrix UNITY_INTERFACE_API GetProjectionMatrix(std::uint8_t eye) { OSVR_ProjectionMatrix pm; if (s_renderInfo.size() > 0 && eye <= s_renderInfo.size() - 1) { pm = s_renderInfo[eye].projection; + lastGoodProjMatrix = pm; } else { std::string errorLog = "[OSVR Rendering Plugin] Error in GetProjectionMatrix, returning default values. Eye = " + std::to_string(int(eye)); DebugLog(errorLog.c_str()); + pm = lastGoodProjMatrix; } return pm; } @@ -792,11 +808,13 @@ OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { if (s_renderInfo.size() > 0 && eye <= s_renderInfo.size() - 1) { pose = s_renderInfo[eye].pose; + lastGoodPose = pose; } else { std::string errorLog = "[OSVR Rendering Plugin] Error in GetEyePose, returning default values. Eye = " + std::to_string(int(eye)); DebugLog(errorLog.c_str()); + pose = lastGoodPose; } return pose; } From 0079f1fc2e569ddef42018e528c026e8fb78eb8d Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Thu, 16 Feb 2017 16:31:53 -0500 Subject: [PATCH 13/43] Update RenderInfoCollection. Shuts down properly. --- OsvrRenderingPlugin.cpp | 108 ++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 60 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 236c81d..761684c 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -84,7 +84,9 @@ static OSVR_RenderManagerD3D11 s_renderD3D = nullptr; static OSVR_ClientContext s_clientContext = nullptr; static std::vector s_renderBuffers; static std::vector s_renderInfo; +static std::vector s_lastRenderInfo; static OSVR_RenderInfoCount numRenderInfo; +static OSVR_RenderInfoCollection s_renderInfoCollection; static OSVR_GraphicsLibraryD3D11 s_libraryD3D; static void *s_leftEyeTexturePtr = nullptr; static void *s_rightEyeTexturePtr = nullptr; @@ -154,10 +156,11 @@ void UNITY_INTERFACE_API ShutdownRenderManager() { DebugLog("[OSVR Rendering Plugin] Shutting down RenderManager."); if (s_render != nullptr) { osvrDestroyRenderManager(s_render); - // s_rightEyeTexturePtr = nullptr; - // s_leftEyeTexturePtr = nullptr; + s_render = nullptr; + s_rightEyeTexturePtr = nullptr; + s_leftEyeTexturePtr = nullptr; } - // s_clientContext = nullptr; + s_clientContext = nullptr; } // -------------------------------------------------------------------------- @@ -326,24 +329,28 @@ void UNITY_INTERFACE_API UnityPluginUnload() { #endif // defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) } -inline void UpdateRenderInfo() { - if ((OSVR_RETURN_SUCCESS != osvrRenderManagerGetNumRenderInfo( - s_render, s_renderParams, &numRenderInfo))) { - DebugLog("[OSVR Rendering Plugin] Could not get context number of render infos."); +inline void UpdateRenderInfoCollection() { + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerGetRenderInfoCollection( + s_render, s_renderParams, &s_renderInfoCollection))) { + DebugLog("[OSVR Rendering Plugin] UpdateRenderInfo Could not get renderinfo collection."); ShutdownRenderManager(); } + osvrRenderManagerGetNumRenderInfoInCollection(s_renderInfoCollection, &numRenderInfo); + + //update renderinfo s_renderInfo.clear(); for (OSVR_RenderInfoCount i = 0; i < numRenderInfo; i++) { OSVR_RenderInfoD3D11 info; - if ((OSVR_RETURN_SUCCESS != osvrRenderManagerGetRenderInfoD3D11( - s_renderD3D, i, s_renderParams, &info))) { + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerGetRenderInfoFromCollectionD3D11( + s_renderInfoCollection, i, &info))) { DebugLog("[OSVR Rendering Plugin] Could not get render info."); - ShutdownRenderManager(); } s_renderInfo.push_back(info); } - // s_renderInfo = s_render->GetRenderInfo(s_renderParams); - //osvrRenderManagerGetRenderInfoD3D11(s_renderD3D) + if (s_renderInfo.size() > 0) + { + s_lastRenderInfo = s_renderInfo; + } } #if 0 @@ -397,19 +404,19 @@ void ClearRoomToWorldTransform() { /*s_render->ClearRoomToWorldTransform(); */} // Called from Unity to create a RenderManager, passing in a ClientContext OSVR_ReturnCode UNITY_INTERFACE_API CreateRenderManagerFromUnity(OSVR_ClientContext context) { - /// See if we're already created/running - shouldn't happen, but might. - /* if (s_render != nullptr) { - if (s_render->doingOkay()) { - DebugLog("[OSVR Rendering Plugin] RenderManager already created " - "and doing OK - will just return success without trying " - "to re-initialize."); - return OSVR_RETURN_SUCCESS; - } - DebugLog("[OSVR Rendering Plugin] RenderManager already created, " - "but not doing OK. Will shut down before creating again."); - ShutdownRenderManager(); - }*/ + if (s_render != nullptr) { + if (osvrRenderManagerGetDoingOkay(s_render)) { + DebugLog("[OSVR Rendering Plugin] RenderManager already created " + "and doing OK - will just return success without trying " + "to re-initialize."); + return OSVR_RETURN_SUCCESS; + } + + DebugLog("[OSVR Rendering Plugin] RenderManager already created, " + "but not doing OK. Will shut down before creating again."); + ShutdownRenderManager(); + } if (s_clientContext != nullptr) { DebugLog( "[OSVR Rendering Plugin] Client context already set! Replacing..."); @@ -424,11 +431,6 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context) { // the platform from Unity than assume it's D3D11. s_deviceType = kUnityGfxRendererD3D11; - - /* DebugLog("[OSVR Rendering Plugin] Attempted to create render manager, " - "but device type wasn't set (to a supported type) by the " - "plugin load/init routine. Order issue?"); - return OSVR_RETURN_FAILURE;*/ } bool setLibraryFromOpenDisplayReturn = false; @@ -458,6 +460,8 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context) { } if (s_render == nullptr) { + DebugLog("[OSVR Rendering Plugin] here we aer."); + DebugLog("[OSVR Rendering Plugin] Could not create RenderManager"); ShutdownRenderManager(); @@ -493,24 +497,8 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context) { // create a new set of RenderParams for passing to GetRenderInfo() osvrRenderManagerGetDefaultRenderParams(&s_renderParams); - if((OSVR_RETURN_SUCCESS != osvrRenderManagerGetNumRenderInfo( - s_render, s_renderParams, &numRenderInfo))) { - DebugLog("[OSVR Rendering Plugin] Could not get context number of render infos."); - ShutdownRenderManager(); - return OSVR_RETURN_FAILURE; - } - - //update renderinfo - s_renderInfo.clear(); - for (OSVR_RenderInfoCount i = 0; i < numRenderInfo; i++) { - OSVR_RenderInfoD3D11 info; - if ((OSVR_RETURN_SUCCESS != osvrRenderManagerGetRenderInfoD3D11( - s_renderD3D, i, s_renderParams, &info))) { - DebugLog("[OSVR Rendering Plugin] Could not get render info."); - ShutdownRenderManager(); - } - s_renderInfo.push_back(info); - } + + UpdateRenderInfoCollection(); DebugLog("[OSVR Rendering Plugin] CreateRenderManagerFromUnity Success!"); return OSVR_RETURN_SUCCESS; @@ -551,7 +539,7 @@ inline OSVR_ReturnCode applyRenderBufferConstructor(const int numBuffers, // Register our constructed buffers so that we can use them for // presentation. - UpdateRenderInfo(); + UpdateRenderInfoCollection(); OSVR_RenderManagerRegisterBufferState registerBufferState; if ((OSVR_RETURN_SUCCESS != osvrRenderManagerStartRegisterRenderBuffers( @@ -711,7 +699,7 @@ OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { DebugLog("[OSVR Rendering Plugin] Device type not supported."); return OSVR_RETURN_FAILURE; } - UpdateRenderInfo(); + UpdateRenderInfoCollection(); // construct buffers const int n = static_cast(s_renderInfo.size()); @@ -753,20 +741,20 @@ void UNITY_INTERFACE_API SetIPD(double ipdMeters) { OSVR_ViewportDescription UNITY_INTERFACE_API GetViewport(std::uint8_t eye) { OSVR_ViewportDescription viewportDescription; - if (s_renderInfo.size() > 0 && eye <= s_renderInfo.size() - 1) + if (s_lastRenderInfo.size() > 0 && eye <= s_lastRenderInfo.size() - 1) { - viewportDescription = s_renderInfo[eye].viewport; + viewportDescription = s_lastRenderInfo[eye].viewport; //cache the viewport width and height //patches issue where sometimes empty viewport is returned //@todo fix the real cause of why this method bugs out occasionally on some machines, more often on others - if (viewportWidth == 0 && s_renderInfo[eye].viewport.width != 0) + if (viewportWidth == 0 && s_lastRenderInfo[eye].viewport.width != 0) { - viewportWidth = s_renderInfo[eye].viewport.width; + viewportWidth = s_lastRenderInfo[eye].viewport.width; } - if (viewportHeight == 0 && s_renderInfo[eye].viewport.height != 0) + if (viewportHeight == 0 && s_lastRenderInfo[eye].viewport.height != 0) { - viewportHeight = s_renderInfo[eye].viewport.height; + viewportHeight = s_lastRenderInfo[eye].viewport.height; } lastGoodViewportDescription = viewportDescription; } @@ -788,9 +776,9 @@ GetViewport(std::uint8_t eye) { OSVR_ProjectionMatrix UNITY_INTERFACE_API GetProjectionMatrix(std::uint8_t eye) { OSVR_ProjectionMatrix pm; - if (s_renderInfo.size() > 0 && eye <= s_renderInfo.size() - 1) + if (s_lastRenderInfo.size() > 0 && eye <= s_lastRenderInfo.size() - 1) { - pm = s_renderInfo[eye].projection; + pm = s_lastRenderInfo[eye].projection; lastGoodProjMatrix = pm; } else @@ -805,9 +793,9 @@ GetProjectionMatrix(std::uint8_t eye) { OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { OSVR_Pose3 pose; osvrPose3SetIdentity(&pose); - if (s_renderInfo.size() > 0 && eye <= s_renderInfo.size() - 1) + if (s_lastRenderInfo.size() > 0 && eye <= s_lastRenderInfo.size() - 1) { - pose = s_renderInfo[eye].pose; + pose = s_lastRenderInfo[eye].pose; lastGoodPose = pose; } else @@ -1024,7 +1012,7 @@ void UNITY_INTERFACE_API OnRenderEvent(int eventID) { case kOsvrEventID_Shutdown: break; case kOsvrEventID_Update: - UpdateRenderInfo(); + UpdateRenderInfoCollection(); break; case kOsvrEventID_SetRoomRotationUsingHead: SetRoomRotationUsingHead(); From 5edd011e646f62680436e0fd6e0a40b8fef3a6d1 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Tue, 20 Jun 2017 16:24:37 -0400 Subject: [PATCH 14/43] cmake updates --- CMakeLists.txt | 23 +- cmake/CMakeBoostHelper.cmake | 42 ++ cmake/CompatibilityVersionFile-BASIC.cmake.in | 19 + .../CompatibilityVersionFile-CXX_ABI.cmake.in | 29 + ...mpatibilityVersionFile-CXX_LAYOUT.cmake.in | 16 + cmake/CompatibilityVersionFile-C_ABI.cmake.in | 16 + cmake/CopyImportedTarget.cmake | 32 + cmake/FindEigen3.cmake | 81 +++ cmake/FindJsonCpp.cmake | 153 ++--- cmake/FindOpenGLES2.cmake | 31 + cmake/FindSDL2.cmake | 34 +- cmake/FindVRPN.cmake | 156 +++++ cmake/FindWindowsSDK.cmake | 585 ++++++++++++++++++ cmake/Findliquidvr.cmake | 54 ++ cmake/Findnvapi.cmake | 109 ++++ cmake/Findquatlib.cmake | 104 ++++ cmake/GenerateCompatibilityVersionFile.cmake | 83 +++ cmake/GetGitRevisionDescription.cmake | 130 ++++ cmake/GetGitRevisionDescription.cmake.in | 41 ++ cmake/GetMSVCVersion.cmake | 127 ++++ cmake/PrintTargetProperties.cmake | 256 ++++++++ cmake/Version.cmake | 35 ++ cmake/osvrRenderManagerConfig.cmake | 112 ++++ ...RenderManagerConfigBuildTreeHints.cmake.in | 39 ++ ...svrRenderManagerConfigInstalledBoost.cmake | 16 + cmake/osvrStashMapConfig.cmake | 61 ++ 26 files changed, 2253 insertions(+), 131 deletions(-) create mode 100644 cmake/CMakeBoostHelper.cmake create mode 100644 cmake/CompatibilityVersionFile-BASIC.cmake.in create mode 100644 cmake/CompatibilityVersionFile-CXX_ABI.cmake.in create mode 100644 cmake/CompatibilityVersionFile-CXX_LAYOUT.cmake.in create mode 100644 cmake/CompatibilityVersionFile-C_ABI.cmake.in create mode 100644 cmake/CopyImportedTarget.cmake create mode 100644 cmake/FindEigen3.cmake create mode 100644 cmake/FindOpenGLES2.cmake create mode 100644 cmake/FindVRPN.cmake create mode 100644 cmake/FindWindowsSDK.cmake create mode 100644 cmake/Findliquidvr.cmake create mode 100644 cmake/Findnvapi.cmake create mode 100644 cmake/Findquatlib.cmake create mode 100644 cmake/GenerateCompatibilityVersionFile.cmake create mode 100644 cmake/GetGitRevisionDescription.cmake create mode 100644 cmake/GetGitRevisionDescription.cmake.in create mode 100644 cmake/GetMSVCVersion.cmake create mode 100644 cmake/PrintTargetProperties.cmake create mode 100644 cmake/Version.cmake create mode 100644 cmake/osvrRenderManagerConfig.cmake create mode 100644 cmake/osvrRenderManagerConfigBuildTreeHints.cmake.in create mode 100644 cmake/osvrRenderManagerConfigInstalledBoost.cmake create mode 100644 cmake/osvrStashMapConfig.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 5625b8f..10ae7e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,9 @@ cmake_minimum_required(VERSION 3.1.0) project(osvrUnityRenderingPlugin) +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + #----------------------------------------------------------------------------- # Local CMake Modules list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") @@ -17,11 +20,13 @@ find_package(osvr REQUIRED) # Add one of these libraries for each vendor that we've got a driver # for and add a No driver that tells that it is unavailable when we # don't find the driver library. -find_package(OpenGL REQUIRED) -find_package(GLEW REQUIRED) -find_package(Boost REQUIRED) +find_package(OpenGL) +find_package(OpenGLES2 REQUIRED) +find_package(GLEW) +find_package(Boost) find_package(osvrRenderManager REQUIRED) -find_package(JsonCpp REQUIRED) +find_package(JsonCpp) +find_package(SDL2) set (osvrUnityRenderingPlugin_SOURCES OsvrRenderingPlugin.h @@ -43,12 +48,20 @@ target_include_directories(osvrUnityRenderingPlugin PRIVATE ${Boost_INCLUDE_DIRS if (OPENGL_FOUND AND GLEW_FOUND) target_include_directories(osvrUnityRenderingPlugin PRIVATE ${OPENGL_INCLUDE_DIRS}) - target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} GLEW::GLEW JsonCpp::JsonCpp) + target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} GLEW::GLEW JsonCpp::JsonCpp SDL2::SDL2) # Handle static glew. if(GLEW_LIBRARY MATCHES ".*s.lib") target_compile_definitions(osvrUnityRenderingPlugin PRIVATE GLEW_STATIC) endif() endif() +if (OPENGL_FOUND) + target_include_directories(osvrUnityRenderingPlugin PRIVATE ${OPENGL_INCLUDE_DIRS}) + target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} JsonCpp::JsonCpp ) +endif() +if(OPENGLES2_FOUND) + target_include_directories(osvrUnityRenderingPlugin PRIVATE ${OPENGLES2_INCLUDE_DIR}) + target_link_libraries(osvrUnityRenderingPlugin PRIVATE ${OPENGLES2_LIBRARIES} JsonCpp::JsonCpp osvr::osvrClientKit osvrRenderManager::osvrRenderManager) +endif() # Install docs, license, sample config install(TARGETS diff --git a/cmake/CMakeBoostHelper.cmake b/cmake/CMakeBoostHelper.cmake new file mode 100644 index 0000000..f52bb13 --- /dev/null +++ b/cmake/CMakeBoostHelper.cmake @@ -0,0 +1,42 @@ +# Help CMake find recent Boost MSVC binaries without manual configuration. +if(MSVC) + if(NOT DEFINED Boost_USE_MULTITHREADED) + set(Boost_USE_MULTITHREADED ON) # Most common ABI + endif() +endif() + +# Function exists solely to introduce a new scope for CMAKE_MODULE_PATH +function(_boosthelper_includehelper) + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") + include(GetMSVCVersion) +endfunction() + +if(MSVC AND (NOT Boost_INCLUDE_DIR OR NOT Boost_LIBRARY_DIR)) + _boosthelper_includehelper() + get_msvc_major_minor_version(_vs_major _vs_minor) + if(CMAKE_CXX_SIZEOF_DATA_PTR EQUAL 8) + set(_libdir "lib64-msvc-${_vs_major}.${_vs_minor}") + else() + set(_libdir "lib32-msvc-${_vs_major}.${_vs_minor}") + endif() + + set(_haslibs) + if(EXISTS "c:/local") + # Get all versions, newest first. + file(GLOB _possibilities "c:/local/boost*") + list(REVERSE _possibilities) + foreach(DIR ${_possibilities}) + if(EXISTS "${DIR}/${_libdir}") + list(APPEND _haslibs "${DIR}") + endif() + endforeach() + if(_haslibs) + list(APPEND CMAKE_PREFIX_PATH ${_haslibs}) + find_package(Boost QUIET) + if(Boost_FOUND AND NOT Boost_LIBRARY_DIR) + set(BOOST_ROOT "${Boost_INCLUDE_DIR}" CACHE PATH "") + set(BOOST_LIBRARYDIR "${Boost_INCLUDE_DIR}/${_libdir}" CACHE PATH "") + endif() + endif() + endif() +endif() diff --git a/cmake/CompatibilityVersionFile-BASIC.cmake.in b/cmake/CompatibilityVersionFile-BASIC.cmake.in new file mode 100644 index 0000000..d2b97ba --- /dev/null +++ b/cmake/CompatibilityVersionFile-BASIC.cmake.in @@ -0,0 +1,19 @@ +# will always be the actual version one +# Wrapped in a macro because it's got a return before we want. +macro(_gcvf_version) + @GCVF_PREVIOUS_FILE@ +endmacro() +_gcvf_version() + + +if(NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "@CMAKE_SYSTEM_NAME@") + set(PACKAGE_VERSION "${PACKAGE_VERSION} (@CMAKE_SYSTEM_NAME@)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) + return() +endif() + +if(ANDROID AND NOT ("${ANDROID_ABI}" STREQUAL "@ANDROID_ABI@")) + set(PACKAGE_VERSION "${PACKAGE_VERSION} (Android @ANDROID_ABI@)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) + return() +endif() \ No newline at end of file diff --git a/cmake/CompatibilityVersionFile-CXX_ABI.cmake.in b/cmake/CompatibilityVersionFile-CXX_ABI.cmake.in new file mode 100644 index 0000000..f09043d --- /dev/null +++ b/cmake/CompatibilityVersionFile-CXX_ABI.cmake.in @@ -0,0 +1,29 @@ +@GCVF_PREVIOUS_FILE@ + +if(MSVC) + if(NOT "${MSVC_VERSION}" STREQUAL "@MSVC_VERSION@") + set(PACKAGE_VERSION "${PACKAGE_VERSION} (@GCVF_WIN_CXXLAYOUT@)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) + return() + endif() +endif() + +macro(_gcvf_compute_cxxabi _var _compilerid _compilerver) + set(${_var}) + if("${_compilerid}" STREQUAL "GNU" AND NOT ("${_compilerver}" STREQUAL "")) + if("${_compilerver}" VER_LESS 5.0) + # This is pre-gcc5, not compatible with post-gcc5 + set(${_var} "g++ < 5.0") + else() + set(${_var} "g++ >= 5.0") + endif() + endif() +endmacro() +_gcvr_compute_cxxabi(_installed_cxx "@CMAKE_CXX_COMPILER_ID@" "@CMAKE_CXX_COMPILER_VERSION@") +_gcvr_compute_cxxabi(_current_cxx "${CMAKE_CXX_COMPILER_ID}" "${CMAKE_CXX_COMPILER_VERSION}") + +# if(NOT "${_installed_cxx}" STREQUAL "${_current_cxx}") +# set(PACKAGE_VERSION "${PACKAGE_VERSION} (${_installed_cxx})") +# set(PACKAGE_VERSION_UNSUITABLE TRUE) +# return() +# endif() diff --git a/cmake/CompatibilityVersionFile-CXX_LAYOUT.cmake.in b/cmake/CompatibilityVersionFile-CXX_LAYOUT.cmake.in new file mode 100644 index 0000000..8f98a08 --- /dev/null +++ b/cmake/CompatibilityVersionFile-CXX_LAYOUT.cmake.in @@ -0,0 +1,16 @@ +@GCVF_PREVIOUS_FILE@ + +set(GCVF_WIN_CXXLAYOUT) +if(MSVC) + set(GCVF_WIN_CXXLAYOUT "MSVC") +elseif(MINGW) + set(GCVF_WIN_CXXLAYOUT "MinGW") +elseif(WIN32) + set(GCVF_WIN_CXXLAYOUT "other") +endif() + +if(NOT "@GCVF_WIN_CXXLAYOUT@" STREQUAL "${GCVF_WIN_CXXLAYOUT}") + set(PACKAGE_VERSION "${PACKAGE_VERSION} (@GCVF_WIN_CXXLAYOUT@)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) + return() +endif() diff --git a/cmake/CompatibilityVersionFile-C_ABI.cmake.in b/cmake/CompatibilityVersionFile-C_ABI.cmake.in new file mode 100644 index 0000000..656e90f --- /dev/null +++ b/cmake/CompatibilityVersionFile-C_ABI.cmake.in @@ -0,0 +1,16 @@ +@GCVF_PREVIOUS_FILE@ + +if(NOT ("${CMAKE_C_COMPILER_ABI}" STREQUAL "") AND NOT ("@CMAKE_C_COMPILER_ABI@" STREQUAL "")) + if(NOT "${CMAKE_C_COMPILER_ABI}" STREQUAL "@CMAKE_C_COMPILER_ABI@") + set(PACKAGE_VERSION "${PACKAGE_VERSION} (@CMAKE_C_COMPILER_ABI@)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) + return() + endif() +endif() + +if(NOT "${CMAKE_C_COMPILER_TARGET}" STREQUAL "@CMAKE_C_COMPILER_TARGET@") + set(PACKAGE_VERSION "${PACKAGE_VERSION} (@CMAKE_C_COMPILER_TARGET@)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) + return() +endif() +# todo anything for a C ABI beyond just "basic"? \ No newline at end of file diff --git a/cmake/CopyImportedTarget.cmake b/cmake/CopyImportedTarget.cmake new file mode 100644 index 0000000..fed23b4 --- /dev/null +++ b/cmake/CopyImportedTarget.cmake @@ -0,0 +1,32 @@ +# - Copy shared libraries from imported targets to the target build directory +# on Windows during post-build. Install them in all cases. +# +# copy_imported_targets( [ ...]) +# +# install_imported_target( +# +# Copyright Sensics, Inc. 2015. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +function(copy_imported_targets _target) + foreach(_dep ${ARGN}) + if(WIN32) + add_custom_command(TARGET ${_target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ $ + COMMENT "Copying required DLL for dependency ${_dep}" + VERBATIM) + endif() + endforeach() +endfunction() + + +function(install_imported_target _dep) + install(FILES $ ${ARGN}) +endfunction() diff --git a/cmake/FindEigen3.cmake b/cmake/FindEigen3.cmake new file mode 100644 index 0000000..9c546a0 --- /dev/null +++ b/cmake/FindEigen3.cmake @@ -0,0 +1,81 @@ +# - Try to find Eigen3 lib +# +# This module supports requiring a minimum version, e.g. you can do +# find_package(Eigen3 3.1.2) +# to require version 3.1.2 or newer of Eigen3. +# +# Once done this will define +# +# EIGEN3_FOUND - system has eigen lib with correct version +# EIGEN3_INCLUDE_DIR - the eigen include directory +# EIGEN3_VERSION - eigen version + +# Copyright (c) 2006, 2007 Montel Laurent, +# Copyright (c) 2008, 2009 Gael Guennebaud, +# Copyright (c) 2009 Benoit Jacob +# Redistribution and use is allowed according to the terms of the 2-clause BSD license. + +if(NOT Eigen3_FIND_VERSION) + if(NOT Eigen3_FIND_VERSION_MAJOR) + set(Eigen3_FIND_VERSION_MAJOR 2) + endif(NOT Eigen3_FIND_VERSION_MAJOR) + if(NOT Eigen3_FIND_VERSION_MINOR) + set(Eigen3_FIND_VERSION_MINOR 91) + endif(NOT Eigen3_FIND_VERSION_MINOR) + if(NOT Eigen3_FIND_VERSION_PATCH) + set(Eigen3_FIND_VERSION_PATCH 0) + endif(NOT Eigen3_FIND_VERSION_PATCH) + + set(Eigen3_FIND_VERSION "${Eigen3_FIND_VERSION_MAJOR}.${Eigen3_FIND_VERSION_MINOR}.${Eigen3_FIND_VERSION_PATCH}") +endif(NOT Eigen3_FIND_VERSION) + +macro(_eigen3_check_version) + file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header) + + string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}") + set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen3_major_version_match "${_eigen3_version_header}") + set(EIGEN3_MAJOR_VERSION "${CMAKE_MATCH_1}") + string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen3_minor_version_match "${_eigen3_version_header}") + set(EIGEN3_MINOR_VERSION "${CMAKE_MATCH_1}") + + set(EIGEN3_VERSION ${EIGEN3_WORLD_VERSION}.${EIGEN3_MAJOR_VERSION}.${EIGEN3_MINOR_VERSION}) + if(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) + set(EIGEN3_VERSION_OK FALSE) + else(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) + set(EIGEN3_VERSION_OK TRUE) + endif(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION}) + + if(NOT EIGEN3_VERSION_OK) + + message(STATUS "Eigen3 version ${EIGEN3_VERSION} found in ${EIGEN3_INCLUDE_DIR}, " + "but at least version ${Eigen3_FIND_VERSION} is required") + endif(NOT EIGEN3_VERSION_OK) +endmacro(_eigen3_check_version) + +if (EIGEN3_INCLUDE_DIR) + + # in cache already + _eigen3_check_version() + set(EIGEN3_FOUND ${EIGEN3_VERSION_OK}) + +else (EIGEN3_INCLUDE_DIR) + + find_path(EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library + PATHS + ${CMAKE_INSTALL_PREFIX}/include + ${KDE4_INCLUDE_DIR} + PATH_SUFFIXES eigen3 eigen + ) + + if(EIGEN3_INCLUDE_DIR) + _eigen3_check_version() + endif(EIGEN3_INCLUDE_DIR) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK) + + mark_as_advanced(EIGEN3_INCLUDE_DIR) + +endif(EIGEN3_INCLUDE_DIR) + diff --git a/cmake/FindJsonCpp.cmake b/cmake/FindJsonCpp.cmake index a625647..2f66845 100644 --- a/cmake/FindJsonCpp.cmake +++ b/cmake/FindJsonCpp.cmake @@ -46,10 +46,8 @@ macro(_jsoncpp_check_for_real_jsoncpplib) set(__jsoncpp_have_jsoncpplib FALSE) if(TARGET jsoncpp_lib) get_property(__jsoncpp_lib_type TARGET jsoncpp_lib PROPERTY TYPE) - #message(STATUS "__jsoncpp_lib_type ${__jsoncpp_lib_type}") # We make interface libraries. If an actual config module made it, it would be an imported library. if(NOT __jsoncpp_lib_type STREQUAL "INTERFACE_LIBRARY") - #message("have jsoncpp_lib and we didn't invent it ourselves") set(__jsoncpp_have_jsoncpplib TRUE) endif() endif() @@ -59,106 +57,61 @@ include(FindPackageHandleStandardArgs) # Ensure that if this is TRUE later, it's because we set it. set(JSONCPP_FOUND FALSE) -# See if we find a CMake config file - there is no harm in calling this more than once, -# and we need to call it at least once every CMake invocation to create the original -# imported targets, since those don't stick around like cache variables. +# See if we find a CMake config file. find_package(jsoncpp QUIET NO_MODULE) -if(jsoncpp_FOUND) - # Build a string to help us figure out when to invalidate our cache variables. - # start with where we found jsoncpp - set(__jsoncpp_info_string "[${jsoncpp_DIR}]") - - # part of the string to indicate if we found a real jsoncpp_lib (and what kind) - _jsoncpp_check_for_real_jsoncpplib() - if(__jsoncpp_have_jsoncpplib) - list(APPEND __jsoncpp_info_string "[${__jsoncpp_lib_type}]") - else() - list(APPEND __jsoncpp_info_string "[]") - endif() - # part of the string to indicate if we found jsoncpp_lib_static - if(TARGET jsoncpp_lib_static) - list(APPEND __jsoncpp_info_string "[T]") - else() - list(APPEND __jsoncpp_info_string "[]") - endif() -endif() - - -# If we found something, and it's not the exact same as what we've found before... -# NOTE: The contents of this "if" block update only (internal) cache variables! -# (since this will only get run the first CMake pass that finds jsoncpp or that finds a different/updated install) -if(jsoncpp_FOUND AND NOT __jsoncpp_info_string STREQUAL "${JSONCPP_CACHED_JSONCPP_DIR_DETAILS}") - #message("Updating jsoncpp cache variables! ${__jsoncpp_info_string}") - set(JSONCPP_CACHED_JSONCPP_DIR_DETAILS "${__jsoncpp_info_string}" CACHE INTERNAL "" FORCE) - unset(JSONCPP_IMPORTED_LIBRARY_SHARED) - unset(JSONCPP_IMPORTED_LIBRARY_STATIC) - unset(JSONCPP_IMPORTED_LIBRARY) - unset(JSONCPP_IMPORTED_INCLUDE_DIRS) - unset(JSONCPP_IMPORTED_LIBRARY_IS_SHARED) - - # if(__jsoncpp_have_jsoncpplib) is equivalent to if(TARGET jsoncpp_lib) except it excludes our - # "invented" jsoncpp_lib interface targets, made for convenience purposes after this block. - - if(__jsoncpp_have_jsoncpplib AND TARGET jsoncpp_lib_static) - - # A veritable cache of riches - we have both shared and static! - set(JSONCPP_IMPORTED_LIBRARY_SHARED jsoncpp_lib CACHE INTERNAL "" FORCE) - set(JSONCPP_IMPORTED_LIBRARY_STATIC jsoncpp_lib_static CACHE INTERNAL "" FORCE) - if(WIN32 OR CYGWIN OR MINGW) - # DLL platforms: static library should be default - set(JSONCPP_IMPORTED_LIBRARY ${JSONCPP_IMPORTED_LIBRARY_STATIC} CACHE INTERNAL "" FORCE) +# We will always try first to get a config file. +if(NOT JSONCPP_IMPORTED_LIBRARY) + if(jsoncpp_FOUND) + # OK, so we found something. + unset(JSONCPP_IMPORTED_LIBRARY_IS_SHARED) + _jsoncpp_check_for_real_jsoncpplib() + if(__jsoncpp_have_jsoncpplib AND TARGET jsoncpp_lib_static) + # A veritable cache of riches - we have both shared and static! + set(JSONCPP_IMPORTED_LIBRARY_SHARED jsoncpp_lib CACHE INTERNAL "" FORCE) + set(JSONCPP_IMPORTED_LIBRARY_STATIC jsoncpp_lib_static CACHE INTERNAL "" FORCE) + if(WIN32 OR CYGWIN OR MINGW) + # DLL platforms: static library should be default + set(JSONCPP_IMPORTED_LIBRARY ${JSONCPP_IMPORTED_LIBRARY_STATIC} CACHE INTERNAL "" FORCE) + set(JSONCPP_IMPORTED_LIBRARY_IS_SHARED FALSE CACHE INTERNAL "" FORCE) + else() + # Other platforms - might require PIC to be linked into shared libraries, so safest to prefer shared. + set(JSONCPP_IMPORTED_LIBRARY ${JSONCPP_IMPORTED_LIBRARY_SHARED} CACHE INTERNAL "" FORCE) + set(JSONCPP_IMPORTED_LIBRARY_IS_SHARED TRUE CACHE INTERNAL "" FORCE) + endif() + elseif(TARGET jsoncpp_lib_static) + # Well, only one variant, but we know for sure that it's static. + set(JSONCPP_IMPORTED_LIBRARY_STATIC jsoncpp_lib_static CACHE INTERNAL "" FORCE) + set(JSONCPP_IMPORTED_LIBRARY jsoncpp_lib_static CACHE INTERNAL "" FORCE) set(JSONCPP_IMPORTED_LIBRARY_IS_SHARED FALSE CACHE INTERNAL "" FORCE) - else() - # Other platforms - might require PIC to be linked into shared libraries, so safest to prefer shared. - set(JSONCPP_IMPORTED_LIBRARY ${JSONCPP_IMPORTED_LIBRARY_SHARED} CACHE INTERNAL "" FORCE) - set(JSONCPP_IMPORTED_LIBRARY_IS_SHARED TRUE CACHE INTERNAL "" FORCE) + elseif(TARGET __jsoncpp_have_jsoncpplib) + # One variant, and we have no idea if this is just an old version or if + # this is shared based on the target name alone. Hmm. + # TODO figure out if this is shared or static? + set(JSONCPP_IMPORTED_LIBRARY jsoncpp_lib CACHE INTERNAL "" FORCE) endif() - elseif(TARGET jsoncpp_lib_static) - # Well, only one variant, but we know for sure that it's static. - set(JSONCPP_IMPORTED_LIBRARY_STATIC jsoncpp_lib_static CACHE INTERNAL "" FORCE) - set(JSONCPP_IMPORTED_LIBRARY jsoncpp_lib_static CACHE INTERNAL "" FORCE) - set(JSONCPP_IMPORTED_LIBRARY_IS_SHARED FALSE CACHE INTERNAL "" FORCE) - - elseif(__jsoncpp_have_jsoncpplib AND __jsoncpp_lib_type STREQUAL "STATIC_LIBRARY") - # We were able to figure out the mystery library is static! - set(JSONCPP_IMPORTED_LIBRARY_STATIC jsoncpp_lib CACHE INTERNAL "" FORCE) - set(JSONCPP_IMPORTED_LIBRARY jsoncpp_lib CACHE INTERNAL "" FORCE) - set(JSONCPP_IMPORTED_LIBRARY_IS_SHARED FALSE CACHE INTERNAL "" FORCE) - - elseif(__jsoncpp_have_jsoncpplib AND __jsoncpp_lib_type STREQUAL "SHARED_LIBRARY") - # We were able to figure out the mystery library is shared! - set(JSONCPP_IMPORTED_LIBRARY_SHARED jsoncpp_lib CACHE INTERNAL "" FORCE) - set(JSONCPP_IMPORTED_LIBRARY jsoncpp_lib CACHE INTERNAL "" FORCE) - set(JSONCPP_IMPORTED_LIBRARY_IS_SHARED TRUE CACHE INTERNAL "" FORCE) - - elseif(__jsoncpp_have_jsoncpplib) - # One variant, and we have no idea if this is just an old version or if - # this is shared based on the target name alone. Hmm. - set(JSONCPP_IMPORTED_LIBRARY jsoncpp_lib CACHE INTERNAL "" FORCE) - endif() - - # Now, we need include directories. Can't just limit this to old CMakes, since - # new CMakes might be used to build projects designed to support older ones. - if(__jsoncpp_have_jsoncpplib) - get_property(__jsoncpp_interface_include_dirs TARGET jsoncpp_lib PROPERTY INTERFACE_INCLUDE_DIRECTORIES) - if(__jsoncpp_interface_include_dirs) - set(JSONCPP_IMPORTED_INCLUDE_DIRS "${__jsoncpp_interface_include_dirs}" CACHE INTERNAL "" FORCE) + # Now, we need include directories. Can't just limit this to old CMakes, since + # new CMakes might be used to build projects designed to support older ones. + if(__jsoncpp_have_jsoncpplib) + get_property(__jsoncpp_interface_include_dirs TARGET jsoncpp_lib PROPERTY INTERFACE_INCLUDE_DIRECTORIES) + if(__jsoncpp_interface_include_dirs) + set(JSONCPP_IMPORTED_INCLUDE_DIRS "${__jsoncpp_interface_include_dirs}" CACHE INTERNAL "" FORCE) + endif() endif() - endif() - if(TARGET jsoncpp_lib_static AND NOT JSONCPP_IMPORTED_INCLUDE_DIRS) - get_property(__jsoncpp_interface_include_dirs TARGET jsoncpp_lib_static PROPERTY INTERFACE_INCLUDE_DIRECTORIES) - if(__jsoncpp_interface_include_dirs) - set(JSONCPP_IMPORTED_INCLUDE_DIRS "${__jsoncpp_interface_include_dirs}" CACHE INTERNAL "" FORCE) + if(TARGET jsoncpp_lib_static AND NOT JSONCPP_IMPORTED_INCLUDE_DIRS) + get_property(__jsoncpp_interface_include_dirs TARGET jsoncpp_lib_static PROPERTY INTERFACE_INCLUDE_DIRECTORIES) + if(__jsoncpp_interface_include_dirs) + set(JSONCPP_IMPORTED_INCLUDE_DIRS "${__jsoncpp_interface_include_dirs}" CACHE INTERNAL "" FORCE) + endif() endif() - endif() -endif() -# As a convenience... -if(TARGET jsoncpp_lib_static AND NOT TARGET jsoncpp_lib) - add_library(jsoncpp_lib INTERFACE) - target_link_libraries(jsoncpp_lib INTERFACE jsoncpp_lib_static) + # As a convenience... + if(TARGET jsoncpp_lib_static AND NOT TARGET jsoncpp_lib) + add_library(jsoncpp_lib INTERFACE) + target_link_libraries(jsoncpp_lib INTERFACE jsoncpp_lib_static) + endif() + endif() endif() if(JSONCPP_IMPORTED_LIBRARY) @@ -193,7 +146,6 @@ if(JSONCPP_IMPORTED_LIBRARY) find_package_handle_standard_args(JsonCpp DEFAULT_MSG - jsoncpp_DIR JSONCPP_IMPORTED_LIBRARY JSONCPP_IMPORTED_INCLUDE_DIRS) endif() @@ -221,14 +173,6 @@ if(JSONCPP_FOUND) INTERFACE_INCLUDE_DIRECTORIES "${JSONCPP_IMPORTED_INCLUDE_DIRS}" INTERFACE_LINK_LIBRARIES "${JSONCPP_IMPORTED_LIBRARY_STATIC}") endif() - - # Hide the stuff we didn't, and no longer, need. - if(NOT JsonCpp_LIBRARY) - unset(JsonCpp_LIBRARY CACHE) - endif() - if(NOT JsonCpp_INCLUDE_DIR) - unset(JsonCpp_INCLUDE_DIR CACHE) - endif() endif() set(JSONCPP_LIBRARY ${JSONCPP_IMPORTED_LIBRARY}) @@ -364,9 +308,10 @@ if(NOT JSONCPP_FOUND) add_library(JsonCpp::JsonCpp ALIAS jsoncpp_interface) endif() endif() + mark_as_advanced(JsonCpp_INCLUDE_DIR JsonCpp_LIBRARY) endif() endif() if(JSONCPP_FOUND) - mark_as_advanced(jsoncpp_DIR JsonCpp_INCLUDE_DIR JsonCpp_LIBRARY) + mark_as_advanced(jsoncpp_DIR) endif() diff --git a/cmake/FindOpenGLES2.cmake b/cmake/FindOpenGLES2.cmake new file mode 100644 index 0000000..c9307b7 --- /dev/null +++ b/cmake/FindOpenGLES2.cmake @@ -0,0 +1,31 @@ +# - Find OpenGLES2 +# Find the native OpenGLES2 includes and libraries +# +# OPENGLES2_INCLUDE_DIR - where to find GLES2/gl2.h, etc. +# OPENGLES2_LIBRARIES - List of libraries when using OpenGLES2. +# OPENGLES2_FOUND - True if OpenGLES2 found. + +# Downloaded from +# https://sourceforge.net/p/alleg/allegro/ci/5.1/tree/cmake/FindOpenGLES.cmake +# Modified to use the v2 library rather than the v1 library. + +if(OPENGLES2_INCLUDE_DIR) + # Already in cache, be silent + set(OPENGLES2_FIND_QUIETLY TRUE) +endif(OPENGLES2_INCLUDE_DIR) + +find_path(OPENGLES2_INCLUDE_DIR GLES2/gl2.h) + +find_library(OPENGLES2_gl_LIBRARY NAMES GLESv2) + +# Handle the QUIETLY and REQUIRED arguments and set OPENGLES_FOUND +# to TRUE if all listed variables are TRUE. +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(OPENGLES2 DEFAULT_MSG + OPENGLES2_INCLUDE_DIR OPENGLES2_gl_LIBRARY) + +set(OPENGLES2_LIBRARIES ${OPENGLES2_gl_LIBRARY}) + +mark_as_advanced(OPENGLES2_INCLUDE_DIR) +mark_as_advanced(OPENGLES2_gl_LIBRARY) + diff --git a/cmake/FindSDL2.cmake b/cmake/FindSDL2.cmake index f69c68a..9a35dbf 100644 --- a/cmake/FindSDL2.cmake +++ b/cmake/FindSDL2.cmake @@ -16,25 +16,18 @@ # Set up architectures (for windows) and prefixes (for mingw builds) if(WIN32) - if(MINGW) - include(MinGWSearchPathExtras OPTIONAL) - if(MINGWSEARCH_TARGET_TRIPLE) - set(SDL2_PREFIX ${MINGWSEARCH_TARGET_TRIPLE}) - endif() - endif() if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(SDL2_LIB_PATH_SUFFIX lib/x64) - if(NOT MSVC AND NOT SDL2_PREFIX) + if(NOT MSVC) set(SDL2_PREFIX x86_64-w64-mingw32) endif() else() set(SDL2_LIB_PATH_SUFFIX lib/x86) - if(NOT MSVC AND NOT SDL2_PREFIX) + if(NOT MSVC) set(SDL2_PREFIX i686-w64-mingw32) endif() endif() endif() - if(SDL2_PREFIX) set(SDL2_ORIGPREFIXPATH ${CMAKE_PREFIX_PATH}) if(SDL2_ROOT_DIR) @@ -45,9 +38,6 @@ if(SDL2_PREFIX) list(APPEND CMAKE_PREFIX_PATH "${_prefix}/${SDL2_PREFIX}") endforeach() endif() - if(MINGWSEARCH_PREFIXES) - list(APPEND CMAKE_PREFIX_PATH ${MINGWSEARCH_PREFIXES}) - endif() endif() # Invoke pkgconfig for hints @@ -192,15 +182,15 @@ if(SDL2_FOUND) ) endif() - if(APPLE) - # Need Cocoa here, is always a framework - find_library(SDL2_COCOA_LIBRARY Cocoa) - list(APPEND SDL2_EXTRA_REQUIRED SDL2_COCOA_LIBRARY) - if(SDL2_COCOA_LIBRARY) - set_target_properties(SDL2::SDL2 PROPERTIES - IMPORTED_LINK_INTERFACE_LIBRARIES ${SDL2_COCOA_LIBRARY}) - endif() - endif() + if(APPLE) + # Need Cocoa here, is always a framework + find_library(SDL2_COCOA_LIBRARY Cocoa) + list(APPEND SDL2_EXTRA_REQUIRED SDL2_COCOA_LIBRARY) + if(SDL2_COCOA_LIBRARY) + set_target_properties(SDL2::SDL2 PROPERTIES + IMPORTED_LINK_INTERFACE_LIBRARIES ${SDL2_COCOA_LIBRARY}) + endif() + endif() # Compute what to do with SDL2main @@ -211,7 +201,7 @@ if(SDL2_FOUND) set_target_properties(SDL2::SDL2main_real PROPERTIES IMPORTED_LOCATION "${SDL2_SDLMAIN_LIBRARY}") - set(SDL2MAIN_LIBRARIES SDL2::SDL2main_real ${SDL2MAIN_LIBRARIES}) + list(APPEND SDL2MAIN_LIBRARIES SDL2::SDL2main_real) endif() if(MINGW) # MinGW requires some additional libraries to appear earlier in the link line. diff --git a/cmake/FindVRPN.cmake b/cmake/FindVRPN.cmake new file mode 100644 index 0000000..641b62b --- /dev/null +++ b/cmake/FindVRPN.cmake @@ -0,0 +1,156 @@ +# - try to find VRPN library +# +# Cache Variables: +# VRPN_LIBRARY +# VRPN_SERVER_LIBRARY +# VRPN_INCLUDE_DIR +# +# Non-cache variables you might use in your CMakeLists.txt: +# VRPN_FOUND +# VRPN_SERVER_LIBRARIES - server libraries +# VRPN_LIBRARIES - client libraries +# VRPN_CLIENT_DEFINITIONS - definitions if you only use the client library +# VRPN_DEFINITIONS - Client-only definition if all we found was the client library. +# VRPN_INCLUDE_DIRS +# +# VRPN_ROOT_DIR is searched preferentially for these files +# +# Requires these CMake modules: +# FindPackageHandleStandardArgs (known included with CMake >=2.6.2) +# +# Original Author: +# 2009-2012 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2012. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +set(VRPN_ROOT_DIR + "${VRPN_ROOT_DIR}" + CACHE + PATH + "Root directory to search for VRPN") + +if("${CMAKE_SIZEOF_VOID_P}" MATCHES "8") + set(_libsuffixes lib64 lib) + + # 64-bit dir: only set on win64 + file(TO_CMAKE_PATH "$ENV{ProgramW6432}" _progfiles) +else() + set(_libsuffixes lib) + set(_PF86 "ProgramFiles(x86)") + if(NOT "$ENV{${_PF86}}" STREQUAL "") + # 32-bit dir: only set on win64 + file(TO_CMAKE_PATH "$ENV{${_PF86}}" _progfiles) + else() + # 32-bit dir on win32, useless to us on win64 + file(TO_CMAKE_PATH "$ENV{ProgramFiles}" _progfiles) + endif() +endif() + +set(_vrpn_quiet) +if(VRPN_FIND_QUIETLY) + set(_vrpn_quiet QUIET) +endif() + +### +# Configure VRPN +### + +find_path(VRPN_INCLUDE_DIR + NAMES + vrpn_Connection.h + PATH_SUFFIXES + include + include/vrpn + HINTS + "${VRPN_ROOT_DIR}" + PATHS + "${_progfiles}/VRPN" + C:/usr/local + /usr/local) + +find_library(VRPN_LIBRARY + NAMES + vrpn + PATH_SUFFIXES + ${_libsuffixes} + HINTS + "${VRPN_ROOT_DIR}" + PATHS + "${_progfiles}/VRPN" + C:/usr/local + /usr/local) + +find_library(VRPN_SERVER_LIBRARY + NAMES + vrpnserver + PATH_SUFFIXES + ${_libsuffixes} + HINTS + "${VRPN_ROOT_DIR}" + PATHS + "${_progfiles}/VRPN" + C:/usr/local + /usr/local) + +### +# Dependencies +### +set(_deps_libs) +set(_deps_includes) +set(_deps_check) + +find_package(quatlib ${_vrpn_quiet}) +list(APPEND _deps_libs ${QUATLIB_LIBRARIES}) +list(APPEND _deps_includes ${QUATLIB_INCLUDE_DIRS}) +list(APPEND _deps_check QUATLIB_FOUND) + +if(NOT WIN32) + find_package(Threads ${_vrpn_quiet}) + list(APPEND _deps_libs ${CMAKE_THREAD_LIBS_INIT}) + list(APPEND _deps_check CMAKE_HAVE_THREADS_LIBRARY) +endif() + +if(WIN32) + find_package(Libusb1 QUIET) + if(LIBUSB1_FOUND) + list(APPEND _deps_libs ${LIBUSB1_LIBRARIES}) + list(APPEND _deps_includes ${LIBUSB1_INCLUDE_DIRS}) + endif() +endif() + + +# handle the QUIETLY and REQUIRED arguments and set xxx_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(VRPN + DEFAULT_MSG + VRPN_LIBRARY + VRPN_INCLUDE_DIR + ${_deps_check}) + +if(VRPN_FOUND) + set(VRPN_INCLUDE_DIRS "${VRPN_INCLUDE_DIR}" ${_deps_includes}) + set(VRPN_LIBRARIES "${VRPN_LIBRARY}" ${_deps_libs}) + set(VRPN_SERVER_LIBRARIES "${VRPN_SERVER_LIBRARY}" ${_deps_libs}) + + if(VRPN_LIBRARY) + set(VRPN_CLIENT_DEFINITIONS -DVRPN_CLIENT_ONLY) + else() + unset(VRPN_CLIENT_DEFINITIONS) + endif() + + if(VRPN_LIBRARY AND NOT VRPN_SERVER_LIBRARY) + set(VRPN_DEFINITIONS -DVRPN_CLIENT_ONLY) + else() + unset(VRPN_DEFINITIONS) + endif() + + mark_as_advanced(VRPN_ROOT_DIR) +endif() + +mark_as_advanced(VRPN_LIBRARY VRPN_SERVER_LIBRARY VRPN_INCLUDE_DIR) diff --git a/cmake/FindWindowsSDK.cmake b/cmake/FindWindowsSDK.cmake new file mode 100644 index 0000000..17d9342 --- /dev/null +++ b/cmake/FindWindowsSDK.cmake @@ -0,0 +1,585 @@ +# - Find the Windows SDK aka Platform SDK +# +# Relevant Wikipedia article: http://en.wikipedia.org/wiki/Microsoft_Windows_SDK +# +# Pass "COMPONENTS tools" to ignore Visual Studio version checks: in case +# you just want the tool binaries to run, rather than the libraries and headers +# for compiling. +# +# Variables: +# WINDOWSSDK_FOUND - if any version of the windows or platform SDK was found that is usable with the current version of visual studio +# WINDOWSSDK_LATEST_DIR +# WINDOWSSDK_LATEST_NAME +# WINDOWSSDK_FOUND_PREFERENCE - if we found an entry indicating a "preferred" SDK listed for this visual studio version +# WINDOWSSDK_PREFERRED_DIR +# WINDOWSSDK_PREFERRED_NAME +# +# WINDOWSSDK_DIRS - contains no duplicates, ordered most recent first. +# WINDOWSSDK_PREFERRED_FIRST_DIRS - contains no duplicates, ordered with preferred first, followed by the rest in descending recency +# +# Functions: +# windowssdk_name_lookup( ) - Find the name corresponding with the SDK directory you pass in, or +# NOTFOUND if not recognized. Your directory must be one of WINDOWSSDK_DIRS for this to work. +# +# windowssdk_build_lookup( ) - Find the build version number corresponding with the SDK directory you pass in, or +# NOTFOUND if not recognized. Your directory must be one of WINDOWSSDK_DIRS for this to work. +# +# get_windowssdk_from_component( ) - Given a library or include dir, +# find the Windows SDK root dir corresponding to it, or NOTFOUND if unrecognized. +# +# get_windowssdk_library_dirs( ) - Find the architecture-appropriate +# library directories corresponding to the SDK directory you pass in (or NOTFOUND if none) +# +# get_windowssdk_include_dirs( ) - Find the +# include directories corresponding to the SDK directory you pass in (or NOTFOUND if none) +# +# Requires these CMake modules: +# FindPackageHandleStandardArgs (known included with CMake >=2.6.2) +# +# Original Author: +# 2012 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2012. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +set(_preferred_sdk_dirs) # pre-output +set(_win_sdk_dirs) # pre-output +set(_win_sdk_versanddirs) # pre-output +set(_win_sdk_buildsanddirs) # pre-output +set(_winsdk_vistaonly) # search parameters +set(_winsdk_kits) # search parameters + + +set(_WINDOWSSDK_ANNOUNCE OFF) +if(NOT WINDOWSSDK_FOUND AND (NOT WindowsSDK_FIND_QUIETLY)) + set(_WINDOWSSDK_ANNOUNCE ON) +endif() +macro(_winsdk_announce) + if(_WINSDK_ANNOUNCE) + message(STATUS ${ARGN}) + endif() +endmacro() + +set(_winsdk_win10vers + 10.0.10586.0 # TH2 aka Win10 1511 + 10.0.10240.0 # Win10 RTM + 10.0.10150.0 # just ucrt + 10.0.10056.0 +) + +if(WindowsSDK_FIND_COMPONENTS MATCHES "tools") + set(_WINDOWSSDK_IGNOREMSVC ON) + _winsdk_announce("Checking for tools from Windows/Platform SDKs...") +else() + set(_WINDOWSSDK_IGNOREMSVC OFF) + _winsdk_announce("Checking for Windows/Platform SDKs...") +endif() + +# Appends to the three main pre-output lists used only if the path exists +# and is not already in the list. +function(_winsdk_conditional_append _vername _build _path) + if(("${_path}" MATCHES "registry") OR (NOT EXISTS "${_path}")) + # Path invalid - do not add + return() + endif() + list(FIND _win_sdk_dirs "${_path}" _win_sdk_idx) + if(_win_sdk_idx GREATER -1) + # Path already in list - do not add + return() + endif() + _winsdk_announce( " - ${_vername}, Build ${_build} @ ${_path}") + # Not yet in the list, so we'll add it + list(APPEND _win_sdk_dirs "${_path}") + set(_win_sdk_dirs "${_win_sdk_dirs}" CACHE INTERNAL "" FORCE) + list(APPEND + _win_sdk_versanddirs + "${_vername}" + "${_path}") + set(_win_sdk_versanddirs "${_win_sdk_versanddirs}" CACHE INTERNAL "" FORCE) + list(APPEND + _win_sdk_buildsanddirs + "${_build}" + "${_path}") + set(_win_sdk_buildsanddirs "${_win_sdk_buildsanddirs}" CACHE INTERNAL "" FORCE) +endfunction() + +# Appends to the "preferred SDK" lists only if the path exists +function(_winsdk_conditional_append_preferred _info _path) + if(("${_path}" MATCHES "registry") OR (NOT EXISTS "${_path}")) + # Path invalid - do not add + return() + endif() + + get_filename_component(_path "${_path}" ABSOLUTE) + + list(FIND _win_sdk_preferred_sdk_dirs "${_path}" _win_sdk_idx) + if(_win_sdk_idx GREATER -1) + # Path already in list - do not add + return() + endif() + _winsdk_announce( " - Found \"preferred\" SDK ${_info} @ ${_path}") + # Not yet in the list, so we'll add it + list(APPEND _win_sdk_preferred_sdk_dirs "${_path}") + set(_win_sdk_preferred_sdk_dirs "${_win_sdk_dirs}" CACHE INTERNAL "" FORCE) + + # Just in case we somehow missed it: + _winsdk_conditional_append("${_info}" "" "${_path}") +endfunction() + +# Given a version like v7.0A, looks for an SDK in the registry under "Microsoft SDKs". +# If the given version might be in both HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows +# and HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots aka "Windows Kits", +# use this macro first, since these registry keys usually have more information. +# +# Pass a "default" build number as an extra argument in case we can't find it. +function(_winsdk_check_microsoft_sdks_registry _winsdkver) + set(SDKKEY "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\${_winsdkver}") + get_filename_component(_sdkdir + "[${SDKKEY};InstallationFolder]" + ABSOLUTE) + + set(_sdkname "Windows SDK ${_winsdkver}") + + # Default build number passed as extra argument + set(_build ${ARGN}) + # See if the registry holds a Microsoft-mutilated, err, designated, product name + # (just using get_filename_component to execute the registry lookup) + get_filename_component(_sdkproductname + "[${SDKKEY};ProductName]" + NAME) + if(NOT "${_sdkproductname}" MATCHES "registry") + # Got a product name + set(_sdkname "${_sdkname} (${_sdkproductname})") + endif() + + # try for a version to augment our name + # (just using get_filename_component to execute the registry lookup) + get_filename_component(_sdkver + "[${SDKKEY};ProductVersion]" + NAME) + if(NOT "${_sdkver}" MATCHES "registry" AND NOT MATCHES) + # Got a version + if(NOT "${_sdkver}" MATCHES "\\.\\.") + # and it's not an invalid one with two dots in it: + # use to override the default build + set(_build ${_sdkver}) + if(NOT "${_sdkname}" MATCHES "${_sdkver}") + # Got a version that's not already in the name, let's use it to improve our name. + set(_sdkname "${_sdkname} (${_sdkver})") + endif() + endif() + endif() + _winsdk_conditional_append("${_sdkname}" "${_build}" "${_sdkdir}") +endfunction() + +# Given a name for identification purposes, the build number, and a key (technically a "value name") +# corresponding to a Windows SDK packaged as a "Windows Kit", look for it +# in HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots +# Note that the key or "value name" tends to be something weird like KitsRoot81 - +# no easy way to predict, just have to observe them in the wild. +# Doesn't hurt to also try _winsdk_check_microsoft_sdks_registry for these: +# sometimes you get keys in both parts of the registry (in the wow64 portion especially), +# and the non-"Windows Kits" location is often more descriptive. +function(_winsdk_check_windows_kits_registry _winkit_name _winkit_build _winkit_key) + get_filename_component(_sdkdir + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots;${_winkit_key}]" + ABSOLUTE) + _winsdk_conditional_append("${_winkit_name}" "${_winkit_build}" "${_sdkdir}") +endfunction() + +# Given a name for identification purposes and the build number +# corresponding to a Windows 10 SDK packaged as a "Windows Kit", look for it +# in HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots +# Doesn't hurt to also try _winsdk_check_microsoft_sdks_registry for these: +# sometimes you get keys in both parts of the registry (in the wow64 portion especially), +# and the non-"Windows Kits" location is often more descriptive. +function(_winsdk_check_win10_kits _winkit_build) + get_filename_component(_sdkdir + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots;KitsRoot10]" + ABSOLUTE) + if(("${_sdkdir}" MATCHES "registry") OR (NOT EXISTS "${_sdkdir}")) + return() # not found + endif() + if(EXISTS "${_sdkdir}/Include/${_winkit_build}/um") + _winsdk_conditional_append("Windows Kits 10 (Build ${_winkit_build})" "${_winkit_build}" "${_sdkdir}") + endif() +endfunction() + +# Given a name for indentification purposes, the build number, and the associated package GUID, +# look in the registry under both HKLM and HKCU in \\SOFTWARE\\Microsoft\\MicrosoftSDK\\InstalledSDKs\\ +# for that guid and the SDK it points to. +function(_winsdk_check_platformsdk_registry _platformsdkname _build _platformsdkguid) + foreach(_winsdk_hive HKEY_LOCAL_MACHINE HKEY_CURRENT_USER) + get_filename_component(_sdkdir + "[${_winsdk_hive}\\SOFTWARE\\Microsoft\\MicrosoftSDK\\InstalledSDKs\\${_platformsdkguid};Install Dir]" + ABSOLUTE) + _winsdk_conditional_append("${_platformsdkname} (${_build})" "${_build}" "${_sdkdir}") + endforeach() +endfunction() + +### +# Detect toolchain information: to know whether it's OK to use Vista+ only SDKs +### +set(_winsdk_vistaonly_ok OFF) +if(MSVC AND NOT _WINDOWSSDK_IGNOREMSVC) + # VC 10 and older has broad target support + if(MSVC_VERSION LESS 1700) + # VC 11 by default targets Vista and later only, so we can add a few more SDKs that (might?) only work on vista+ + elseif("${CMAKE_VS_PLATFORM_TOOLSET}" MATCHES "_xp") + # This is the XP-compatible v110+ toolset + elseif("${CMAKE_VS_PLATFORM_TOOLSET}" STREQUAL "v100" OR "${CMAKE_VS_PLATFORM_TOOLSET}" STREQUAL "v90") + # This is the VS2010/VS2008 toolset + else() + # OK, we're VC11 or newer and not using a backlevel or XP-compatible toolset. + # These versions have no XP (and possibly Vista pre-SP1) support + set(_winsdk_vistaonly_ok ON) + if(_WINDOWSSDK_ANNOUNCE AND NOT WINDOWSSDK_DIRS) + message(STATUS "FindWindowsSDK: Detected Visual Studio 2012 or newer, not using the _xp toolset variant: including SDK versions that drop XP support in search!") + endif() + endif() +endif() +if(_WINDOWSSDK_IGNOREMSVC) + set(_winsdk_vistaonly_ok ON) +endif() + +### +# MSVC version checks - keeps messy conditionals in one place +# (messy because of _WINDOWSSDK_IGNOREMSVC) +### +set(_winsdk_msvc_greater_1200 OFF) +if(_WINDOWSSDK_IGNOREMSVC OR (MSVC AND (MSVC_VERSION GREATER 1200))) + set(_winsdk_msvc_greater_1200 ON) +endif() +# Newer than VS .NET/VS Toolkit 2003 +set(_winsdk_msvc_greater_1310 OFF) +if(_WINDOWSSDK_IGNOREMSVC OR (MSVC AND (MSVC_VERSION GREATER 1310))) + set(_winsdk_msvc_greater_1310 ON) +endif() + +# VS2005/2008 +set(_winsdk_msvc_less_1600 OFF) +if(_WINDOWSSDK_IGNOREMSVC OR (MSVC AND (MSVC_VERSION LESS 1600))) + set(_winsdk_msvc_less_1600 ON) +endif() + +# VS2013+ +set(_winsdk_msvc_not_less_1800 OFF) +if(_WINDOWSSDK_IGNOREMSVC OR (MSVC AND (NOT MSVC_VERSION LESS 1800))) + set(_winsdk_msvc_not_less_1800 ON) +endif() + +### +# START body of find module +### +if(_winsdk_msvc_greater_1310) # Newer than VS .NET/VS Toolkit 2003 + ### + # Look for "preferred" SDKs + ### + + # Environment variable for SDK dir + if(EXISTS "$ENV{WindowsSDKDir}" AND (NOT "$ENV{WindowsSDKDir}" STREQUAL "")) + _winsdk_conditional_append_preferred("WindowsSDKDir environment variable" "$ENV{WindowsSDKDir}") + endif() + + if(_winsdk_msvc_less_1600) + # Per-user current Windows SDK for VS2005/2008 + get_filename_component(_sdkdir + "[HKEY_CURRENT_USER\\Software\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]" + ABSOLUTE) + _winsdk_conditional_append_preferred("Per-user current Windows SDK" "${_sdkdir}") + + # System-wide current Windows SDK for VS2005/2008 + get_filename_component(_sdkdir + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]" + ABSOLUTE) + _winsdk_conditional_append_preferred("System-wide current Windows SDK" "${_sdkdir}") + endif() + + ### + # Begin the massive list of SDK searching! + ### + if(_winsdk_vistaonly_ok AND _winsdk_msvc_not_less_1800) + # These require at least Visual Studio 2013 (VC12) + + _winsdk_check_microsoft_sdks_registry(v10.0A) + + # Windows Software Development Kit (SDK) for Windows 10 + # Several different versions living in the same directory - if nothing else we can assume RTM (10240) + _winsdk_check_microsoft_sdks_registry(v10.0 10.0.10240.0) + foreach(_win10build ${_winsdk_win10vers}) + _winsdk_check_win10_kits(${_win10build}) + endforeach() + endif() # vista-only and 2013+ + + # Included in Visual Studio 2013 + # Includes the v120_xp toolset + _winsdk_check_microsoft_sdks_registry(v8.1A 8.1.51636) + + if(_winsdk_vistaonly_ok AND _winsdk_msvc_not_less_1800) + # Windows Software Development Kit (SDK) for Windows 8.1 + # http://msdn.microsoft.com/en-gb/windows/desktop/bg162891 + _winsdk_check_microsoft_sdks_registry(v8.1 8.1.25984.0) + _winsdk_check_windows_kits_registry("Windows Kits 8.1" 8.1.25984.0 KitsRoot81) + endif() # vista-only and 2013+ + + if(_winsdk_vistaonly_ok) + # Included in Visual Studio 2012 + _winsdk_check_microsoft_sdks_registry(v8.0A 8.0.50727) + + # Microsoft Windows SDK for Windows 8 and .NET Framework 4.5 + # This is the first version to also include the DirectX SDK + # http://msdn.microsoft.com/en-US/windows/desktop/hh852363.aspx + _winsdk_check_microsoft_sdks_registry(v8.0 6.2.9200.16384) + _winsdk_check_windows_kits_registry("Windows Kits 8.0" 6.2.9200.16384 KitsRoot) + endif() # vista-only + + # Included with VS 2012 Update 1 or later + # Introduces v110_xp toolset + _winsdk_check_microsoft_sdks_registry(v7.1A 7.1.51106) + if(_winsdk_vistaonly_ok) + # Microsoft Windows SDK for Windows 7 and .NET Framework 4 + # http://www.microsoft.com/downloads/en/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b + _winsdk_check_microsoft_sdks_registry(v7.1 7.1.7600.0.30514) + endif() # vista-only + + # Included with VS 2010 + _winsdk_check_microsoft_sdks_registry(v7.0A 6.1.7600.16385) + + # Windows SDK for Windows 7 and .NET Framework 3.5 SP1 + # Works with VC9 + # http://www.microsoft.com/en-us/download/details.aspx?id=18950 + _winsdk_check_microsoft_sdks_registry(v7.0 6.1.7600.16385) + + # Two versions call themselves "v6.1": + # Older: + # Windows Vista Update & .NET 3.0 SDK + # http://www.microsoft.com/en-us/download/details.aspx?id=14477 + + # Newer: + # Windows Server 2008 & .NET 3.5 SDK + # may have broken VS9SP1? they recommend v7.0 instead, or a KB... + # http://www.microsoft.com/en-us/download/details.aspx?id=24826 + _winsdk_check_microsoft_sdks_registry(v6.1 6.1.6000.16384.10) + + # Included in VS 2008 + _winsdk_check_microsoft_sdks_registry(v6.0A 6.1.6723.1) + + # Microsoft Windows Software Development Kit for Windows Vista and .NET Framework 3.0 Runtime Components + # http://blogs.msdn.com/b/stanley/archive/2006/11/08/microsoft-windows-software-development-kit-for-windows-vista-and-net-framework-3-0-runtime-components.aspx + _winsdk_check_microsoft_sdks_registry(v6.0 6.0.6000.16384) +endif() + +# Let's not forget the Platform SDKs, which sometimes are useful! +if(_winsdk_msvc_greater_1200) + _winsdk_check_platformsdk_registry("Microsoft Platform SDK for Windows Server 2003 R2" "5.2.3790.2075.51" "D2FF9F89-8AA2-4373-8A31-C838BF4DBBE1") + _winsdk_check_platformsdk_registry("Microsoft Platform SDK for Windows Server 2003 SP1" "5.2.3790.1830.15" "8F9E5EF3-A9A5-491B-A889-C58EFFECE8B3") +endif() +### +# Finally, look for "preferred" SDKs +### +if(_winsdk_msvc_greater_1310) # Newer than VS .NET/VS Toolkit 2003 + + + # Environment variable for SDK dir + if(EXISTS "$ENV{WindowsSDKDir}" AND (NOT "$ENV{WindowsSDKDir}" STREQUAL "")) + _winsdk_conditional_append_preferred("WindowsSDKDir environment variable" "$ENV{WindowsSDKDir}") + endif() + + if(_winsdk_msvc_less_1600) + # Per-user current Windows SDK for VS2005/2008 + get_filename_component(_sdkdir + "[HKEY_CURRENT_USER\\Software\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]" + ABSOLUTE) + _winsdk_conditional_append_preferred("Per-user current Windows SDK" "${_sdkdir}") + + # System-wide current Windows SDK for VS2005/2008 + get_filename_component(_sdkdir + "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]" + ABSOLUTE) + _winsdk_conditional_append_preferred("System-wide current Windows SDK" "${_sdkdir}") + endif() +endif() + + +function(windowssdk_name_lookup _dir _outvar) + list(FIND _win_sdk_versanddirs "${_dir}" _diridx) + math(EXPR _idx "${_diridx} - 1") + if(${_idx} GREATER -1) + list(GET _win_sdk_versanddirs ${_idx} _ret) + else() + set(_ret "NOTFOUND") + endif() + set(${_outvar} "${_ret}" PARENT_SCOPE) +endfunction() + +function(windowssdk_build_lookup _dir _outvar) + list(FIND _win_sdk_buildsanddirs "${_dir}" _diridx) + math(EXPR _idx "${_diridx} - 1") + if(${_idx} GREATER -1) + list(GET _win_sdk_buildsanddirs ${_idx} _ret) + else() + set(_ret "NOTFOUND") + endif() + set(${_outvar} "${_ret}" PARENT_SCOPE) +endfunction() + +# If we found something... +if(_win_sdk_dirs) + list(GET _win_sdk_dirs 0 WINDOWSSDK_LATEST_DIR) + windowssdk_name_lookup("${WINDOWSSDK_LATEST_DIR}" + WINDOWSSDK_LATEST_NAME) + set(WINDOWSSDK_DIRS ${_win_sdk_dirs}) + + # Fallback, in case no preference found. + set(WINDOWSSDK_PREFERRED_DIR "${WINDOWSSDK_LATEST_DIR}") + set(WINDOWSSDK_PREFERRED_NAME "${WINDOWSSDK_LATEST_NAME}") + set(WINDOWSSDK_PREFERRED_FIRST_DIRS ${WINDOWSSDK_DIRS}) + set(WINDOWSSDK_FOUND_PREFERENCE OFF) +endif() + +# If we found indications of a user preference... +if(_win_sdk_preferred_sdk_dirs) + list(GET _win_sdk_preferred_sdk_dirs 0 WINDOWSSDK_PREFERRED_DIR) + windowssdk_name_lookup("${WINDOWSSDK_PREFERRED_DIR}" + WINDOWSSDK_PREFERRED_NAME) + set(WINDOWSSDK_PREFERRED_FIRST_DIRS + ${_win_sdk_preferred_sdk_dirs} + ${_win_sdk_dirs}) + list(REMOVE_DUPLICATES WINDOWSSDK_PREFERRED_FIRST_DIRS) + set(WINDOWSSDK_FOUND_PREFERENCE ON) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(WindowsSDK + "No compatible version of the Windows SDK or Platform SDK found." + WINDOWSSDK_DIRS) + +if(WINDOWSSDK_FOUND) + # Internal: Architecture-appropriate library directory names. + if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "ARM") + if(CMAKE_SIZEOF_VOID_P MATCHES "8") + # Only supported in Win10 SDK and up. + set(_winsdk_arch8 arm64) # what the WDK for Win8+ calls this architecture + else() + set(_winsdk_archbare /arm) # what the architecture used to be called in oldest SDKs + set(_winsdk_arch arm) # what the architecture used to be called + set(_winsdk_arch8 arm) # what the WDK for Win8+ calls this architecture + endif() + else() + if(CMAKE_SIZEOF_VOID_P MATCHES "8") + set(_winsdk_archbare /x64) # what the architecture used to be called in oldest SDKs + set(_winsdk_arch amd64) # what the architecture used to be called + set(_winsdk_arch8 x64) # what the WDK for Win8+ calls this architecture + else() + set(_winsdk_archbare ) # what the architecture used to be called in oldest SDKs + set(_winsdk_arch i386) # what the architecture used to be called + set(_winsdk_arch8 x86) # what the WDK for Win8+ calls this architecture + endif() + endif() + + function(get_windowssdk_from_component _component _var) + get_filename_component(_component "${_component}" ABSOLUTE) + file(TO_CMAKE_PATH "${_component}" _component) + foreach(_sdkdir ${WINDOWSSDK_DIRS}) + get_filename_component(_sdkdir "${_sdkdir}" ABSOLUTE) + string(LENGTH "${_sdkdir}" _sdklen) + file(RELATIVE_PATH _rel "${_sdkdir}" "${_component}") + # If we don't have any "parent directory" items... + if(NOT "${_rel}" MATCHES "[.][.]") + set(${_var} "${_sdkdir}" PARENT_SCOPE) + return() + endif() + endforeach() + # Fail. + set(${_var} "NOTFOUND" PARENT_SCOPE) + endfunction() + function(get_windowssdk_library_dirs _winsdk_dir _var) + set(_result) + set(_suffixes + "lib${_winsdk_archbare}" # SDKs like 7.1A + "lib/${_winsdk_arch}" # just because some SDKs have x86 dir and root dir + "lib/w2k/${_winsdk_arch}" # Win2k min requirement + "lib/wxp/${_winsdk_arch}" # WinXP min requirement + "lib/wnet/${_winsdk_arch}" # Win Server 2003 min requirement + "lib/wlh/${_winsdk_arch}" + "lib/wlh/um/${_winsdk_arch8}" # Win Vista ("Long Horn") min requirement + "lib/win7/${_winsdk_arch}" + "lib/win7/um/${_winsdk_arch8}" # Win 7 min requirement + ) + foreach(_ver + wlh # Win Vista ("Long Horn") min requirement + win7 # Win 7 min requirement + win8 # Win 8 min requirement + winv6.3 # Win 8.1 min requirement + ) + + list(APPEND _suffixes + "lib/${_ver}/${_winsdk_arch}" + "lib/${_ver}/um/${_winsdk_arch8}" + "lib/${_ver}/km/${_winsdk_arch8}" + ) + endforeach() + + # Look for WDF libraries in Win10+ SDK + foreach(_mode umdf kmdf) + file(GLOB _wdfdirs RELATIVE "${_winsdk_dir}" "${_winsdk_dir}/lib/wdf/${_mode}/${_winsdk_arch8}/*") + if(_wdfdirs) + list(APPEND _suffixes ${_wdfdirs}) + endif() + endforeach() + + foreach(_win10ver ${_winsdk_win10vers}) + foreach(_component um km ucrt mmos) + list(APPEND _suffixes "lib/${_win10ver}/${_component}/${_winsdk_arch8}") + endforeach() + endforeach() + + foreach(_suffix ${_suffixes}) + # Check to see if a library actually exists here. + file(GLOB _libs "${_winsdk_dir}/${_suffix}/*.lib") + if(_libs) + list(APPEND _result "${_winsdk_dir}/${_suffix}") + endif() + endforeach() + if(NOT _result) + set(_result NOTFOUND) + else() + list(REMOVE_DUPLICATES _result) + endif() + set(${_var} ${_result} PARENT_SCOPE) + endfunction() + function(get_windowssdk_include_dirs _winsdk_dir _var) + set(_result) + + set(_subdirs shared um winrt km wdf mmos ucrt) + set(_suffixes Include) + + foreach(_dir ${_subdirs}) + list(APPEND _suffixes "Include/${_dir}") + endforeach() + + foreach(_ver ${_winsdk_win10vers}) + foreach(_dir ${_subdirs}) + list(APPEND _suffixes "Include/${_ver}/${_dir}") + endforeach() + endforeach() + + foreach(_suffix ${_suffixes}) + # Check to see if a header file actually exists here. + file(GLOB _headers "${_winsdk_dir}/${_suffix}/*.h") + if(_headers) + list(APPEND _result "${_winsdk_dir}/${_suffix}") + endif() + endforeach() + if(NOT _result) + set(_result NOTFOUND) + else() + list(REMOVE_DUPLICATES _result) + endif() + set(${_var} ${_result} PARENT_SCOPE) + endfunction() +endif() diff --git a/cmake/Findliquidvr.cmake b/cmake/Findliquidvr.cmake new file mode 100644 index 0000000..c5e6572 --- /dev/null +++ b/cmake/Findliquidvr.cmake @@ -0,0 +1,54 @@ +# - Find liquidvr +# Find the liquidvr header. +# +# LIQUIDVR_INCLUDE_DIRS - where to find LiquidVRD2D.h +# LIQUIDVR_FOUND - True if liquidvr found. +# +# Creates an "liquidvr" interface target with the include dir +# that you can link against instead of using the above variables. +# +# Original Author: +# 2016 Russ Taylor working through ReliaSolve for Sensics. +# +# Copyright Sensics, Inc. 2016. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +set(LIQUIDVR_ROOT_DIR + "${LIQUIDVR_ROOT_DIR}" + CACHE + PATH + "Path to search for liquidvr library") + +# Look for the header file. +find_path(LIQUIDVR_INCLUDE_DIR + NAMES + LiquidVRD2D.h + PATH_SUFFIXES + include + inc + PATHS + "${LIQUIDVR_ROOT_DIR}") + +# handle the QUIETLY and REQUIRED arguments and set LIQUIDVR_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(liquidvr + REQUIRED_VARS LIQUIDVR_INCLUDE_DIR + HANDLE_COMPONENTS) + +if(LIQUIDVR_FOUND) + set(LIQUIDVR_INCLUDE_DIRS ${LIQUIDVR_INCLUDE_DIR}) + if(NOT TARGET liquidvr) + add_library(liquidvr INTERFACE) + target_include_directories(liquidvr INTERFACE "${LIQUIDVR_INCLUDE_DIR}") + endif() + mark_as_advanced(LIQUIDVR_ROOT_DIR) +else() + set(LIQUIDVR_INCLUDE_DIRS) + set(LIQUIDVR_ROOT_DIR LIQUIDVR_ROOT_DIR_NOTFOUND) + mark_as_advanced(CLEAR LIQUIDVR_ROOT_DIR) +endif() + +mark_as_advanced(LIQUIDVR_LIBRARY LIQUIDVR_INCLUDE_DIR) diff --git a/cmake/Findnvapi.cmake b/cmake/Findnvapi.cmake new file mode 100644 index 0000000..a98588e --- /dev/null +++ b/cmake/Findnvapi.cmake @@ -0,0 +1,109 @@ +# - Find nvapi +# Find the nvapi headers and libraries. Can request component NDA which +# will only succeed if an NDA version of the header is found. +# +# NVAPI_INCLUDE_DIRS - where to find nvapi.h +# NVAPI_LIBRARIES - List of libraries when using nvapi. +# NVAPI_FOUND - True if nvapi found. +# +# Creates an "nvapi" interface target with the libraries and include dir +# that you can link against instead of using the above variables. +# +# Original Author: +# 2016 Russ Taylor working through ReliaSolve for Sensics. +# +# Copyright Sensics, Inc. 2016. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +set(NVAPI_ROOT_DIR + "${NVAPI_ROOT_DIR}" + CACHE + PATH + "Path to search for nvapi library") + +# Look for the header file. +find_path(NVAPI_INCLUDE_DIR + NAMES + nvapi.h + PATH_SUFFIXES + include + PATHS + "${NVAPI_ROOT_DIR}" + C:/usr/local + /usr/local) + +# Allow user to have us re-detect the edition by clearing NVAPI_EDITION +if(NOT DEFINED NVAPI_EDITION) + set(NVAPI_LAST_INCLUDE_DIR "" CACHE INTERNAL "" FORCE) +endif() +if(NVAPI_INCLUDE_DIR AND NOT "${NVAPI_INCLUDE_DIR}" STREQUAL "${NVAPI_LAST_INCLUDE_DIR}") + file(STRINGS "${NVAPI_INCLUDE_DIR}/nvapi.h" _nvapi_strings REGEX "Target Profile:") + if("${_nvapi_strings}" MATCHES ".* NDA-developer") + set(NVAPI_EDITION "NDA-developer" CACHE STRING "The detected edition of the NVAPI") + elseif("${_nvapi_strings}" MATCHES ".* developer") + set(NVAPI_EDITION "developer" CACHE STRING "The detected edition of the NVAPI") + endif() + # If we found an edition, keep track of where we found it so that we don't re-check next time CMake runs. + if(DEFINED NVAPI_EDITION) + set(NVAPI_LAST_INCLUDE_DIR "${NVAPI_INCLUDE_DIR}" CACHE INTERNAL "" FORCE) + endif() +endif() + +if(NVAPI_INCLUDE_DIR) + # Prioritize finding the lib near the header to hopefully ensure they match. + set(_nvapi_hints "${NVAPI_INCLUDE_DIR}") +endif() + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_nvapiextraname nvapi64 nvapi64.lib) + set(_nvapipathsuffix amd64) +else() + set(_nvapiextraname nvapi nvapi.lib) + set(_nvapipathsuffix x86) +endif() + +# Look for the library. +find_library(NVAPI_LIBRARY + NAMES + ${_nvapiextraname} + libnvapi.a + HINTS + ${_nvapi_hints} + PATH_SUFFIXES + ${_nvapipathsuffix} + PATHS + "${NVAPI_ROOT_DIR}" + C:/usr/local + /usr/local) + +# Handle asking for component "NDA" +if("${NVAPI_EDITION}" STREQUAL "NDA-developer") + set(nvapi_NDA_FOUND TRUE) +endif() + +# handle the QUIETLY and REQUIRED arguments and set NVAPI_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(nvapi + REQUIRED_VARS NVAPI_LIBRARY NVAPI_INCLUDE_DIR + HANDLE_COMPONENTS) + +if(NVAPI_FOUND) + set(NVAPI_LIBRARIES ${NVAPI_LIBRARY}) + set(NVAPI_INCLUDE_DIRS ${NVAPI_INCLUDE_DIR}) + if(NOT TARGET nvapi) + add_library(nvapi INTERFACE) + target_include_directories(nvapi INTERFACE "${NVAPI_INCLUDE_DIR}") + target_link_libraries(nvapi INTERFACE "${NVAPI_LIBRARY}") + endif() + mark_as_advanced(NVAPI_ROOT_DIR) +else() + set(NVAPI_LIBRARIES) + set(NVAPI_INCLUDE_DIRS) + set(NVAPI_ROOT_DIR NVAPI_ROOT_DIR_NOTFOUND) + mark_as_advanced(CLEAR NVAPI_ROOT_DIR) +endif() + +mark_as_advanced(NVAPI_LIBRARY NVAPI_INCLUDE_DIR) diff --git a/cmake/Findquatlib.cmake b/cmake/Findquatlib.cmake new file mode 100644 index 0000000..efca27f --- /dev/null +++ b/cmake/Findquatlib.cmake @@ -0,0 +1,104 @@ +# - Find quatlib +# Find the quatlib headers and libraries. +# +# QUATLIB_INCLUDE_DIRS - where to find quat.h +# QUATLIB_LIBRARIES - List of libraries when using quatlib. +# QUATLIB_FOUND - True if quatlib found. +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +if(TARGET quat) + # Look for the header file. + find_path(QUATLIB_INCLUDE_DIR NAMES quat.h + PATHS ${quatlib_SOURCE_DIR}) + + set(QUATLIB_LIBRARY "quat") + +else() + set(QUATLIB_ROOT_DIR + "${QUATLIB_ROOT_DIR}" + CACHE + PATH + "Root directory to search for quatlib") + if(DEFINED VRPN_ROOT_DIR AND NOT QUATLIB_ROOT_DIR) + set(QUATLIB_ROOT_DIR "${VRPN_ROOT_DIR}") + mark_as_advanced(QUATLIB_ROOT_DIR) + endif() + + if("${CMAKE_SIZEOF_VOID_P}" MATCHES "8") + set(_libsuffixes lib64 lib) + + # 64-bit dir: only set on win64 + file(TO_CMAKE_PATH "$ENV{ProgramW6432}" _progfiles) + else() + set(_libsuffixes lib) + set(_PF86 "ProgramFiles(x86)") + if(NOT "$ENV{${_PF86}}" STREQUAL "") + # 32-bit dir: only set on win64 + file(TO_CMAKE_PATH "$ENV{${_PF86}}" _progfiles) + else() + # 32-bit dir on win32, useless to us on win64 + file(TO_CMAKE_PATH "$ENV{ProgramFiles}" _progfiles) + endif() + endif() + + # Look for the header file. + find_path(QUATLIB_INCLUDE_DIR + NAMES + quat.h + HINTS + "${QUATLIB_ROOT_DIR}" + PATH_SUFFIXES + include + PATHS + "${_progfiles}/VRPN" + "${_progfiles}/quatlib" + C:/usr/local + /usr/local) + + # Look for the library. + find_library(QUATLIB_LIBRARY + NAMES + quat.lib + libquat.a + HINTS + "${QUATLIB_ROOT_DIR}" + PATH_SUFFIXES + ${_libsuffixes} + PATHS + "${_progfiles}/VRPN" + "${_progfiles}/quatlib" + C:/usr/local + /usr/local) +endif() + +# handle the QUIETLY and REQUIRED arguments and set QUATLIB_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(quatlib + DEFAULT_MSG + QUATLIB_LIBRARY + QUATLIB_INCLUDE_DIR) + +if(QUATLIB_FOUND) + set(QUATLIB_LIBRARIES ${QUATLIB_LIBRARY}) + if(NOT WIN32) + list(APPEND QUATLIB_LIBRARIES m) + endif() + set(QUATLIB_INCLUDE_DIRS ${QUATLIB_INCLUDE_DIR}) + + mark_as_advanced(QUATLIB_ROOT_DIR) +else() + set(QUATLIB_LIBRARIES) + set(QUATLIB_INCLUDE_DIRS) +endif() + +mark_as_advanced(QUATLIB_LIBRARY QUATLIB_INCLUDE_DIR) diff --git a/cmake/GenerateCompatibilityVersionFile.cmake b/cmake/GenerateCompatibilityVersionFile.cmake new file mode 100644 index 0000000..7ac28ed --- /dev/null +++ b/cmake/GenerateCompatibilityVersionFile.cmake @@ -0,0 +1,83 @@ +#.rst: +# .. command:: generate_compatibility_version_file +# +# Create a version file for a project:: +# +# generate_compatibility_version_file( +# [VERSION ] +# COMPATIBILITY +# [C_ABI] +# [CXX_LAYOUT] +# [CXX_ABI]) + +#============================================================================= +# Copyright 2015 Sensics, Inc. +# Copyright 2012 Alexander Neundorf +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + + +include(CMakeParseArguments) +include(CMakePackageConfigHelpers) + +set(GCVF_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "" FORCE) + +function(generate_compatibility_version_file _filename) + + set(options C_ABI CXX_LAYOUT CXX_ABI) + set(oneValueArgs VERSION COMPATIBILITY ) + set(multiValueArgs ) + cmake_parse_arguments(GCVF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(GCVF_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown keywords given to generate_compatibility_version_file(): ${GCVF_UNPARSED_ARGUMENTS}") + endif() + set(versionTemplateFile "${CMAKE_ROOT}/Modules/BasicConfigVersion-${GCVF_COMPATIBILITY}.cmake.in") + if(NOT EXISTS "${versionTemplateFile}") + message(FATAL_ERROR "Bad COMPATIBILITY value used for generate_compatibility_version_file(): \"${GCVF_COMPATIBILITY}\"") + endif() + + if(GCVF_CXX_ABI) + set(GCVF_CXX_LAYOUT TRUE) + endif() + if(GCVF_CXX_LAYOUT) + set(GCVF_C_ABI TRUE) + endif() + + if("${GCVF_VERSION}" STREQUAL "") + if("${PROJECT_VERSION}" STREQUAL "") + message(FATAL_ERROR "No VERSION specified for generate_compatibility_version_file()") + else() + set(GCVF_VERSION ${PROJECT_VERSION}) + endif() + endif() + + set(GCVF_WIN_CXXLAYOUT) + if(MSVC) + set(GCVF_WIN_CXXLAYOUT "MSVC") + elseif(MINGW) + set(GCVF_WIN_CXXLAYOUT "MinGW") + elseif(WIN32) + set(GCVF_WIN_CXXLAYOUT "other") + endif() + + set(PREV_FILE "${_filename}.cmakeversion") + write_basic_package_version_file("${PREV_FILE}" VERSION ${GCVF_VERSION} COMPATIBILITY ${GCVF_COMPATIBILITY}) + set(GCVF_BASIC TRUE) + foreach(level BASIC C_ABI CXX_LAYOUT CXX_ABI) + if(GCVF_${level}) + file(READ "${PREV_FILE}" GCVF_PREVIOUS_FILE) + set(PREV_FILE "${_filename}.${level}") + configure_file("${GCVF_DIR}/CompatibilityVersionFile-${level}.cmake.in" "${PREV_FILE}" @ONLY) + endif() + endforeach() + configure_file("${PREV_FILE}" "${_filename}" COPYONLY) +endfunction() \ No newline at end of file diff --git a/cmake/GetGitRevisionDescription.cmake b/cmake/GetGitRevisionDescription.cmake new file mode 100644 index 0000000..85eae15 --- /dev/null +++ b/cmake/GetGitRevisionDescription.cmake @@ -0,0 +1,130 @@ +# - Returns a version string from Git +# +# These functions force a re-configure on each git commit so that you can +# trust the values of the variables in your build system. +# +# get_git_head_revision( [ ...]) +# +# Returns the refspec and sha hash of the current head revision +# +# git_describe( [ ...]) +# +# Returns the results of git describe on the source tree, and adjusting +# the output so that it tests false if an error occurs. +# +# git_get_exact_tag( [ ...]) +# +# Returns the results of git describe --exact-match on the source tree, +# and adjusting the output so that it tests false if there was no exact +# matching tag. +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +if(__get_git_revision_description) + return() +endif() +set(__get_git_revision_description YES) + +# We must run the following at "include" time, not at function call time, +# to find the path to this module rather than the path to a calling list file +get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) + +function(get_git_head_revision _refspecvar _hashvar) + set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + set(GIT_DIR "${GIT_PARENT_DIR}/.git") + while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories + set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") + get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) + if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) + # We have reached the root directory, we are not in git + set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE) + set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE) + return() + endif() + set(GIT_DIR "${GIT_PARENT_DIR}/.git") + endwhile() + # check if this is a submodule + if(NOT IS_DIRECTORY ${GIT_DIR}) + file(READ ${GIT_DIR} submodule) + string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) + get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) + get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) + endif() + set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") + if(NOT EXISTS "${GIT_DATA}") + file(MAKE_DIRECTORY "${GIT_DATA}") + endif() + + if(NOT EXISTS "${GIT_DIR}/HEAD") + return() + endif() + set(HEAD_FILE "${GIT_DATA}/HEAD") + configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) + + configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" + "${GIT_DATA}/grabRef.cmake" + @ONLY) + include("${GIT_DATA}/grabRef.cmake") + + set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE) + set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE) +endfunction() + +function(git_describe _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) + return() + endif() + + # TODO sanitize + #if((${ARGN}" MATCHES "&&") OR + # (ARGN MATCHES "||") OR + # (ARGN MATCHES "\\;")) + # message("Please report the following error to the project!") + # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") + #endif() + + #message(STATUS "Arguments to execute_process: ${ARGN}") + + execute_process(COMMAND + "${GIT_EXECUTABLE}" + describe + ${hash} + ${ARGN} + WORKING_DIRECTORY + "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE + res + OUTPUT_VARIABLE + out + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT res EQUAL 0) + set(out "${out}-${res}-NOTFOUND") + endif() + + set(${_var} "${out}" PARENT_SCOPE) +endfunction() + +function(git_get_exact_tag _var) + git_describe(out --exact-match ${ARGN}) + set(${_var} "${out}" PARENT_SCOPE) +endfunction() diff --git a/cmake/GetGitRevisionDescription.cmake.in b/cmake/GetGitRevisionDescription.cmake.in new file mode 100644 index 0000000..6d8b708 --- /dev/null +++ b/cmake/GetGitRevisionDescription.cmake.in @@ -0,0 +1,41 @@ +# +# Internal file for GetGitRevisionDescription.cmake +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +set(HEAD_HASH) + +file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) + +string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) +if(HEAD_CONTENTS MATCHES "ref") + # named branch + string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") + if(EXISTS "@GIT_DIR@/${HEAD_REF}") + configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) + else() + configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) + file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) + if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") + set(HEAD_HASH "${CMAKE_MATCH_1}") + endif() + endif() +else() + # detached HEAD + configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) +endif() + +if(NOT HEAD_HASH) + file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) + string(STRIP "${HEAD_HASH}" HEAD_HASH) +endif() diff --git a/cmake/GetMSVCVersion.cmake b/cmake/GetMSVCVersion.cmake new file mode 100644 index 0000000..48d7b7c --- /dev/null +++ b/cmake/GetMSVCVersion.cmake @@ -0,0 +1,127 @@ +#.rst: +# GetMSVCVersion +# -------------- +# +# +# +# get_msvc_major_version() +# get_msvc_minor_version() +# get_msvc_combined_major_minor_version() +# get_msvc_major_minor_version( ) +# get_msvc_unique_decimal_version() +# +# This family of functions is designed to be used to convert +# MSVC_VERSION from the compiler version number to the Visual Studio +# decimal version number (2012 is 11.0, 2015 is 14.0). All take a name +# of a variable in to return their results in. +# +# Consider Visual Studio 2013, which reports 1800 in MSVC_VERSION (and +# the _MSC_VER preprocessor macro). It is also known as VS 12 or 12.0. +# (Minor versions are rarely used, except in the case of 7.1 aka +# VS.NET 2003) The functions would return this output for 2013: +# +# get_msvc_major_version: 12 +# get_msvc_minor_version: 0 +# get_msvc_combined_major_minor_version: 120 +# get_msvc_major_minor_version: 12 in , 0 in +# get_msvc_unique_decimal_version: 12 (this returns with a decimal and +# minor when needed to be precise, e.g. 7.1) +# +# The variable is not modified if not building with MSVC. + +#============================================================================= +# Copyright 2015 Ryan Pavlik +# +# Distributed under the OSI-approved BSD License (the "License"); +# see below. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the names of Kitware, Inc., the Insight Software Consortium, +# nor the names of their contributors may be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= + +# This function serves as the main implementation, with the others just +# tweaking the result. +function(get_msvc_combined_major_minor_version _var) + if(NOT MSVC) + return() + endif() + math(EXPR _vs_ver "${MSVC_VERSION} / 10 - 60") + + # VS 2015 changed the pattern because they skipped VS 13 + if(_vs_ver GREATER 120) + math(EXPR _vs_ver "${_vs_ver} + 10") + endif() + set(${_var} ${_vs_ver} PARENT_SCOPE) +endfunction() + +# This function is also used as backend to some implementation, though +# its contents are simpler, no real business logic to speak of. +function(get_msvc_major_minor_version _major_var _minor_var) + if(NOT MSVC) + return() + endif() + get_msvc_combined_major_minor_version(_vs_ver) + + math(EXPR _vs_minor "${_vs_ver} % 10") + math(EXPR _vs_major "(${_vs_ver} - ${_vs_minor}) / 10") + set(${_major_var} ${_vs_major} PARENT_SCOPE) + set(${_minor_var} ${_vs_minor} PARENT_SCOPE) +endfunction() + +function(get_msvc_major_version _var) + if(NOT MSVC) + return() + endif() + get_msvc_major_minor_version(_vs_ver _dummy) + set(${_var} ${_vs_ver} PARENT_SCOPE) +endfunction() + +function(get_msvc_minor_version _var) + if(NOT MSVC) + return() + endif() + get_msvc_major_minor_version(_dummy _vs_ver) + set(${_var} ${_vs_ver} PARENT_SCOPE) +endfunction() + +function(get_msvc_unique_decimal_version _var) + if(NOT MSVC) + return() + endif() + get_msvc_major_minor_version(_vs_major _vs_minor) + set(_vs_ver ${_vs_major}) + if(_vs_minor GREATER 0) + set(_vs_ver "${_vs_ver}.${_vs_minor}") + endif() + set(${_var} ${_vs_ver} PARENT_SCOPE) +endfunction() diff --git a/cmake/PrintTargetProperties.cmake b/cmake/PrintTargetProperties.cmake new file mode 100644 index 0000000..8e17a02 --- /dev/null +++ b/cmake/PrintTargetProperties.cmake @@ -0,0 +1,256 @@ +# Prints a target's properties. +# +# Usage: +# print_target_properties(target [target...]) +# + +function(print_target_property _target _prop) + get_property(value TARGET ${_target} PROPERTY ${_prop}) + get_property(is_defined TARGET ${_target} PROPERTY ${_prop} DEFINED) + get_property(is_set TARGET ${_target} PROPERTY ${_prop} SET) + + if(is_set) + message(" ${_prop} = [${value}]") + #elseif(NOT is_set) + # message(" ${_prop} is not set") + #elseif(NOT is_defined) + # message(" ${_prop} is not defined") + endif() +endfunction() + +function(print_target_properties _targets) + set(_targets ${ARGV}) + foreach(_target ${_targets}) + if(NOT TARGET ${_target}) + message(WARNING "There is no target named [${_target}].") + return() + endif() + + set(props + ALIASED_TARGET + ANDROID_ANT_ADDITIONAL_OPTIONS + ANDROID_API + ANDROID_API_MIN + ANDROID_ARCH + ANDROID_ASSETS_DIRECTORIES + ANDROID_GUI + ANDROID_JAR_DEPENDENCIES + ANDROID_JAR_DIRECTORIES + ANDROID_JAVA_SOURCE_DIR + ANDROID_NATIVE_LIB_DEPENDENCIES + ANDROID_NATIVE_LIB_DIRECTORIES + ANDROID_PROCESS_MAX + ANDROID_PROGUARD + ANDROID_PROGUARD_CONFIG_PATH + ANDROID_SECURE_PROPS_PATH + ANDROID_SKIP_ANT_STEP + ANDROID_STL_TYPE + ARCHIVE_OUTPUT_DIRECTORY_ + ARCHIVE_OUTPUT_DIRECTORY + ARCHIVE_OUTPUT_NAME_ + ARCHIVE_OUTPUT_NAME + AUTOGEN_TARGET_DEPENDS + AUTOMOC_MOC_OPTIONS + AUTOMOC + AUTOUIC + AUTOUIC_OPTIONS + AUTORCC + AUTORCC_OPTIONS + BINARY_DIR + BUILD_WITH_INSTALL_RPATH + BUNDLE_EXTENSION + BUNDLE + C_EXTENSIONS + C_STANDARD + C_STANDARD_REQUIRED + COMPATIBLE_INTERFACE_BOOL + COMPATIBLE_INTERFACE_NUMBER_MAX + COMPATIBLE_INTERFACE_NUMBER_MIN + COMPATIBLE_INTERFACE_STRING + COMPILE_DEFINITIONS + COMPILE_FEATURES + COMPILE_FLAGS + COMPILE_OPTIONS + COMPILE_PDB_NAME + COMPILE_PDB_NAME_ + COMPILE_PDB_OUTPUT_DIRECTORY + COMPILE_PDB_OUTPUT_DIRECTORY_ + _OUTPUT_NAME + _POSTFIX + CROSSCOMPILING_EMULATOR + CXX_EXTENSIONS + CXX_STANDARD + CXX_STANDARD_REQUIRED + DEBUG_POSTFIX + DEFINE_SYMBOL + EchoString + ENABLE_EXPORTS + EXCLUDE_FROM_ALL + EXCLUDE_FROM_DEFAULT_BUILD_ + EXCLUDE_FROM_DEFAULT_BUILD + EXPORT_NAME + FOLDER + Fortran_FORMAT + Fortran_MODULE_DIRECTORY + FRAMEWORK + FRAMEWORK_VERSION + GENERATOR_FILE_NAME + GNUtoMS + HAS_CXX + IMPLICIT_DEPENDS_INCLUDE_TRANSFORM + IMPORTED_CONFIGURATIONS + IMPORTED_IMPLIB_ + IMPORTED_IMPLIB + IMPORTED_LINK_DEPENDENT_LIBRARIES_ + IMPORTED_LINK_DEPENDENT_LIBRARIES + IMPORTED_LINK_INTERFACE_LANGUAGES_ + IMPORTED_LINK_INTERFACE_LANGUAGES + IMPORTED_LINK_INTERFACE_LIBRARIES_ + IMPORTED_LINK_INTERFACE_LIBRARIES + IMPORTED_LINK_INTERFACE_MULTIPLICITY_ + IMPORTED_LINK_INTERFACE_MULTIPLICITY + IMPORTED_LOCATION_ + IMPORTED_LOCATION + IMPORTED_NO_SONAME_ + IMPORTED_NO_SONAME + IMPORTED + IMPORTED_SONAME_ + IMPORTED_SONAME + IMPORT_PREFIX + IMPORT_SUFFIX + INCLUDE_DIRECTORIES + INSTALL_NAME_DIR + INSTALL_RPATH + INSTALL_RPATH_USE_LINK_PATH + INTERFACE_AUTOUIC_OPTIONS + INTERFACE_COMPILE_DEFINITIONS + INTERFACE_COMPILE_FEATURES + INTERFACE_COMPILE_OPTIONS + INTERFACE_INCLUDE_DIRECTORIES + INTERFACE_LINK_LIBRARIES + INTERFACE_POSITION_INDEPENDENT_CODE + INTERFACE_SOURCES + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES + INTERPROCEDURAL_OPTIMIZATION_ + INTERPROCEDURAL_OPTIMIZATION + IOS_INSTALL_COMBINED + JOB_POOL_COMPILE + JOB_POOL_LINK + LABELS + _COMPILER_LAUNCHER + _INCLUDE_WHAT_YOU_USE + _VISIBILITY_PRESET + LIBRARY_OUTPUT_DIRECTORY_ + LIBRARY_OUTPUT_DIRECTORY + LIBRARY_OUTPUT_NAME_ + LIBRARY_OUTPUT_NAME + LINK_DEPENDS_NO_SHARED + LINK_DEPENDS + LINKER_LANGUAGE + LINK_FLAGS_ + LINK_FLAGS + LINK_INTERFACE_LIBRARIES_ + LINK_INTERFACE_LIBRARIES + LINK_INTERFACE_MULTIPLICITY_ + LINK_INTERFACE_MULTIPLICITY + LINK_LIBRARIES + LINK_SEARCH_END_STATIC + LINK_SEARCH_START_STATIC + LOCATION_ + LOCATION + MACOSX_BUNDLE_INFO_PLIST + MACOSX_BUNDLE + MACOSX_FRAMEWORK_INFO_PLIST + MACOSX_RPATH + MAP_IMPORTED_CONFIG_ + NAME + NO_SONAME + NO_SYSTEM_FROM_IMPORTED + OSX_ARCHITECTURES_ + OSX_ARCHITECTURES + OUTPUT_NAME_ + OUTPUT_NAME + PDB_NAME_ + PDB_NAME + PDB_OUTPUT_DIRECTORY_ + PDB_OUTPUT_DIRECTORY + POSITION_INDEPENDENT_CODE + PREFIX + PRIVATE_HEADER + PROJECT_LABEL + PUBLIC_HEADER + RESOURCE + RULE_LAUNCH_COMPILE + RULE_LAUNCH_CUSTOM + RULE_LAUNCH_LINK + RUNTIME_OUTPUT_DIRECTORY_ + RUNTIME_OUTPUT_DIRECTORY + RUNTIME_OUTPUT_NAME_ + RUNTIME_OUTPUT_NAME + SKIP_BUILD_RPATH + SOURCE_DIR + SOURCES + SOVERSION + STATIC_LIBRARY_FLAGS_ + STATIC_LIBRARY_FLAGS + SUFFIX + TYPE + VERSION + VISIBILITY_INLINES_HIDDEN + VS_DESKTOP_EXTENSIONS_VERSION + VS_DOTNET_REFERENCES + VS_DOTNET_TARGET_FRAMEWORK_VERSION + VS_GLOBAL_KEYWORD + VS_GLOBAL_PROJECT_TYPES + VS_GLOBAL_ROOTNAMESPACE + VS_IOT_EXTENSIONS_VERSION + VS_IOT_STARTUP_TASK + VS_KEYWORD + VS_MOBILE_EXTENSIONS_VERSION + VS_SCC_AUXPATH + VS_SCC_LOCALPATH + VS_SCC_PROJECTNAME + VS_SCC_PROVIDER + VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION + VS_WINRT_COMPONENT + VS_WINRT_EXTENSIONS + VS_WINRT_REFERENCES + WIN32_EXECUTABLE + WINDOWS_EXPORT_ALL_SYMBOLS + XCTEST + ) + + set(all_props) + foreach(p IN LISTS props) + # Expand + string(FIND "${p}" "" _position) + if(_position GREATER "-1") + foreach(config DEBUG RELEASE RELWITHDEBINFO MINSIZEREL) + string(REPLACE "" "${config}" p "${p}") + list(APPEND all_props ${p}) + endforeach() + continue() + endif() + + # Expand + string(FIND "${p}" "" _position) + if(_position GREATER "-1") + foreach(lang C CXX) + string(REPLACE "" "${lang}" p "${p}") + list(APPEND all_props ${p}) + endforeach() + continue() + endif() + + list(APPEND all_props ${p}) + endforeach() + + message("Target ${_target} properties:") + foreach(p ${all_props}) + print_target_property("${_target}" "${p}") + endforeach() + message("") + endforeach() +endfunction() + + diff --git a/cmake/Version.cmake b/cmake/Version.cmake new file mode 100644 index 0000000..3eae488 --- /dev/null +++ b/cmake/Version.cmake @@ -0,0 +1,35 @@ +# Set up package options +set(CPACK_PACKAGE_NAME "OSVR-RenderManager") +set(CPACK_PACKAGE_VENDOR "Sensics, Inc.") +set(CPACK_PACKAGE_CONTACT "") +set(CPACK_PACKAGE_VERSION_MAJOR 0) +set(CPACK_PACKAGE_VERSION_MINOR 6) +set(OSVR_RENDERMANAGER_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION ${OSVR_RENDERMANAGER_VERSION}) + +include(GetGitRevisionDescription) +git_describe(GIT_REVISION_DESCRIPTION --tags --match v*) +if(GIT_REVISION_DESCRIPTION) + string(REPLACE "v" "" + GIT_REVISION_DESCRIPTION + "${GIT_REVISION_DESCRIPTION}") + set(CPACK_PACKAGE_VERSION "${GIT_REVISION_DESCRIPTION}") + message(STATUS "Git reports version ${CPACK_PACKAGE_VERSION}") +else() + message(STATUS "Could not get revision information from Git! Calling this just version ${CPACK_PACKAGE_VERSION}!") +endif() + +if(WIN32) + set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_CXX_COMPILER_ID}") + if(MSVC) + include(GetMSVCVersion) + get_msvc_major_minor_version(_vs_major _vs_minor) + set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}${_vs_major}${_vs_minor}") + endif() + if(CMAKE_CXX_SIZEOF_DATA_PTR EQUAL 8) + set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-64bit") + else() + set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-32bit") + endif() +endif() + diff --git a/cmake/osvrRenderManagerConfig.cmake b/cmake/osvrRenderManagerConfig.cmake new file mode 100644 index 0000000..45673af --- /dev/null +++ b/cmake/osvrRenderManagerConfig.cmake @@ -0,0 +1,112 @@ + +# Hook for a super-build to optionally inject hints before target import. +include("${CMAKE_CURRENT_LIST_DIR}/osvrRenderManagerConfigSuperBuildPrefix.cmake" OPTIONAL) + +set(OSVRRM_IN_BUILD_TREE @OSVRRM_IN_BUILD_TREE@) + +if(NOT OSVRRM_IN_BUILD_TREE) + # Compute the installation prefix relative to this file. + get_filename_component(OSVRRM_ROOT "${CMAKE_CURRENT_LIST_FILE}" PATH) + get_filename_component(OSVRRM_ROOT "${OSVRRM_ROOT}" PATH) + get_filename_component(OSVRRM_ROOT "${OSVRRM_ROOT}" PATH) + get_filename_component(OSVRRM_ROOT "${OSVRRM_ROOT}" PATH) +endif() + +set(OSVRRM_NEED_SDL2 @OSVRRM_NEED_SDL2@) +set(OSVRRM_NEED_GLEW @OSVRRM_NEED_GLEW@) + +set(OSVRRM_PREV_CMAKE_MODULES ${CMAKE_MODULE_PATH}) +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}" ${CMAKE_MODULE_PATH}) +include("${CMAKE_CURRENT_LIST_DIR}/osvrRenderManagerConfigBuildTreeHints.cmake" OPTIONAL) +include(osvrStashMapConfig) +include(CMakeFindDependencyMacro) +if(OSVRRM_NEED_SDL2) + # TODO + #find_dependency(SDL2) +endif() +if(OSVRRM_NEED_GLEW) + # TODO + #find_dependency(GLEW) +endif() + +# Set up config mapping +osvr_stash_common_map_config() + +find_dependency(osvr) + +# restore module path +set(CMAKE_MODULE_PATH ${OSVRRM_PREV_CMAKE_MODULES}) + +# The actual exported targets - config mapping still applied. +include("${CMAKE_CURRENT_LIST_DIR}/osvrRenderManagerTargets.cmake") + +# Undo our changes for later consumers +osvr_unstash_common_map_config() + +if(NOT TARGET osvrRenderManager::osvrRenderManagerCpp) + add_library(osvrRenderManager::osvrRenderManagerCpp INTERFACE IMPORTED) + set_target_properties(osvrRenderManager::osvrRenderManagerCpp PROPERTIES + INTERFACE_LINK_LIBRARIES "osvrRenderManager::osvrRenderManager;osvr::osvrClientKitCpp") +endif() + +# Fix up imported targets to add deps: these files will only exist in install trees. +include("${CMAKE_CURRENT_LIST_DIR}/osvrRenderManagerConfigInstalledBoost.cmake" OPTIONAL) + +# A list of filenames of required libraries for running with osvrRenderManager DLL +set(OSVRRM_REQUIRED_LIBRARIES_DEBUG "@OSVRRM_REQUIRED_LIBRARIES_DEBUG@") +set(OSVRRM_REQUIRED_LIBRARIES_RELEASE "@OSVRRM_REQUIRED_LIBRARIES_RELEASE@") +set(OSVRRM_REQUIRED_LIBRARIES_RELWITHDEBINFO "@OSVRRM_REQUIRED_LIBRARIES_RELWITHDEBINFO@") +set(OSVRRM_REQUIRED_LIBRARIES_MINSIZEREL "@OSVRRM_REQUIRED_LIBRARIES_MINSIZEREL@") +set(OSVRRM_NEED_SDL2_COPIED @OSVRRM_NEED_SDL2_COPIED@) +set(OSVRRM_NEED_GLEW_COPIED @OSVRRM_NEED_GLEW_COPIED@) + +# Options +set(OSVRRM_HAVE_D3D11_SUPPORT @OSVRRM_HAVE_D3D11_SUPPORT@) +set(OSVRRM_HAVE_OPENGL_SUPPORT @OSVRRM_HAVE_OPENGL_SUPPORT@) +set(OSVRRM_USE_OPENGLES20 @OSVRRM_USE_OPENGLES20@) + +# Helper function to copy required libraries to an install directory +set(OSVRRM_CONFIG_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "" FORCE) +function(osvrrm_install_dependencies _destination) + foreach(_config Debug Release RelWithDebInfo MinSizeRel) + string(TOUPPER "${_config}" _CONFIG) + # Canonicalize paths relative to the directory containing this .cmake file + set(_files) + foreach(_file IN LISTS OSVRRM_REQUIRED_LIBRARIES_${_CONFIG}) + get_filename_component(_file "${_file}" ABSOLUTE BASE_DIR "${OSVRRM_CONFIG_DIR}") + list(APPEND _files "${_file}") + endforeach() + install(FILES + ${_files} + CONFIGURATIONS ${_config} + DESTINATION ${_destination} + COMPONENT Runtime + OPTIONAL) + endforeach() + set(OSVRRM_NEED_D3DCOMPILER_COPIED @OSVRRM_NEED_D3DCOMPILER_COPIED@) + if(OSVRRM_NEED_D3DCOMPILER_COPIED) + install(FILES "@OSVRRM_D3DCOMPILER_FILE@" + DESTINATION ${_destination} + COMPONENT Runtime + OPTIONAL) + endif() +endfunction() + +# Find SDL2 using the script bundled with RenderManager. +macro(osvrrm_find_SDL2) + set(OSVRRM_PREV_CMAKE_MODULES ${CMAKE_MODULE_PATH}) + set(CMAKE_MODULE_PATH "${OSVRRM_CONFIG_DIR}" ${CMAKE_MODULE_PATH}) + find_package(SDL2 ${ARGN}) + set(CMAKE_MODULE_PATH ${OSVRRM_PREV_CMAKE_MODULES}) +endmacro() + +# Find GLEW using the script bundled with RenderManager. +macro(osvrrm_find_GLEW) + set(OSVRRM_PREV_CMAKE_MODULES ${CMAKE_MODULE_PATH}) + set(CMAKE_MODULE_PATH "${OSVRRM_CONFIG_DIR}" ${CMAKE_MODULE_PATH}) + find_package(GLEW ${ARGN}) + set(CMAKE_MODULE_PATH ${OSVRRM_PREV_CMAKE_MODULES}) +endmacro() + +# Hook for a super-build to optionally inject configuration after target import. +include("${CMAKE_CURRENT_LIST_DIR}/osvrRenderManagerConfigSuperBuildSuffix.cmake" OPTIONAL) diff --git a/cmake/osvrRenderManagerConfigBuildTreeHints.cmake.in b/cmake/osvrRenderManagerConfigBuildTreeHints.cmake.in new file mode 100644 index 0000000..a8852ee --- /dev/null +++ b/cmake/osvrRenderManagerConfigBuildTreeHints.cmake.in @@ -0,0 +1,39 @@ +# Help find OSVR, if required. +if(NOT osvr_DIR) + set(osvr_DIR "@osvr_DIR@" CACHE PATH "" FORCE) +endif() + +# Help find Eigen3 +if(NOT EIGEN3_INCLUDE_DIR) + set(EIGEN3_INCLUDE_DIR "@EIGEN3_INCLUDE_DIR@" CACHE PATH "" FORCE) +endif() + +# Help with SDL2 +if(OSVRRM_NEED_SDL2) + if(WIN32 AND NOT SDL2_RUNTIME_LIBRARY) + set(SDL2_RUNTIME_LIBRARY "@SDL2_RUNTIME_LIBRARY@" CACHE FILEPATH "" FORCE) + endif() + if(NOT SDL2_LIBRARY) + set(SDL2_LIBRARY "@SDL2_LIBRARY@" CACHE FILEPATH "" FORCE) + endif() + if(NOT SDL2_INCLUDE_DIR) + set(SDL2_INCLUDE_DIR "@SDL2_INCLUDE_DIR@" CACHE PATH "" FORCE) + endif() + set(OSVRRM_SDL2MAIN @OSVRRM_SDL2MAIN@) + if(OSVRRM_SDL2MAIN AND NOT SDL2_SDLMAIN_LIBRARY) + set(SDL2_SDLMAIN_LIBRARY "@SDL2_SDLMAIN_LIBRARY@" CACHE FILEPATH "" FORCE) + endif() +endif() + +# Help with GLEW +if(OSVRRM_NEED_GLEW) + if(WIN32 AND NOT GLEW_RUNTIME_LIBRARY) + set(GLEW_RUNTIME_LIBRARY "@GLEW_RUNTIME_LIBRARY@" CACHE FILEPATH "" FORCE) + endif() + if(NOT GLEW_LIBRARY) + set(GLEW_LIBRARY "@GLEW_LIBRARY@" CACHE FILEPATH "" FORCE) + endif() + if(NOT GLEW_INCLUDE_DIR) + set(GLEW_INCLUDE_DIR "@GLEW_INCLUDE_DIR@" CACHE PATH "" FORCE) + endif() +endif() diff --git a/cmake/osvrRenderManagerConfigInstalledBoost.cmake b/cmake/osvrRenderManagerConfigInstalledBoost.cmake new file mode 100644 index 0000000..ab1be9c --- /dev/null +++ b/cmake/osvrRenderManagerConfigInstalledBoost.cmake @@ -0,0 +1,16 @@ +# File included only with installed binaries, to re-find Boost on those systems. + +if(NOT BOOST_FOUND) + # Optionally help Windows machines find Boost easier. + include("${CMAKE_CURRENT_LIST_DIR}/CMakeBoostHelper.cmake" OPTIONAL) +endif() +find_package(Boost QUIET) + +if(BOOST_FOUND) + # Boost is optional for UtilCpp - lots of stuff needs it, but lots doesn't. + set_property(TARGET osvr::osvrUtilCpp APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIRS}) +endif() + +# Boost is required for these bindings. Adding regardless of if we found it - make the build fail early if it's not found. +set_property(TARGET osvr::osvrClientKitCpp APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIRS}) +set_property(TARGET osvr::osvrPluginKitCpp APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIRS}) diff --git a/cmake/osvrStashMapConfig.cmake b/cmake/osvrStashMapConfig.cmake new file mode 100644 index 0000000..3183fe9 --- /dev/null +++ b/cmake/osvrStashMapConfig.cmake @@ -0,0 +1,61 @@ +# Manipulate CMAKE_MAP_IMPORTED_CONFIG_ cautiously and reversibly. +macro(osvr_stash_map_config config) + # Re-entrancy protection + list(APPEND OSVR_IN_MAP_CONFIG_STASH_${config} yes) + list(LENGTH OSVR_IN_MAP_CONFIG_STASH_${config} OSVR_IN_MAP_CONFIG_STASH_LEN) + if(OSVR_IN_MAP_CONFIG_STASH_LEN GREATER 1) + # Not the first stash, get out. + return() + endif() + + # Actually perform the saving and replacement of CMAKE_MAP_IMPORTED_CONFIG_${config} + if(DEFINED CMAKE_MAP_IMPORTED_CONFIG_${config}) + set(OSVR_OLD_CMAKE_MAP_IMPORTED_CONFIG_${config} ${CMAKE_MAP_IMPORTED_CONFIG_${config}}) + endif() + set(CMAKE_MAP_IMPORTED_CONFIG_${config} ${ARGN}) +endmacro() + +macro(osvr_unstash_map_config config) + if(NOT DEFINED OSVR_IN_MAP_CONFIG_STASH_${config}) + # Nobody actually called the matching stash... + return() + endif() + # Other half of re-entrancy protection + list(REMOVE_AT OSVR_IN_MAP_CONFIG_STASH_${config} -1) + list(LENGTH OSVR_IN_MAP_CONFIG_STASH_${config} OSVR_IN_MAP_CONFIG_STASH_LEN) + if(OSVR_IN_MAP_CONFIG_STASH_LEN GREATER 0) + # someone still in here + return() + endif() + + # Restoration of CMAKE_MAP_IMPORTED_CONFIG_${config} + if(DEFINED OSVR_OLD_CMAKE_MAP_IMPORTED_CONFIG_${config}) + set(CMAKE_MAP_IMPORTED_CONFIG_${config} ${OSVR_OLD_CMAKE_MAP_IMPORTED_CONFIG_${config}}) + unset(OSVR_OLD_CMAKE_MAP_IMPORTED_CONFIG_${config}) + else() + unset(CMAKE_MAP_IMPORTED_CONFIG_${config}) + endif() +endmacro() + +macro(osvr_stash_common_map_config) + if(MSVC) + # Can't do this - different runtimes, incompatible ABI, etc. + set(OSVR_DEBUG_FALLBACK) + osvr_stash_map_config(DEBUG DEBUG) + else() + set(OSVR_DEBUG_FALLBACK DEBUG) + osvr_stash_map_config(DEBUG DEBUG RELWITHDEBINFO RELEASE MINSIZEREL NONE) + endif() + osvr_stash_map_config(RELEASE RELEASE RELWITHDEBINFO MINSIZEREL NONE ${OSVR_DEBUG_FALLBACK}) + osvr_stash_map_config(RELWITHDEBINFO RELWITHDEBINFO RELEASE MINSIZEREL NONE ${OSVR_DEBUG_FALLBACK}) + osvr_stash_map_config(MINSIZEREL MINSIZEREL RELEASE RELWITHDEBINFO NONE ${OSVR_DEBUG_FALLBACK}) + osvr_stash_map_config(NONE NONE RELEASE RELWITHDEBINFO MINSIZEREL ${OSVR_DEBUG_FALLBACK}) +endmacro() + +macro(osvr_unstash_common_map_config) + osvr_unstash_map_config(DEBUG) + osvr_unstash_map_config(RELEASE) + osvr_unstash_map_config(RELWITHDEBINFO) + osvr_unstash_map_config(MINSIZEREL) + osvr_unstash_map_config(NONE) +endmacro() From 01a1cb964019898fe6f51ab3a98ea82391de488a Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Tue, 20 Jun 2017 16:24:50 -0400 Subject: [PATCH 15/43] added android support --- OsvrRenderingPlugin.cpp | 1134 ++++++++++++++++++++++++++++++++++++++- PluginConfig.h | 4 +- Unity/IUnityGraphics.h | 1 + UnityRendererType.h | 5 +- 4 files changed, 1118 insertions(+), 26 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 761684c..9d98a06 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -35,16 +35,16 @@ Sensics, Inc. #include #include -// standard includes -#if defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) -#include -#include -#endif -#include #if UNITY_WIN #define NO_MINMAX #define WIN32_LEAN_AND_MEAN +// logging on windows +#if defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) +#include +#include +#endif //end define ENABLE_LOGGING +#include #endif // Include headers for the graphics APIs we support @@ -62,15 +62,25 @@ Sensics, Inc. // Needed for render buffer calls. OSVR will have called glewInit() for us // when we open the display. #include - #include - -#include -#include -#else // UNITY_WIN || UNITY_LINUX ^ // v others (mac) // +#elif UNITY_OSX // Mac OpenGL include #include -#endif // +#elif UNITY_ANDROID +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif //end unity_android +#include +#include #endif // SUPPORT_OPENGL // VARIABLES @@ -78,6 +88,86 @@ static IUnityInterfaces *s_UnityInterfaces = nullptr; static IUnityGraphics *s_Graphics = nullptr; static UnityRendererType s_deviceType = {}; +/// @todo is this redundant? (given renderParams) +static double s_nearClipDistance = 0.1; +/// @todo is this redundant? (given renderParams) +static double s_farClipDistance = 1000.0; +/// @todo is this redundant? (given renderParams) +static double s_ipd = 0.063; + +//cached viewport values +static std::uint32_t viewportWidth = 0; +static std::uint32_t viewportHeight = 0; + +#if UNITY_ANDROID +static JNIEnv* jniEnvironment = 0; + +static GLuint gProgram; +static GLuint gvPositionHandle; +static GLuint gvColorHandle; +static GLuint gvTexCoordinateHandle; +static GLuint guTextureUniformId; +static GLuint gvProjectionUniformId; +static GLuint gvViewUniformId; +static GLuint gvModelUniformId; +static GLuint gFrameBuffer; +static GLuint gTextureID; +static GLuint gLeftEyeTextureID; +static GLuint gRightEyeTextureID; +static bool gGraphicsInitializedOnce = false; // if setupGraphics has been called at least once +static bool gOSVRInitialized = false; +static bool gRenderManagerInitialized = false; + +static OSVR_ClientInterface gCamera = NULL; +static OSVR_ClientInterface gHead = NULL; +static int gReportNumber = 0; +static OSVR_ImageBufferElement *gLastFrame = nullptr; +static GLuint gLastFrameWidth = 0; +static GLuint gLastFrameHeight = 0; +static GLubyte *gTextureBuffer = nullptr; +static OSVR_GraphicsLibraryOpenGL gGraphicsLibrary = { 0 }; +static OSVR_RenderManager gRenderManager = nullptr; +static OSVR_RenderManagerOpenGL gRenderManagerOGL = nullptr; +static OSVR_RenderParams gRenderParams = { 0 }; +static std::vector buffers; +static std::vector gRenderTargets; +static bool contextSet = false; + +typedef struct OSVR_RenderTargetInfo { + GLuint colorBufferName; + GLuint depthBufferName; + GLuint frameBufferName; + GLuint renderBufferName; // @todo - do we need this? +} OSVR_RenderTargetInfo; + +static const char gVertexShader[] = +"uniform mat4 model;\n" +"uniform mat4 view;\n" +"uniform mat4 projection;\n" +"attribute vec4 vPosition;\n" +"attribute vec4 vColor;\n" +"attribute vec2 vTexCoordinate;\n" +"varying vec2 texCoordinate;\n" +"varying vec4 fragmentColor;\n" +"void main() {\n" +" gl_Position = projection * view * model * vPosition;\n" +" fragmentColor = vColor;\n" +" texCoordinate = vTexCoordinate;\n" +"}\n"; + +static const char gFragmentShader[] = +"precision mediump float;\n" +"uniform sampler2D uTexture;\n" +"varying vec2 texCoordinate;\n" +"varying vec4 fragmentColor;\n" +"void main()\n" +"{\n" +" gl_FragColor = fragmentColor * texture2D(uTexture, texCoordinate);\n" +//" gl_FragColor = texture2D(uTexture, texCoordinate);\n" +"}\n"; + + +#else //Windows, Linux, OSX static OSVR_RenderParams s_renderParams; static OSVR_RenderManager s_render = nullptr; static OSVR_RenderManagerD3D11 s_renderD3D = nullptr; @@ -90,26 +180,18 @@ static OSVR_RenderInfoCollection s_renderInfoCollection; static OSVR_GraphicsLibraryD3D11 s_libraryD3D; static void *s_leftEyeTexturePtr = nullptr; static void *s_rightEyeTexturePtr = nullptr; -/// @todo is this redundant? (given renderParams) -static double s_nearClipDistance = 0.1; -/// @todo is this redundant? (given renderParams) -static double s_farClipDistance = 1000.0; -/// @todo is this redundant? (given renderParams) -static double s_ipd = 0.063; -//cached viewport values -static std::uint32_t viewportWidth = 0; -static std::uint32_t viewportHeight = 0; static OSVR_ProjectionMatrix lastGoodProjMatrix; static OSVR_Pose3 lastGoodPose; static OSVR_ViewportDescription lastGoodViewportDescription; + #if defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) static std::ofstream s_debugLogFile; static std::streambuf *s_oldCout = nullptr; static std::streambuf *s_oldCerr = nullptr; #endif // defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) - +#endif //end Windows, Linux, OSX // D3D11 vars #if SUPPORT_D3D11 static D3D11_TEXTURE2D_DESC s_textureDesc; @@ -152,8 +234,20 @@ inline void DebugLog(const char *str) { #endif // defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) } +#if UNITY_ANDROID +//this OnLoadd gets called automatically +jint JNI_OnLoad(JavaVM* vm, void* reserved) { + jniEnvironment = 0; + vm->AttachCurrentThread(&jniEnvironment, 0); + return JNI_VERSION_1_6; +}cre +#endif void UNITY_INTERFACE_API ShutdownRenderManager() { DebugLog("[OSVR Rendering Plugin] Shutting down RenderManager."); +#if UNITY_ANDROID + ShutdownRenderManagerAndroid(); + return; +#endif if (s_render != nullptr) { osvrDestroyRenderManager(s_render); s_render = nullptr; @@ -250,12 +344,64 @@ inline void dispatchEventToRenderer(UnityRendererType renderer, } } +//@TODO InitSDLGL, ShreContext + + + /// Needs the calling convention, even though it's static and not exported, /// because it's registered as a callback on plugin load. static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) { switch (eventType) { case kUnityGfxDeviceEventInitialize: { +#if UNITY_ANDROID + mainActivityClass = jniEnvironment->FindClass("org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class + if (mainActivityClass == nullptr) { + return; + } + else { // if class found, continue + + jmethodID logmid = jniEnvironment->GetStaticMethodID(mainActivityClass, "logMsg", "(Ljava/lang/String;)V"); // find method + jmethodID setGlContextId = jniEnvironment->GetStaticMethodID(mainActivityClass, "setUnityMainContext", "()J"); // find method + if (setGlContextId == nullptr) + //cerr << "ERROR: method void mymain() not found !" << endl; + return; + else { + //load libs! + /* jmethodID loadLibsMID = jniEnvironment->GetStaticMethodID(mainActivityClass, "loadLibraries", "()V"); // find method + if(loadLibsMID == nullptr) + //cerr << "ERROR: method void mymain() not found !" << endl; + return; + else { + + jniEnvironment->CallStaticVoidMethod(mainActivityClass, loadLibsMID); + }*/ + + jlong currentEglContextHandle = jniEnvironment->CallStaticLongMethod(mainActivityClass, setGlContextId); // call method + long myLongValue = (long)currentEglContextHandle; + std::string stringy = "[OSVR-Unity-Android] setCurrentContext with handle: " + std::to_string(myLongValue); + jstring jstr2 = jniEnvironment->NewStringUTF(stringy.c_str()); + jniEnvironment->CallStaticVoidMethod(mainActivityClass, logmid, jstr2); + contextSet = true; + //cout << endl; + } + //create context + jmethodID getWidthMID = jniEnvironment->GetStaticMethodID(mainActivityClass, "getDisplayWidth", "()I"); // find method + jmethodID getHeightMID = jniEnvironment->GetStaticMethodID(mainActivityClass, "getDisplayHeight", "()I"); // find method + if (getWidthMID == nullptr || getHeightMID == nullptr) + //cerr << "ERROR: method void mymain() not found !" << endl; + return; + else { + + jint displayWidth = jniEnvironment->CallStaticIntMethod(mainActivityClass, getWidthMID); // call method + jint displayHeight = jniEnvironment->CallStaticIntMethod(mainActivityClass, getHeightMID); // call method + gWidth = (int)displayWidth; + gHeight = (int)displayHeight; + //cout << endl; + } + } +#endif + //@todo windows, osx context sharing DebugLog( "[OSVR Rendering Plugin] OnGraphicsDeviceEvent(Initialize).\n"); s_deviceType = s_Graphics->GetRenderer(); @@ -401,10 +547,889 @@ void SetRoomRotationUsingHead() {/* s_renderD3D-> SetRoomRotationUsingHead(); */ /// @todo does this actually get called from anywhere or is it dead code? void ClearRoomToWorldTransform() { /*s_render->ClearRoomToWorldTransform(); */} + +/////////ANDROID////////////////////////////////////////// +#if UNITY_ANDROID +inline osvr::renderkit::OSVR_ProjectionMatrix ConvertProjectionMatrix(::OSVR_ProjectionMatrix matrix) +{ + osvr::renderkit::OSVR_ProjectionMatrix ret = { 0 }; + ret.bottom = matrix.bottom; + ret.top = matrix.top; + ret.left = matrix.left; + ret.right = matrix.right; + ret.nearClip = matrix.nearClip; + ret.farClip = matrix.farClip; + return ret; +} + +static void checkReturnCode(OSVR_ReturnCode returnCode, const char *msg) { + if (returnCode != OSVR_RETURN_SUCCESS) { + //LOGI("[OSVR] OSVR method returned a failure: %s", msg); + throw std::runtime_error(msg); + } +} +// RAII wrapper around the RenderManager collection APIs for OpenGL +class RenderInfoCollectionOpenGL { +private: + OSVR_RenderManager mRenderManager = nullptr; + OSVR_RenderInfoCollection mRenderInfoCollection = nullptr; + OSVR_RenderParams mRenderParams = { 0 }; + +public: + RenderInfoCollectionOpenGL(OSVR_RenderManager renderManager, OSVR_RenderParams renderParams) + : mRenderManager(renderManager), mRenderParams(renderParams) { + OSVR_ReturnCode rc; + rc = osvrRenderManagerGetRenderInfoCollection(mRenderManager, mRenderParams, &mRenderInfoCollection); + checkReturnCode(rc, "osvrRenderManagerGetRenderInfoCollection call failed."); + } + + OSVR_RenderInfoCount getNumRenderInfo() { + OSVR_RenderInfoCount ret; + OSVR_ReturnCode rc; + rc = osvrRenderManagerGetNumRenderInfoInCollection(mRenderInfoCollection, &ret); + checkReturnCode(rc, "osvrRenderManagerGetNumRenderInfoInCollection call failed."); + return ret; + } + + OSVR_RenderInfoOpenGL getRenderInfo(OSVR_RenderInfoCount index) { + if (index < 0 || index >= getNumRenderInfo()) { + const static char* err = "getRenderInfo called with invalid index"; + //LOGE(err); + throw std::runtime_error(err); + } + OSVR_RenderInfoOpenGL ret; + OSVR_ReturnCode rc; + rc = osvrRenderManagerGetRenderInfoFromCollectionOpenGL(mRenderInfoCollection, index, &ret); + checkReturnCode(rc, "osvrRenderManagerGetRenderInfoFromCollectionOpenGL call failed."); + return ret; + } + + ~RenderInfoCollectionOpenGL() { + if (mRenderInfoCollection) { + osvrRenderManagerReleaseRenderInfoCollection(mRenderInfoCollection); + } + } +}; + +static void checkGlError(const char *op) { + std::stringstream ss; + for (GLint error = glGetError(); error; error = glGetError()) { + // gluErrorString without glu + std::string errorString; + switch (error) { + case GL_NO_ERROR: + errorString = "GL_NO_ERROR"; + break; + case GL_INVALID_ENUM: + errorString = "GL_INVALID_ENUM"; + break; + case GL_INVALID_VALUE: + errorString = "GL_INVALID_VALUE"; + break; + case GL_INVALID_OPERATION: + errorString = "GL_INVALID_OPERATION"; + break; + case GL_INVALID_FRAMEBUFFER_OPERATION: + errorString = "GL_INVALID_FRAMEBUFFER_OPERATION"; + break; + case GL_OUT_OF_MEMORY: + errorString = "GL_OUT_OF_MEMORY"; + break; + default: + errorString = "(unknown error)"; + break; + } + //LOGI("after %s() glError (%s)\n", op, errorString.c_str()); + } +} + +class PassThroughOpenGLContextImpl { + OSVR_OpenGLToolkitFunctions toolkit; + int mWidth; + int mHeight; + + static void createImpl(void* data) { + } + static void destroyImpl(void* data) { + delete ((PassThroughOpenGLContextImpl*)data); + } + static OSVR_CBool addOpenGLContextImpl(void* data, const OSVR_OpenGLContextParams* p) { + return ((PassThroughOpenGLContextImpl*)data)->addOpenGLContext(p); + } + static OSVR_CBool removeOpenGLContextsImpl(void* data) { + return ((PassThroughOpenGLContextImpl*)data)->removeOpenGLContexts(); + } + static OSVR_CBool makeCurrentImpl(void* data, size_t display) { + return ((PassThroughOpenGLContextImpl*)data)->makeCurrent(display); + } + static OSVR_CBool swapBuffersImpl(void* data, size_t display) { + return ((PassThroughOpenGLContextImpl*)data)->swapBuffers(display); + } + static OSVR_CBool setVerticalSyncImpl(void* data, OSVR_CBool verticalSync) { + return ((PassThroughOpenGLContextImpl*)data)->setVerticalSync(verticalSync); + } + static OSVR_CBool handleEventsImpl(void* data) { + return ((PassThroughOpenGLContextImpl*)data)->handleEvents(); + } + static OSVR_CBool getDisplayFrameBufferImpl(void* data, size_t display, GLuint* displayFrameBufferOut) { + return ((PassThroughOpenGLContextImpl*)data)->getDisplayFrameBuffer(display, displayFrameBufferOut); + } + static OSVR_CBool getDisplaySizeOverrideImpl(void* data, size_t display, int* width, int* height) { + return ((PassThroughOpenGLContextImpl*)data)->getDisplaySizeOverride(display, width, height); + } + + +public: + PassThroughOpenGLContextImpl() { + memset(&toolkit, 0, sizeof(toolkit)); + toolkit.size = sizeof(toolkit); + toolkit.data = this; + + toolkit.create = createImpl; + toolkit.destroy = destroyImpl; + toolkit.addOpenGLContext = addOpenGLContextImpl; + toolkit.removeOpenGLContexts = removeOpenGLContextsImpl; + toolkit.makeCurrent = makeCurrentImpl; + toolkit.swapBuffers = swapBuffersImpl; + toolkit.setVerticalSync = setVerticalSyncImpl; + toolkit.handleEvents = handleEventsImpl; + toolkit.getDisplaySizeOverride = getDisplaySizeOverrideImpl; + toolkit.getDisplayFrameBuffer = getDisplayFrameBufferImpl; + } + + ~PassThroughOpenGLContextImpl() { + } + + const OSVR_OpenGLToolkitFunctions* getToolkit() const { return &toolkit; } + + bool addOpenGLContext(const OSVR_OpenGLContextParams* p) { + return true; + } + + bool removeOpenGLContexts() { + return true; + } + + bool makeCurrent(size_t display) { + return true; + } + + bool swapBuffers(size_t display) { + return true; + } + + bool setVerticalSync(bool verticalSync) { + return true; + } + + bool handleEvents() { + return true; + } + bool getDisplayFrameBuffer(size_t display, GLuint* displayFrameBufferOut) { + *displayFrameBufferOut = gFrameBuffer; + return true; + } + + bool getDisplaySizeOverride(size_t display, int* width, int* height) { + *width = gWidth; + *height = gHeight; + return false; + } +}; + +static GLuint loadShader(GLenum shaderType, const char *pSource) { + GLuint shader = glCreateShader(shaderType); + if (shader) { + glShaderSource(shader, 1, &pSource, NULL); + glCompileShader(shader); + GLint compiled = 0; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (!compiled) { + GLint infoLen = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen) { + char *buf = (char *)malloc(infoLen); + if (buf) { + glGetShaderInfoLog(shader, infoLen, NULL, buf); + //LOGE("Could not compile shader %d:\n%s\n", + // shaderType, buf); + free(buf); + } + glDeleteShader(shader); + shader = 0; + } + } + } + return shader; +} + +static GLuint createProgram(const char *pVertexSource, const char *pFragmentSource) { + GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); + if (!vertexShader) { + return 0; + } + + GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); + if (!pixelShader) { + return 0; + } + + GLuint program = glCreateProgram(); + if (program) { + glAttachShader(program, vertexShader); + checkGlError("glAttachShader"); + + glAttachShader(program, pixelShader); + checkGlError("glAttachShader"); + + glBindAttribLocation(program, 0, "vPosition"); + glBindAttribLocation(program, 1, "vColor"); + glBindAttribLocation(program, 2, "vTexCoordinate"); + + glLinkProgram(program); + GLint linkStatus = GL_FALSE; + glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); + if (linkStatus != GL_TRUE) { + GLint bufLength = 0; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); + if (bufLength) { + char *buf = (char *)malloc(bufLength); + if (buf) { + glGetProgramInfoLog(program, bufLength, NULL, buf); + // LOGE("Could not link program:\n%s\n", buf); + free(buf); + } + } + glDeleteProgram(program); + program = 0; + } + } + return program; +} + +static GLuint createTexture(GLuint width, GLuint height) { + GLuint ret; + glGenTextures(1, &ret); + checkGlError("glGenTextures"); + + glBindTexture(GL_TEXTURE_2D, ret); + checkGlError("glBindTexture"); + + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + // // DEBUG CODE - should be passing null here, but then texture is always black. + GLubyte *dummyBuffer = new GLubyte[width * height * 4]; + for (GLuint i = 0; i < width * height * 4; i++) { + dummyBuffer[i] = (i % 4 ? 100 : 255); + } + + // This dummy texture successfully makes it into the texture and renders, but subsequent + // calls to glTexSubImage2D don't appear to do anything. + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, + dummyBuffer); + checkGlError("glTexImage2D"); + delete[] dummyBuffer; + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + checkGlError("glTexParameteri"); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + checkGlError("glTexParameteri"); + return ret; +} + +static void updateTexture(GLuint width, GLuint height, GLubyte *data) { + + glBindTexture(GL_TEXTURE_2D, gTextureID); + checkGlError("glBindTexture"); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + // @todo use glTexSubImage2D to be faster here, but add check to make sure height/width are the same. + //glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); + //checkGlError("glTexSubImage2D"); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + checkGlError("glTexImage2D"); +} + +static void imagingCallback(void *userdata, const OSVR_TimeValue *timestamp, + const OSVR_ImagingReport *report) { + + OSVR_ClientContext *ctx = (OSVR_ClientContext *)userdata; + + gReportNumber++; + GLuint width = report->state.metadata.width; + GLuint height = report->state.metadata.height; + gLastFrameWidth = width; + gLastFrameHeight = height; + GLuint size = width * height * 4; + + gLastFrame = report->state.data; +} +#if SUPPORT_OPENGL +inline GLuint GetEyeTextureOpenGL(int eye) { + return (eye == 0) ? gLeftEyeTextureID : gRightEyeTextureID; +} +#endif +static bool setupRenderTextures(OSVR_RenderManager renderManager) { + try { + OSVR_ReturnCode rc; + rc = osvrRenderManagerGetDefaultRenderParams(&gRenderParams); + checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); + + gRenderParams.farClipDistanceMeters = 1000000.0f; + gRenderParams.nearClipDistanceMeters = 0.0000001f; + RenderInfoCollectionOpenGL renderInfo(renderManager, gRenderParams); + + OSVR_RenderManagerRegisterBufferState state; + rc = osvrRenderManagerStartRegisterRenderBuffers(&state); + checkReturnCode(rc, "osvrRenderManagerStartRegisterRenderBuffers call failed."); + + for (OSVR_RenderInfoCount i = 0; i < renderInfo.getNumRenderInfo(); i++) { + OSVR_RenderInfoOpenGL currentRenderInfo = renderInfo.getRenderInfo(i); + + // Determine the appropriate size for the frame buffer to be used for + // all eyes when placed horizontally size by side. + int width = static_cast(currentRenderInfo.viewport.width); + int height = static_cast(currentRenderInfo.viewport.height); + + GLuint frameBufferName = 0; + glGenFramebuffers(1, &frameBufferName); + glBindFramebuffer(GL_FRAMEBUFFER, frameBufferName); + + GLuint renderBufferName = 0; + glGenRenderbuffers(1, &renderBufferName); + + GLuint colorBufferName = GetEyeTextureOpenGL(i); + rc = osvrRenderManagerCreateColorBufferOpenGL(width, height, GL_RGBA, + &colorBufferName); + checkReturnCode(rc, "osvrRenderManagerCreateColorBufferOpenGL call failed."); + + // bind it to our framebuffer + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + colorBufferName, 0); + + // The depth buffer + GLuint depthBuffer; + rc = osvrRenderManagerCreateDepthBufferOpenGL(width, height, &depthBuffer); + checkReturnCode(rc, "osvrRenderManagerCreateDepthBufferOpenGL call failed."); + + glGenRenderbuffers(1, &depthBuffer); + glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, + depthBuffer); + + glBindRenderbuffer(GL_RENDERBUFFER, renderBufferName); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferName, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderBufferName); + + + // unbind the framebuffer + glBindTexture(GL_TEXTURE_2D, 0); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, gFrameBuffer); + + OSVR_RenderBufferOpenGL buffer = { 0 }; + buffer.colorBufferName = colorBufferName; + buffer.depthStencilBufferName = depthBuffer; + rc = osvrRenderManagerRegisterRenderBufferOpenGL(state, buffer); + checkReturnCode(rc, "osvrRenderManagerRegisterRenderBufferOpenGL call failed."); + + OSVR_RenderTargetInfo renderTarget = { 0 }; + renderTarget.frameBufferName = frameBufferName; + renderTarget.renderBufferName = renderBufferName; + renderTarget.colorBufferName = colorBufferName; + renderTarget.depthBufferName = depthBuffer; + gRenderTargets.push_back(renderTarget); + } + + rc = osvrRenderManagerFinishRegisterRenderBuffers(renderManager, state, true); + checkReturnCode(rc, "osvrRenderManagerFinishRegisterRenderBuffers call failed."); + } + catch (...) { + //LOGE("Error durring render target creation."); + return false; + } + return true; +} + +static bool setupOSVR() { + if (gOSVRInitialized) { + return true; + } + OSVR_ReturnCode rc = 0; + try { + // On Android, the current working directory is added to the default plugin search path. + // it also helps the server find its configuration and display files. + // boost::filesystem::current_path("/data/data/com.osvr.android.gles2sample/files"); + // auto workingDirectory = boost::filesystem::current_path(); + // //LOGI("[OSVR] Current working directory: %s", workingDirectory.string().c_str()); + + // auto-start the server + osvrClientAttemptServerAutoStart(); + + if (!gClientContext) { + //LOGI("[OSVR] Creating ClientContext..."); + gClientContext = osvrClientInit("com.osvr.android.examples.OSVROpenGL", 0); + if (!gClientContext) { + //LOGI("[OSVR] could not create client context"); + return false; + } + + // temporary workaround to DisplayConfig issue, + // display sometimes fails waiting for the tree from the server. + //LOGI("[OSVR] Calling update a few times..."); + for (int i = 0; i < 10000; i++) { + rc = osvrClientUpdate(gClientContext); + if (rc != OSVR_RETURN_SUCCESS) { + //LOGI("[OSVR] Error while updating client context."); + return false; + } + } + + + rc = osvrClientCheckStatus(gClientContext); + if (rc != OSVR_RETURN_SUCCESS) { + //LOGI("[OSVR] Client context reported bad status."); + return false; + } + else { + //LOGI("[OSVR] Client context reported good status."); + } + + + // if (OSVR_RETURN_SUCCESS != + // osvrClientGetInterface(gClientContext, "/camera", &gCamera)) { + // //LOGI("Error, could not get the camera interface at /camera."); + // return false; + // } + // + // // Register the imaging callback. + // if (OSVR_RETURN_SUCCESS != + // osvrRegisterImagingCallback(gCamera, &imagingCallback, &gClientContext)) { + // //LOGI("Error, could not register image callback."); + // return false; + // } + } + + gOSVRInitialized = true; + return true; + } + catch (const std::runtime_error &ex) { + //LOGI("[OSVR] OSVR initialization failed: %s", ex.what()); + return false; + } +} + +// Idempotent call to setup render manager +static bool setupRenderManager() { + if (!gOSVRInitialized || !gGraphicsInitializedOnce) { + return false; + } + if (gRenderManagerInitialized) { + return true; + } + try { + PassThroughOpenGLContextImpl* glContextImpl = new PassThroughOpenGLContextImpl(); + gGraphicsLibrary.toolkit = glContextImpl->getToolkit(); + + if (OSVR_RETURN_SUCCESS != osvrCreateRenderManagerOpenGL( + gClientContext, "OpenGL", gGraphicsLibrary, &gRenderManager, &gRenderManagerOGL)) { + std::cerr << "Could not create the RenderManager" << std::endl; + return false; + } + + + + // Open the display and make sure this worked + OSVR_OpenResultsOpenGL openResults; + if (OSVR_RETURN_SUCCESS != osvrRenderManagerOpenDisplayOpenGL( + gRenderManagerOGL, &openResults) || + (openResults.status == OSVR_OPEN_STATUS_FAILURE)) { + std::cerr << "Could not open display" << std::endl; + osvrDestroyRenderManager(gRenderManager); + gRenderManager = gRenderManagerOGL = nullptr; + return false; + } + + gRenderManagerInitialized = true; + return true; + } + catch (const std::runtime_error &ex) { + //LOGI("[OSVR] RenderManager initialization failed: %s", ex.what()); + return false; + } +} +static const GLfloat gTriangleColors[] = { + // white + 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, + + // green + 0.0f, 0.75f, 0.0f, 1.0f, + 0.0f, 0.75f, 0.0f, 1.0f, + 0.0f, 1.0f, 0.0f, 1.0f, + 0.0f, 0.75f, 0.0f, 1.0f, + 0.0f, 1.0f, 0.0f, 1.0f, + 0.0f, 1.0f, 0.0f, 1.0f, + + // blue + 0.0f, 0.0f, 0.75f, 1.0f, + 0.0f, 0.0f, 0.75f, 1.0f, + 0.0f, 0.0f, 1.0f, 1.0f, + 0.0f, 0.0f, 0.75f, 1.0f, + 0.0f, 0.0f, 1.0f, 1.0f, + 0.0f, 0.0f, 1.0f, 1.0f, + + // green/purple + 0.0f, 0.75f, 0.75f, 1.0f, + 0.0f, 0.75f, 0.75f, 1.0f, + 0.0f, 1.0f, 1.0f, 1.0f, + 0.0f, 0.75f, 0.75f, 1.0f, + 0.0f, 1.0f, 1.0f, 1.0f, + 0.0f, 1.0f, 1.0f, 1.0f, + + // red/green + 0.75f, 0.75f, 0.0f, 1.0f, + 0.75f, 0.75f, 0.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, + 0.75f, 0.75f, 0.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 1.0f, + + // red/blue + 0.75f, 0.0f, 0.75f, 1.0f, + 0.75f, 0.0f, 0.75f, 1.0f, + 1.0f, 0.0f, 1.0f, 1.0f, + 0.75f, 0.0f, 0.75f, 1.0f, + 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 0.0f, 1.0f, 1.0f +}; + +static const GLfloat gTriangleTexCoordinates[] = { + // A cube face (letters are unique vertices) + // A--B + // | | + // D--C + + // As two triangles (clockwise) + // A B D + // B C D + + // white + 1.0f, 0.0f, // A + 1.0f, 1.0f, // B + 0.0f, 0.0f, // D + 1.0f, 1.0f, // B + 0.0f, 1.0f, // C + 0.0f, 0.0f, // D + + // green + 1.0f, 0.0f, // A + 1.0f, 1.0f, // B + 0.0f, 0.0f, // D + 1.0f, 1.0f, // B + 0.0f, 1.0f, // C + 0.0f, 0.0f, // D + + // blue + 1.0f, 1.0f, // A + 0.0f, 1.0f, // B + 1.0f, 0.0f, // D + 0.0f, 1.0f, // B + 0.0f, 0.0f, // C + 1.0f, 0.0f, // D + + // blue-green + 1.0f, 0.0f, // A + 1.0f, 1.0f, // B + 0.0f, 0.0f, // D + 1.0f, 1.0f, // B + 0.0f, 1.0f, // C + 0.0f, 0.0f, // D + + // yellow + 0.0f, 0.0f, // A + 1.0f, 0.0f, // B + 0.0f, 1.0f, // D + 1.0f, 0.0f, // B + 1.0f, 1.0f, // C + 0.0f, 1.0f, // D + + // purple/magenta + 1.0f, 1.0f, // A + 0.0f, 1.0f, // B + 1.0f, 0.0f, // D + 0.0f, 1.0f, // B + 0.0f, 0.0f, // C + 1.0f, 0.0f, // D +}; + +static const GLfloat gTriangleVertices[] = { + // A cube face (letters are unique vertices) + // A--B + // | | + // D--C + + // As two triangles (clockwise) + // A B D + // B C D + + //glNormal3f(0.0, 0.0, -1.0); + 1.0f, 1.0f, -1.0f, // A + 1.0f, -1.0f, -1.0f, // B + -1.0f, 1.0f, -1.0f, // D + 1.0f, -1.0f, -1.0f, // B + -1.0f, -1.0f, -1.0f, // C + -1.0f, 1.0f, -1.0f, // D + + //glNormal3f(0.0, 0.0, 1.0); + -1.0f, 1.0f, 1.0f, // A + -1.0f, -1.0f, 1.0f, // B + 1.0f, 1.0f, 1.0f, // D + -1.0f, -1.0f, 1.0f, // B + 1.0f, -1.0f, 1.0f, // C + 1.0f, 1.0f, 1.0f, // D + + // glNormal3f(0.0, -1.0, 0.0); + 1.0f, -1.0f, 1.0f, // A + -1.0f, -1.0f, 1.0f, // B + 1.0f, -1.0f, -1.0f, // D + -1.0f, -1.0f, 1.0f, // B + -1.0f, -1.0f, -1.0f, // C + 1.0f, -1.0f, -1.0f, // D + + // glNormal3f(0.0, 1.0, 0.0); + 1.0f, 1.0f, 1.0f, // A + 1.0f, 1.0f, -1.0f, // B + -1.0f, 1.0f, 1.0f, // D + 1.0f, 1.0f, -1.0f, // B + -1.0f, 1.0f, -1.0f, // C + -1.0f, 1.0f, 1.0f, // D + + // glNormal3f(-1.0, 0.0, 0.0); + -1.0f, 1.0f, 1.0f, // A + -1.0f, 1.0f, -1.0f, // B + -1.0f, -1.0f, 1.0f, // D + -1.0f, 1.0f, -1.0f, // B + -1.0f, -1.0f, -1.0f, // C + -1.0f, -1.0f, 1.0f, // D + + // glNormal3f(1.0, 0.0, 0.0); + 1.0f, -1.0f, 1.0f, // A + 1.0f, -1.0f, -1.0f, // B + 1.0f, 1.0f, 1.0f, // D + 1.0f, -1.0f, -1.0f, // B + 1.0f, 1.0f, -1.0f, // C + 1.0f, 1.0f, 1.0f // D +}; + +static bool setupGraphics(int width, int height) { + //printGLString("Version", GL_VERSION); + //printGLString("Vendor", GL_VENDOR); + //printGLString("Renderer", GL_RENDERER); + //printGLString("Extensions", GL_EXTENSIONS); + + //initializeGLES2Ext(); + GLint frameBuffer; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &frameBuffer); + gFrameBuffer = (GLuint)frameBuffer; + //LOGI("Window GL_FRAMEBUFFER_BINDING: %d", gFrameBuffer); + + //LOGI("setupGraphics(%d, %d)", width, height); + //gWidth = width; + //gHeight = height; + + //bool osvrSetupSuccess = setupOSVR(); + + gProgram = createProgram(gVertexShader, gFragmentShader); + if (!gProgram) { + //LOGE("Could not create program."); + mainActivityClass = jniEnvironment->FindClass("org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class + if (mainActivityClass == nullptr) { + return false; + } + else { // if class found, continue + + jmethodID logmid = jniEnvironment->GetStaticMethodID(mainActivityClass, "logMsg", "(Ljava/lang/String;)V"); // find method + std::string stringy = "[OSVR-Unity-Android] Could not create program."; + jstring jstr2 = jniEnvironment->NewStringUTF(stringy.c_str()); + jniEnvironment->CallStaticVoidMethod(mainActivityClass, logmid, jstr2); + } + return false; + } + gvPositionHandle = glGetAttribLocation(gProgram, "vPosition"); + checkGlError("glGetAttribLocation"); + //LOGI("glGetAttribLocation(\"vPosition\") = %d\n", gvPositionHandle); + + gvColorHandle = glGetAttribLocation(gProgram, "vColor"); + checkGlError("glGetAttribLocation"); + //LOGI("glGetAttribLocation(\"vColor\") = %d\n", gvColorHandle); + + gvTexCoordinateHandle = glGetAttribLocation(gProgram, "vTexCoordinate"); + checkGlError("glGetAttribLocation"); + //LOGI("glGetAttribLocation(\"vTexCoordinate\") = %d\n", gvTexCoordinateHandle); + + gvProjectionUniformId = glGetUniformLocation(gProgram, "projection"); + gvViewUniformId = glGetUniformLocation(gProgram, "view"); + gvModelUniformId = glGetUniformLocation(gProgram, "model"); + guTextureUniformId = glGetUniformLocation(gProgram, "uTexture"); + + glViewport(0, 0, width, height); + checkGlError("glViewport"); + + glDisable(GL_CULL_FACE); + + // @todo can we resize the texture after it has been created? + // if not, we may have to delete the dummy one and create a new one after + // the first imaging report. + //LOGI("Creating texture... here we go!"); + + gTextureID = createTexture(width, height); + + //return osvrSetupSuccess; + gGraphicsInitializedOnce = true; + return true; +} + +/** +* Just the current frame in the display. +*/ +static void renderFrame() { + if (!gOSVRInitialized) { + // @todo implement some logging/error handling? + return; + } + + // this call is idempotent, so we can make it every frame. + // have to ensure render manager is setup from the rendering thread with + // a current GLES context, so this is a lazy setup call + if (!setupRenderManager()) { + // @todo implement some logging/error handling? + return; + } + + OSVR_ReturnCode rc; + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + checkGlError("glClearColor"); + glViewport(0, 0, gWidth, gHeight); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + checkGlError("glClear"); + + + if (gRenderManager && gClientContext) { + osvrClientUpdate(gClientContext); + if (gLastFrame != nullptr) { + updateTexture(gLastFrameWidth, gLastFrameHeight, gLastFrame); + osvrClientFreeImage(gClientContext, gLastFrame); + gLastFrame = nullptr; + } + + OSVR_RenderParams renderParams; + rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); + checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); + + RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, renderParams); + + // Get the present started + OSVR_RenderManagerPresentState presentState; + rc = osvrRenderManagerStartPresentRenderBuffers(&presentState); + checkReturnCode(rc, "osvrRenderManagerStartPresentRenderBuffers call failed."); + + for (OSVR_RenderInfoCount renderInfoCount = 0; + renderInfoCount < renderInfoCollection.getNumRenderInfo(); + renderInfoCount++) { + + // get the current render info + OSVR_RenderInfoOpenGL currentRenderInfo = renderInfoCollection.getRenderInfo(renderInfoCount); + // Set color and depth buffers for the frame buffer + OSVR_RenderTargetInfo renderTargetInfo = gRenderTargets[renderInfoCount]; + + // present this render target (deferred until the finish call below) + OSVR_ViewportDescription normalizedViewport = { 0 }; + normalizedViewport.left = 0.0f; + normalizedViewport.lower = 0.0f; + normalizedViewport.width = 1.0f; + normalizedViewport.height = 1.0f; + OSVR_RenderBufferOpenGL buffer = { 0 }; + buffer.colorBufferName = GetEyeTextureOpenGL(renderInfoCount); + buffer.depthStencilBufferName = renderTargetInfo.depthBufferName; + + rc = osvrRenderManagerPresentRenderBufferOpenGL( + presentState, buffer, currentRenderInfo, normalizedViewport); + checkReturnCode(rc, "osvrRenderManagerPresentRenderBufferOpenGL call failed."); + } + + // actually kick off the present + rc = osvrRenderManagerFinishPresentRenderBuffers( + gRenderManager, presentState, renderParams, false); + checkReturnCode(rc, "osvrRenderManagerFinishPresentRenderBuffers call failed."); + } + +} + + +static void stop() { + //LOGI("[OSVR] Shutting down..."); + + if (gRenderManager) { + osvrDestroyRenderManager(gRenderManager); + gRenderManager = gRenderManagerOGL = nullptr; + } + + // is this needed? Maybe not. the display config manages the lifetime. + if (gClientContext != nullptr) { + osvrClientShutdown(gClientContext); + gClientContext = nullptr; + } + + osvrClientReleaseAutoStartedServer(); +} + +OSVR_ReturnCode CreateRenderManagerAndroid(OSVR_ClientContext context) { + s_clientContext = context; + if(setupOSVR()) + { + if (setupGraphics(gWidth, gHeight)) + { + if (setupRenderManager()) + { + return OSVR_RETURN_SUCCESS; + } + else return 3; + } + else return 2; +} + else return 1; + + return OSVR_RETURN_SUCCESS; +} + +void ShutdownRenderManagerAndroid() +{ + stop(); + contextSet = false; +} +#endif +/////////end ANDROID////////////////////////////////////// + + // Called from Unity to create a RenderManager, passing in a ClientContext OSVR_ReturnCode UNITY_INTERFACE_API CreateRenderManagerFromUnity(OSVR_ClientContext context) { - +#if UNITY_ANDROID + return CreateRenderManagerAndroid(context); +#endif if (s_render != nullptr) { if (osvrRenderManagerGetDoingOkay(s_render)) { DebugLog("[OSVR Rendering Plugin] RenderManager already created " @@ -510,6 +1535,9 @@ template inline OSVR_ReturnCode applyRenderBufferConstructor(const int numBuffers, F &&bufferConstructor, G &&bufferCleanup) { +#if UNITY_ANDROID + return OSVR_RETURN_SUCCESS; +#endif /// If we bail any time before the end, we'll automatically clean up the /// render buffers with this lambda. /* auto cleanupBuffers = osvr::util::finally([&] { @@ -695,6 +1723,12 @@ inline void CleanupBufferD3D11(OSVR_RenderBufferD3D11 &rb) { #endif // SUPPORT_D3D11 OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { +#if UNITY_ANDROID + if (!setupRenderTextures(gRenderManager)) { + return 10; + } + else return OSVR_RETURN_SUCCESS; +#endif if (!s_deviceType) { DebugLog("[OSVR Rendering Plugin] Device type not supported."); return OSVR_RETURN_FAILURE; @@ -725,12 +1759,17 @@ OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { void UNITY_INTERFACE_API SetNearClipDistance(double distance) { s_nearClipDistance = distance; +#if !UNITY_ANDROID s_renderParams.nearClipDistanceMeters = s_nearClipDistance; +#endif } void UNITY_INTERFACE_API SetFarClipDistance(double distance) { s_farClipDistance = distance; +#if !UNITY_ANDROID s_renderParams.farClipDistanceMeters = s_farClipDistance; +#endif + } void UNITY_INTERFACE_API SetIPD(double ipdMeters) { @@ -740,6 +1779,19 @@ void UNITY_INTERFACE_API SetIPD(double ipdMeters) { OSVR_ViewportDescription UNITY_INTERFACE_API GetViewport(std::uint8_t eye) { +#if UNITY_ANDROID + OSVR_RenderParams renderParams; + OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); + checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); + RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, renderParams); + OSVR_RenderInfoOpenGL currentRenderInfo = renderInfoCollection.getRenderInfo(eye); + osvr::renderkit::OSVR_ViewportDescription viewDesc; + viewDesc.width = currentRenderInfo.viewport.width; + viewDesc.height = currentRenderInfo.viewport.height; + viewDesc.left = currentRenderInfo.viewport.left; + viewDesc.lower = currentRenderInfo.viewport.lower; + return viewDesc; +#endif OSVR_ViewportDescription viewportDescription; if (s_lastRenderInfo.size() > 0 && eye <= s_lastRenderInfo.size() - 1) { @@ -775,6 +1827,22 @@ GetViewport(std::uint8_t eye) { OSVR_ProjectionMatrix UNITY_INTERFACE_API GetProjectionMatrix(std::uint8_t eye) { +#if UNITY_ANDROID + OSVR_RenderParams renderParams; + OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); + checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); + RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, renderParams); + OSVR_RenderInfoOpenGL currentRenderInfo = renderInfoCollection.getRenderInfo(eye); + osvr::renderkit::OSVR_ProjectionMatrix proj; + proj.left = currentRenderInfo.projection.left; + proj.right = currentRenderInfo.projection.right; + proj.top = currentRenderInfo.projection.top; + proj.bottom = currentRenderInfo.projection.bottom; + proj.nearClip = currentRenderInfo.projection.nearClip; + proj.farClip = currentRenderInfo.projection.farClip; + return proj; +} +#endif OSVR_ProjectionMatrix pm; if (s_lastRenderInfo.size() > 0 && eye <= s_lastRenderInfo.size() - 1) { @@ -791,6 +1859,14 @@ GetProjectionMatrix(std::uint8_t eye) { } OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { +#if UNITY_ANDROID + OSVR_RenderParams renderParams; + OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); + checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); + RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, renderParams); + OSVR_RenderInfoOpenGL currentRenderInfo = renderInfoCollection.getRenderInfo(eye); + return currentRenderInfo.pose; +#endif OSVR_Pose3 pose; osvrPose3SetIdentity(&pose); if (s_lastRenderInfo.size() > 0 && eye <= s_lastRenderInfo.size() - 1) @@ -826,6 +1902,15 @@ int UNITY_INTERFACE_API SetColorBufferFromUnity(void *texturePtr, std::uint8_t e } DebugLog("[OSVR Rendering Plugin] SetColorBufferFromUnity"); + +#if UNITY_ANDROID + if (eye == 0) { + gLeftEyeTextureID = (GLuint)texturePtr; + } else { + gRightEyeTextureID = (GLuint)texturePtr; + } + return OSVR_RETURN_SUCCESS; +#endif if (eye == 0) { s_leftEyeTexturePtr = texturePtr; } else { @@ -968,6 +2053,9 @@ inline void DoRender() { #if SUPPORT_OPENGL case OSVRSupportedRenderers::OpenGL: { +#if UNITY_ANDROID + renderFrame(); +#endif // OpenGL //@todo OpenGL path is not working yet // Render into each buffer using the specified information. diff --git a/PluginConfig.h b/PluginConfig.h index 564dd1b..ef3599f 100644 --- a/PluginConfig.h +++ b/PluginConfig.h @@ -28,6 +28,8 @@ // Which platform we are on? #ifdef _WIN32 #define UNITY_WIN 1 +#elif define(__ANDROID__) +#define UNITY_ANDROID 1 #elif defined(__APPLE__) #define UNITY_OSX 1 #elif defined(__linux__) @@ -40,7 +42,7 @@ #if UNITY_WIN #define SUPPORT_D3D11 1 #define SUPPORT_OPENGL 1 -#elif UNITY_OSX || UNITY_LINUX +#elif UNITY_OSX || UNITY_LINUX || UNITY_ANDROID #define SUPPORT_OPENGL 1 #endif diff --git a/Unity/IUnityGraphics.h b/Unity/IUnityGraphics.h index d0347f3..37c12d0 100644 --- a/Unity/IUnityGraphics.h +++ b/Unity/IUnityGraphics.h @@ -15,6 +15,7 @@ typedef enum UnityGfxRenderer kUnityGfxRendererPS4 = 13, // PlayStation 4 kUnityGfxRendererXboxOne = 14, // Xbox One kUnityGfxRendererMetal = 16, // iOS Metal + kUnityGfxRendererOpenGLCore = 17, // Desktop OpenGL core kUnityGfxRendererD3D12 = 18, // Direct3D 12 } UnityGfxRenderer; diff --git a/UnityRendererType.h b/UnityRendererType.h index ca2b57a..ea2e09b 100644 --- a/UnityRendererType.h +++ b/UnityRendererType.h @@ -63,6 +63,9 @@ class UnityRendererType { switch (gfxRenderer) { #if SUPPORT_OPENGL case kUnityGfxRendererOpenGL: + case kUnityGfxRendererOpenGLES20: + case kUnityGfxRendererOpenGLES30: + case kUnityGfxRendererOpenGLCore: renderer_ = OSVRSupportedRenderers::OpenGL; supported_ = true; break; @@ -77,8 +80,6 @@ class UnityRendererType { case kUnityGfxRendererGCM: case kUnityGfxRendererNull: case kUnityGfxRendererXenon: - case kUnityGfxRendererOpenGLES20: - case kUnityGfxRendererOpenGLES30: case kUnityGfxRendererGXM: case kUnityGfxRendererPS4: case kUnityGfxRendererXboxOne: From 4214e2f0909483b6ceb8cfb85f8f2b47be37dccb Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Tue, 20 Jun 2017 21:24:57 -0400 Subject: [PATCH 16/43] Cmakelists update --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 10ae7e4..830056e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,14 +41,14 @@ endif() add_library(osvrUnityRenderingPlugin MODULE ${osvrUnityRenderingPlugin_SOURCES}) #set_target_properties(osvrUnityRenderingPlugin PROPERTIES LINK_FLAGS "/DEF:${CMAKE_CURRENT_SOURCE_DIR}/OsvrRenderingPlugin.def") -target_link_libraries(osvrUnityRenderingPlugin osvr::osvrClientKit) -target_link_libraries(osvrUnityRenderingPlugin osvrRenderManager::osvrRenderManager) +#target_link_libraries(osvrUnityRenderingPlugin osvr::osvrClientKit) +#target_link_libraries(osvrUnityRenderingPlugin osvrRenderManager::osvrRenderManager) target_include_directories(osvrUnityRenderingPlugin PRIVATE ${Boost_INCLUDE_DIRS}) # target_link_libraries(osvrUnityRenderingPlugin ${Boost_LIBRARIES}) if (OPENGL_FOUND AND GLEW_FOUND) target_include_directories(osvrUnityRenderingPlugin PRIVATE ${OPENGL_INCLUDE_DIRS}) - target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} GLEW::GLEW JsonCpp::JsonCpp SDL2::SDL2) + target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} GLEW::GLEW JsonCpp::JsonCpp SDL2::SDL2 osvr::osvrClientKit osvrRenderManager::osvrRenderManager) # Handle static glew. if(GLEW_LIBRARY MATCHES ".*s.lib") target_compile_definitions(osvrUnityRenderingPlugin PRIVATE GLEW_STATIC) @@ -56,7 +56,7 @@ if (OPENGL_FOUND AND GLEW_FOUND) endif() if (OPENGL_FOUND) target_include_directories(osvrUnityRenderingPlugin PRIVATE ${OPENGL_INCLUDE_DIRS}) - target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} JsonCpp::JsonCpp ) + target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} JsonCpp::JsonCpp osvr::osvrClientKit osvrRenderManager::osvrRenderManager) endif() if(OPENGLES2_FOUND) target_include_directories(osvrUnityRenderingPlugin PRIVATE ${OPENGLES2_INCLUDE_DIR}) From e1ed6b8ded02ea24206130897d8d37e3d0e7e918 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Tue, 20 Jun 2017 21:25:14 -0400 Subject: [PATCH 17/43] fixed typo --- PluginConfig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PluginConfig.h b/PluginConfig.h index ef3599f..172806c 100644 --- a/PluginConfig.h +++ b/PluginConfig.h @@ -28,7 +28,7 @@ // Which platform we are on? #ifdef _WIN32 #define UNITY_WIN 1 -#elif define(__ANDROID__) +#elif defined(__ANDROID__) #define UNITY_ANDROID 1 #elif defined(__APPLE__) #define UNITY_OSX 1 From 260a9d4800c36270d295c44ae1278192dd3493c0 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Tue, 20 Jun 2017 21:39:38 -0400 Subject: [PATCH 18/43] moved struct definition --- OsvrRenderingPlugin.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 9d98a06..7299f9d 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -118,6 +118,13 @@ static bool gGraphicsInitializedOnce = false; // if setupGraphics has been calle static bool gOSVRInitialized = false; static bool gRenderManagerInitialized = false; +typedef struct OSVR_RenderTargetInfo { + GLuint colorBufferName; + GLuint depthBufferName; + GLuint frameBufferName; + GLuint renderBufferName; // @todo - do we need this? +} OSVR_RenderTargetInfo; + static OSVR_ClientInterface gCamera = NULL; static OSVR_ClientInterface gHead = NULL; static int gReportNumber = 0; @@ -133,12 +140,7 @@ static std::vector buffers; static std::vector gRenderTargets; static bool contextSet = false; -typedef struct OSVR_RenderTargetInfo { - GLuint colorBufferName; - GLuint depthBufferName; - GLuint frameBufferName; - GLuint renderBufferName; // @todo - do we need this? -} OSVR_RenderTargetInfo; + static const char gVertexShader[] = "uniform mat4 model;\n" From 345b832ba254d3a62230f369661ff7a362e73cf6 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Tue, 20 Jun 2017 21:50:28 -0400 Subject: [PATCH 19/43] disabled DebugLog on android --- OsvrRenderingPlugin.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 7299f9d..bf5991e 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -223,6 +223,9 @@ void UNITY_INTERFACE_API LinkDebug(DebugFnPtr d) { s_debugLog = d; } // Only for debugging purposes, as this causes some errors at shutdown inline void DebugLog(const char *str) { +#if UNITY_ANDROID + return; +#else #if !defined(NDEBUG) || defined(ENABLE_LOGGING) if (s_debugLog != nullptr) { s_debugLog(str); @@ -234,6 +237,7 @@ inline void DebugLog(const char *str) { s_debugLogFile << str << std::endl; } #endif // defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) +#endif //not UNITY_ANDROID } #if UNITY_ANDROID From b8e0b11f4a2f1858d3dd7c44396883ea94fcacf1 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Wed, 21 Jun 2017 00:05:16 -0400 Subject: [PATCH 20/43] fixed typo --- OsvrRenderingPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index bf5991e..33d6e1a 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -246,7 +246,7 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) { jniEnvironment = 0; vm->AttachCurrentThread(&jniEnvironment, 0); return JNI_VERSION_1_6; -}cre +} #endif void UNITY_INTERFACE_API ShutdownRenderManager() { DebugLog("[OSVR Rendering Plugin] Shutting down RenderManager."); From 1f8087da24aaacbe23b63f7028f74080082e6b71 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Wed, 21 Jun 2017 00:09:04 -0400 Subject: [PATCH 21/43] Moved ShutdownRenderManager --- OsvrRenderingPlugin.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 33d6e1a..c75138f 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -248,20 +248,6 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) { return JNI_VERSION_1_6; } #endif -void UNITY_INTERFACE_API ShutdownRenderManager() { - DebugLog("[OSVR Rendering Plugin] Shutting down RenderManager."); -#if UNITY_ANDROID - ShutdownRenderManagerAndroid(); - return; -#endif - if (s_render != nullptr) { - osvrDestroyRenderManager(s_render); - s_render = nullptr; - s_rightEyeTexturePtr = nullptr; - s_leftEyeTexturePtr = nullptr; - } - s_clientContext = nullptr; -} // -------------------------------------------------------------------------- // GraphicsDeviceEvents @@ -1429,6 +1415,20 @@ void ShutdownRenderManagerAndroid() #endif /////////end ANDROID////////////////////////////////////// +void UNITY_INTERFACE_API ShutdownRenderManager() { + DebugLog("[OSVR Rendering Plugin] Shutting down RenderManager."); +#if UNITY_ANDROID + ShutdownRenderManagerAndroid(); + return; +#endif + if (s_render != nullptr) { + osvrDestroyRenderManager(s_render); + s_render = nullptr; + s_rightEyeTexturePtr = nullptr; + s_leftEyeTexturePtr = nullptr; + } + s_clientContext = nullptr; +} // Called from Unity to create a RenderManager, passing in a ClientContext OSVR_ReturnCode UNITY_INTERFACE_API From 6bea8e370255d15323191ffcb36161eead0d783a Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Wed, 21 Jun 2017 00:21:33 -0400 Subject: [PATCH 22/43] Added JNI variable declarations --- OsvrRenderingPlugin.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index c75138f..70e717b 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -101,6 +101,9 @@ static std::uint32_t viewportHeight = 0; #if UNITY_ANDROID static JNIEnv* jniEnvironment = 0; +static jclass mainActivityClass; +static jmethodID logMsgId; +static jobject unityActivityClassInstance; static GLuint gProgram; static GLuint gvPositionHandle; From 6029ab9c7451e28649672dd2d7687c52b1713132 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Wed, 21 Jun 2017 00:42:03 -0400 Subject: [PATCH 23/43] a bunch of fixes on android path --- OsvrRenderingPlugin.cpp | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 70e717b..d35a8ca 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -34,6 +34,18 @@ Sensics, Inc. #include #include #include +#if UNITY_ANDROID +#include +#include +#include +#include +#include +#include +#include +//#include //already in OsvrRenderingPlugin.h +#include +#include +#endif #if UNITY_WIN @@ -105,6 +117,8 @@ static jclass mainActivityClass; static jmethodID logMsgId; static jobject unityActivityClassInstance; +static int gWidth = 0; +static int gHeight = 0; static GLuint gProgram; static GLuint gvPositionHandle; static GLuint gvColorHandle; @@ -127,7 +141,7 @@ typedef struct OSVR_RenderTargetInfo { GLuint frameBufferName; GLuint renderBufferName; // @todo - do we need this? } OSVR_RenderTargetInfo; - +static OSVR_ClientContext gClientContext = NULL; static OSVR_ClientInterface gCamera = NULL; static OSVR_ClientInterface gHead = NULL; static int gReportNumber = 0; @@ -183,8 +197,6 @@ static std::vector s_lastRenderInfo; static OSVR_RenderInfoCount numRenderInfo; static OSVR_RenderInfoCollection s_renderInfoCollection; static OSVR_GraphicsLibraryD3D11 s_libraryD3D; -static void *s_leftEyeTexturePtr = nullptr; -static void *s_rightEyeTexturePtr = nullptr; static OSVR_ProjectionMatrix lastGoodProjMatrix; static OSVR_Pose3 lastGoodPose; @@ -197,6 +209,10 @@ static std::streambuf *s_oldCout = nullptr; static std::streambuf *s_oldCerr = nullptr; #endif // defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) #endif //end Windows, Linux, OSX + +static void *s_leftEyeTexturePtr = nullptr; +static void *s_rightEyeTexturePtr = nullptr; + // D3D11 vars #if SUPPORT_D3D11 static D3D11_TEXTURE2D_DESC s_textureDesc; @@ -436,6 +452,7 @@ OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) { // -------------------------------------------------------------------------- // UnitySetInterfaces void UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces *unityInterfaces) { +#if UNITY_WIN #if defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) s_debugLogFile.open("RenderPluginLog.txt"); @@ -448,6 +465,7 @@ void UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces *unityInterfaces) { std::cerr.rdbuf(s_debugLogFile.rdbuf()); } #endif // defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) +#endif //UNITY_WIN s_UnityInterfaces = unityInterfaces; s_Graphics = s_UnityInterfaces->Get(); s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent); @@ -459,7 +477,7 @@ void UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces *unityInterfaces) { void UNITY_INTERFACE_API UnityPluginUnload() { s_Graphics->UnregisterDeviceEventCallback(OnGraphicsDeviceEvent); OnGraphicsDeviceEvent(kUnityGfxDeviceEventShutdown); - +#if UNITY_WIN #if defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) if (s_debugLogFile) { // Restore the buffers @@ -468,8 +486,10 @@ void UNITY_INTERFACE_API UnityPluginUnload() { s_debugLogFile.close(); } #endif // defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) +#endif //UNITY_WIN } +#if UNITY_WIN inline void UpdateRenderInfoCollection() { if ((OSVR_RETURN_SUCCESS != osvrRenderManagerGetRenderInfoCollection( s_render, s_renderParams, &s_renderInfoCollection))) { @@ -493,6 +513,7 @@ inline void UpdateRenderInfoCollection() { s_lastRenderInfo = s_renderInfo; } } +#endif //UNITY_WIN #if 0 extern "C" bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API @@ -1438,7 +1459,7 @@ OSVR_ReturnCode UNITY_INTERFACE_API CreateRenderManagerFromUnity(OSVR_ClientContext context) { #if UNITY_ANDROID return CreateRenderManagerAndroid(context); -#endif +#else if (s_render != nullptr) { if (osvrRenderManagerGetDoingOkay(s_render)) { DebugLog("[OSVR Rendering Plugin] RenderManager already created " @@ -1536,6 +1557,7 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context) { DebugLog("[OSVR Rendering Plugin] CreateRenderManagerFromUnity Success!"); return OSVR_RETURN_SUCCESS; +#endif //non-Android platforms } /// Helper function that handles doing the loop of constructing buffers, and From 622fa6686be331ceecf1301d0e6012da43d81d12 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Wed, 21 Jun 2017 00:50:08 -0400 Subject: [PATCH 24/43] more android fixes --- OsvrRenderingPlugin.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index d35a8ca..1fc3ee4 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -1413,7 +1413,7 @@ static void stop() { } OSVR_ReturnCode CreateRenderManagerAndroid(OSVR_ClientContext context) { - s_clientContext = context; + gClientContext = context; if(setupOSVR()) { if (setupGraphics(gWidth, gHeight)) @@ -1444,7 +1444,7 @@ void UNITY_INTERFACE_API ShutdownRenderManager() { #if UNITY_ANDROID ShutdownRenderManagerAndroid(); return; -#endif +#else if (s_render != nullptr) { osvrDestroyRenderManager(s_render); s_render = nullptr; @@ -1452,6 +1452,7 @@ void UNITY_INTERFACE_API ShutdownRenderManager() { s_leftEyeTexturePtr = nullptr; } s_clientContext = nullptr; +#endif } // Called from Unity to create a RenderManager, passing in a ClientContext @@ -1568,7 +1569,7 @@ inline OSVR_ReturnCode applyRenderBufferConstructor(const int numBuffers, G &&bufferCleanup) { #if UNITY_ANDROID return OSVR_RETURN_SUCCESS; -#endif +#else /// If we bail any time before the end, we'll automatically clean up the /// render buffers with this lambda. /* auto cleanupBuffers = osvr::util::finally([&] { @@ -1621,6 +1622,7 @@ inline OSVR_ReturnCode applyRenderBufferConstructor(const int numBuffers, /// Only if we succeed, do we cancel the cleanup and carry on. // cleanupBuffers.cancel(); return OSVR_RETURN_SUCCESS; +#endif } #if SUPPORT_OPENGL @@ -1759,7 +1761,7 @@ OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { return 10; } else return OSVR_RETURN_SUCCESS; -#endif +#else if (!s_deviceType) { DebugLog("[OSVR Rendering Plugin] Device type not supported."); return OSVR_RETURN_FAILURE; @@ -1786,6 +1788,7 @@ OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { DebugLog("Device type not supported."); return OSVR_RETURN_FAILURE; } +#endif //non-Android platforms } void UNITY_INTERFACE_API SetNearClipDistance(double distance) { @@ -1822,7 +1825,7 @@ GetViewport(std::uint8_t eye) { viewDesc.left = currentRenderInfo.viewport.left; viewDesc.lower = currentRenderInfo.viewport.lower; return viewDesc; -#endif +#else OSVR_ViewportDescription viewportDescription; if (s_lastRenderInfo.size() > 0 && eye <= s_lastRenderInfo.size() - 1) { @@ -1853,6 +1856,7 @@ GetViewport(std::uint8_t eye) { lastGoodViewportDescription = viewportDescription; } return viewportDescription; +#endif //non-Android platforms } @@ -1873,7 +1877,7 @@ GetProjectionMatrix(std::uint8_t eye) { proj.farClip = currentRenderInfo.projection.farClip; return proj; } -#endif +#else OSVR_ProjectionMatrix pm; if (s_lastRenderInfo.size() > 0 && eye <= s_lastRenderInfo.size() - 1) { @@ -1887,6 +1891,7 @@ GetProjectionMatrix(std::uint8_t eye) { pm = lastGoodProjMatrix; } return pm; +#endif //non-Android platforms } OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { @@ -1897,7 +1902,7 @@ OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, renderParams); OSVR_RenderInfoOpenGL currentRenderInfo = renderInfoCollection.getRenderInfo(eye); return currentRenderInfo.pose; -#endif +#else OSVR_Pose3 pose; osvrPose3SetIdentity(&pose); if (s_lastRenderInfo.size() > 0 && eye <= s_lastRenderInfo.size() - 1) @@ -1912,6 +1917,7 @@ OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { pose = lastGoodPose; } return pose; +#endif //non-Android platforms } // -------------------------------------------------------------------------- @@ -1941,7 +1947,7 @@ int UNITY_INTERFACE_API SetColorBufferFromUnity(void *texturePtr, std::uint8_t e gRightEyeTextureID = (GLuint)texturePtr; } return OSVR_RETURN_SUCCESS; -#endif +#else if (eye == 0) { s_leftEyeTexturePtr = texturePtr; } else { @@ -1949,6 +1955,7 @@ int UNITY_INTERFACE_API SetColorBufferFromUnity(void *texturePtr, std::uint8_t e } return OSVR_RETURN_SUCCESS; +#endif } #if SUPPORT_D3D11 // Renders the view from our Unity cameras by copying data at From 12112fcc5c293c7e05ee26483c8c031b94b5d081 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Wed, 21 Jun 2017 00:52:52 -0400 Subject: [PATCH 25/43] Android type fixes --- OsvrRenderingPlugin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 1fc3ee4..cc3228f 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -1819,7 +1819,7 @@ GetViewport(std::uint8_t eye) { checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, renderParams); OSVR_RenderInfoOpenGL currentRenderInfo = renderInfoCollection.getRenderInfo(eye); - osvr::renderkit::OSVR_ViewportDescription viewDesc; + OSVR_ViewportDescription viewDesc; viewDesc.width = currentRenderInfo.viewport.width; viewDesc.height = currentRenderInfo.viewport.height; viewDesc.left = currentRenderInfo.viewport.left; @@ -1868,7 +1868,7 @@ GetProjectionMatrix(std::uint8_t eye) { checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, renderParams); OSVR_RenderInfoOpenGL currentRenderInfo = renderInfoCollection.getRenderInfo(eye); - osvr::renderkit::OSVR_ProjectionMatrix proj; + OSVR_ProjectionMatrix proj; proj.left = currentRenderInfo.projection.left; proj.right = currentRenderInfo.projection.right; proj.top = currentRenderInfo.projection.top; From 95891685329189a2adba9959459936687be6bd46 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Wed, 21 Jun 2017 00:55:04 -0400 Subject: [PATCH 26/43] removed extra bracket --- OsvrRenderingPlugin.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index cc3228f..d36c70e 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -1876,7 +1876,6 @@ GetProjectionMatrix(std::uint8_t eye) { proj.nearClip = currentRenderInfo.projection.nearClip; proj.farClip = currentRenderInfo.projection.farClip; return proj; -} #else OSVR_ProjectionMatrix pm; if (s_lastRenderInfo.size() > 0 && eye <= s_lastRenderInfo.size() - 1) From 62398a39b9210544fdceec5fe901931d9de94243 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Wed, 21 Jun 2017 01:03:48 -0400 Subject: [PATCH 27/43] more platform dependent compilation --- OsvrRenderingPlugin.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index d36c70e..788021f 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -2049,6 +2049,7 @@ inline void DoRender() { if (!s_deviceType) { return; } +#if UNITY_WIN const auto n = static_cast(s_renderInfo.size()); switch (s_deviceType.getDeviceTypeEnum()) { @@ -2087,7 +2088,7 @@ inline void DoRender() { break; } #endif // SUPPORT_D3D11 - +#endif //UNITY_WIN #if SUPPORT_OPENGL case OSVRSupportedRenderers::OpenGL: { #if UNITY_ANDROID From 72314cd9c0c62e101870f3589b1c30c5fbf594d2 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Wed, 21 Jun 2017 01:09:51 -0400 Subject: [PATCH 28/43] more platform dependent compilation changes --- OsvrRenderingPlugin.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 788021f..2ba87aa 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -2049,12 +2049,10 @@ inline void DoRender() { if (!s_deviceType) { return; } -#if UNITY_WIN - const auto n = static_cast(s_renderInfo.size()); - switch (s_deviceType.getDeviceTypeEnum()) { #if SUPPORT_D3D11 case OSVRSupportedRenderers::D3D11: { + const auto n = static_cast(s_renderInfo.size()); // Render into each buffer using the specified information. for (int i = 0; i < n; ++i) { RenderViewD3D11(s_renderInfo[i], @@ -2081,14 +2079,13 @@ inline void DoRender() { if ((OSVR_RETURN_SUCCESS != osvrRenderManagerFinishPresentRenderBuffers( s_render, presentState, s_renderParams, true))) { - DebugLog("[OSVR Rendering Plugin] Could not finish presenting render buffers");; + DebugLog("[OSVR Rendering Plugin] Could not finish presenting render buffers"); ShutdownRenderManager(); } - break; } #endif // SUPPORT_D3D11 -#endif //UNITY_WIN + #if SUPPORT_OPENGL case OSVRSupportedRenderers::OpenGL: { #if UNITY_ANDROID From c86ea982f4c123344f885b812b9fa19e5481c400 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Wed, 21 Jun 2017 01:12:17 -0400 Subject: [PATCH 29/43] platform dependent function call --- OsvrRenderingPlugin.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 2ba87aa..ba0ccc4 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -2135,7 +2135,9 @@ void UNITY_INTERFACE_API OnRenderEvent(int eventID) { case kOsvrEventID_Shutdown: break; case kOsvrEventID_Update: +#if UNITY_WIN UpdateRenderInfoCollection(); +#endif break; case kOsvrEventID_SetRoomRotationUsingHead: SetRoomRotationUsingHead(); From 9f3a572b54ac2ee674eccd78238276885a5a226b Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Thu, 22 Jun 2017 02:28:19 -0400 Subject: [PATCH 30/43] cleanup, comments --- OsvrRenderingPlugin.cpp | 153 ++++++++++++++-------------------------- 1 file changed, 54 insertions(+), 99 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index ba0ccc4..4fa4126 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -34,6 +34,7 @@ Sensics, Inc. #include #include #include + #if UNITY_ANDROID #include #include @@ -44,7 +45,15 @@ Sensics, Inc. #include //#include //already in OsvrRenderingPlugin.h #include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #endif @@ -59,6 +68,7 @@ Sensics, Inc. #include #endif +// D3D- specific includes // Include headers for the graphics APIs we support #if SUPPORT_D3D11 #include @@ -69,7 +79,9 @@ Sensics, Inc. #endif // SUPPORT_D3D11 +// OpenGL/OpenGLES-specific includes #if SUPPORT_OPENGL + #if UNITY_WIN || UNITY_LINUX // Needed for render buffer calls. OSVR will have called glewInit() for us // when we open the display. @@ -79,20 +91,10 @@ Sensics, Inc. // Mac OpenGL include #include #elif UNITY_ANDROID -#include -#include -#include -#include -#include -#include -#include -#include #include #include -#include #endif //end unity_android #include -#include #endif // SUPPORT_OPENGL // VARIABLES @@ -113,7 +115,7 @@ static std::uint32_t viewportHeight = 0; #if UNITY_ANDROID static JNIEnv* jniEnvironment = 0; -static jclass mainActivityClass; +static jclass osvrJniWrapperClass; static jmethodID logMsgId; static jobject unityActivityClassInstance; @@ -186,7 +188,7 @@ static const char gFragmentShader[] = "}\n"; -#else //Windows, Linux, OSX +#else //Windows, Linux, OSX static variables static OSVR_RenderParams s_renderParams; static OSVR_RenderManager s_render = nullptr; static OSVR_RenderManagerD3D11 s_renderD3D = nullptr; @@ -202,7 +204,7 @@ static OSVR_ProjectionMatrix lastGoodProjMatrix; static OSVR_Pose3 lastGoodPose; static OSVR_ViewportDescription lastGoodViewportDescription; - +//logging #if defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) static std::ofstream s_debugLogFile; static std::streambuf *s_oldCout = nullptr; @@ -242,9 +244,11 @@ void UNITY_INTERFACE_API LinkDebug(DebugFnPtr d) { s_debugLog = d; } // Only for debugging purposes, as this causes some errors at shutdown inline void DebugLog(const char *str) { + //@todo complete logMsg implementation in JNI plugin + //for now just return on Android #if UNITY_ANDROID return; -#else +#else //all platforms besides Android #if !defined(NDEBUG) || defined(ENABLE_LOGGING) if (s_debugLog != nullptr) { s_debugLog(str); @@ -256,11 +260,13 @@ inline void DebugLog(const char *str) { s_debugLogFile << str << std::endl; } #endif // defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) -#endif //not UNITY_ANDROID +#endif //all platforms besides Android } +//JNI hook +//@todo look into JNI version. Should this match in JNI plugin? #if UNITY_ANDROID -//this OnLoadd gets called automatically +//this OnLoad gets called automatically jint JNI_OnLoad(JavaVM* vm, void* reserved) { jniEnvironment = 0; vm->AttachCurrentThread(&jniEnvironment, 0); @@ -355,7 +361,7 @@ inline void dispatchEventToRenderer(UnityRendererType renderer, } } -//@TODO InitSDLGL, ShreContext +//@TODO InitSDLGL, ShareContext on OpenGL path @@ -366,49 +372,37 @@ OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) { switch (eventType) { case kUnityGfxDeviceEventInitialize: { #if UNITY_ANDROID - mainActivityClass = jniEnvironment->FindClass("org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class - if (mainActivityClass == nullptr) { + osvrJniWrapperClass = jniEnvironment->FindClass("org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class + if (osvrJniWrapperClass == nullptr) { return; } - else { // if class found, continue + else { // if osvrJniWrapperClass found, continue - jmethodID logmid = jniEnvironment->GetStaticMethodID(mainActivityClass, "logMsg", "(Ljava/lang/String;)V"); // find method - jmethodID setGlContextId = jniEnvironment->GetStaticMethodID(mainActivityClass, "setUnityMainContext", "()J"); // find method + //get the Android logger method ID + jmethodID logmid = jniEnvironment->GetStaticMethodID(osvrJniWrapperClass, "logMsg", "(Ljava/lang/String;)V"); // find method + //get the method ID for setting the GL context + jmethodID setGlContextId = jniEnvironment->GetStaticMethodID(osvrJniWrapperClass, "setUnityMainContext", "()J"); // find method if (setGlContextId == nullptr) - //cerr << "ERROR: method void mymain() not found !" << endl; return; else { - //load libs! - /* jmethodID loadLibsMID = jniEnvironment->GetStaticMethodID(mainActivityClass, "loadLibraries", "()V"); // find method - if(loadLibsMID == nullptr) - //cerr << "ERROR: method void mymain() not found !" << endl; - return; - else { - - jniEnvironment->CallStaticVoidMethod(mainActivityClass, loadLibsMID); - }*/ - - jlong currentEglContextHandle = jniEnvironment->CallStaticLongMethod(mainActivityClass, setGlContextId); // call method - long myLongValue = (long)currentEglContextHandle; + jlong currentEglContextHandle = jniEnvironment->CallStaticLongMethod(osvrJniWrapperClass, setGlContextId); //call mathod + //example code for logging the context ID + /*long myLongValue = (long)currentEglContextHandle; std::string stringy = "[OSVR-Unity-Android] setCurrentContext with handle: " + std::to_string(myLongValue); jstring jstr2 = jniEnvironment->NewStringUTF(stringy.c_str()); - jniEnvironment->CallStaticVoidMethod(mainActivityClass, logmid, jstr2); + jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, logmid, jstr2);*/ contextSet = true; - //cout << endl; } - //create context - jmethodID getWidthMID = jniEnvironment->GetStaticMethodID(mainActivityClass, "getDisplayWidth", "()I"); // find method - jmethodID getHeightMID = jniEnvironment->GetStaticMethodID(mainActivityClass, "getDisplayHeight", "()I"); // find method + //get the display width and height via JNI + jmethodID getWidthMID = jniEnvironment->GetStaticMethodID(osvrJniWrapperClass, "getDisplayWidth", "()I"); // find method + jmethodID getHeightMID = jniEnvironment->GetStaticMethodID(osvrJniWrapperClass, "getDisplayHeight", "()I"); // find method if (getWidthMID == nullptr || getHeightMID == nullptr) - //cerr << "ERROR: method void mymain() not found !" << endl; return; else { - - jint displayWidth = jniEnvironment->CallStaticIntMethod(mainActivityClass, getWidthMID); // call method - jint displayHeight = jniEnvironment->CallStaticIntMethod(mainActivityClass, getHeightMID); // call method + jint displayWidth = jniEnvironment->CallStaticIntMethod(osvrJniWrapperClass, getWidthMID); // call method + jint displayHeight = jniEnvironment->CallStaticIntMethod(osvrJniWrapperClass, getHeightMID); // call method gWidth = (int)displayWidth; gHeight = (int)displayHeight; - //cout << endl; } } #endif @@ -508,45 +502,13 @@ inline void UpdateRenderInfoCollection() { } s_renderInfo.push_back(info); } - if (s_renderInfo.size() > 0) + if (numRenderInfo > 0) { s_lastRenderInfo = s_renderInfo; } } #endif //UNITY_WIN -#if 0 -extern "C" bool UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API -UpdateDistortionMesh(float distanceScale[2], float centerOfProjection[2], - float *polynomial, int desiredTriangles = 12800) { - std::vector dp; - osvr::renderkit::RenderManager::DistortionParameters distortion; - distortion.m_desiredTriangles = desiredTriangles; - std::vector Ds; - Ds.push_back(distanceScale[0]); - Ds.push_back(distanceScale[1]); - distortion.m_distortionD = Ds; - std::vector poly; - int len = sizeof(polynomial) / sizeof(int); - for (size_t i = 0; i < len; i++) { - poly.push_back(polynomial[i]); - } - // assume each color is the same for now - distortion.m_distortionPolynomialRed = poly; - distortion.m_distortionPolynomialGreen = poly; - distortion.m_distortionPolynomialBlue = poly; - for (size_t i = 0; i < s_renderInfo.size(); i++) { - std::vector COP = {static_cast(centerOfProjection[0]), - static_cast(centerOfProjection[1])}; - distortion.m_distortionCOP = COP; - dp.push_back(distortion); - } - return s_render->UpdateDistortionMeshes( - osvr::renderkit::RenderManager::DistortionMeshType::SQUARE, dp); -} - -#endif - // Updates the internal "room to world" transformation (applied to all // tracker data for this client context instance) based on the user's head // orientation, so that the direction the user is facing becomes -Z to your @@ -563,8 +525,7 @@ void SetRoomRotationUsingHead() {/* s_renderD3D-> SetRoomRotationUsingHead(); */ /// @todo does this actually get called from anywhere or is it dead code? void ClearRoomToWorldTransform() { /*s_render->ClearRoomToWorldTransform(); */} - -/////////ANDROID////////////////////////////////////////// +//Android-specific implementation #if UNITY_ANDROID inline osvr::renderkit::OSVR_ProjectionMatrix ConvertProjectionMatrix(::OSVR_ProjectionMatrix matrix) { @@ -1270,16 +1231,16 @@ static bool setupGraphics(int width, int height) { gProgram = createProgram(gVertexShader, gFragmentShader); if (!gProgram) { //LOGE("Could not create program."); - mainActivityClass = jniEnvironment->FindClass("org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class - if (mainActivityClass == nullptr) { + osvrJniWrapperClass = jniEnvironment->FindClass("org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class + if (osvrJniWrapperClass == nullptr) { return false; } else { // if class found, continue - jmethodID logmid = jniEnvironment->GetStaticMethodID(mainActivityClass, "logMsg", "(Ljava/lang/String;)V"); // find method + jmethodID logmid = jniEnvironment->GetStaticMethodID(osvrJniWrapperClass, "logMsg", "(Ljava/lang/String;)V"); // find method std::string stringy = "[OSVR-Unity-Android] Could not create program."; jstring jstr2 = jniEnvironment->NewStringUTF(stringy.c_str()); - jniEnvironment->CallStaticVoidMethod(mainActivityClass, logmid, jstr2); + jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, logmid, jstr2); } return false; } @@ -1437,14 +1398,13 @@ void ShutdownRenderManagerAndroid() contextSet = false; } #endif -/////////end ANDROID////////////////////////////////////// void UNITY_INTERFACE_API ShutdownRenderManager() { DebugLog("[OSVR Rendering Plugin] Shutting down RenderManager."); #if UNITY_ANDROID ShutdownRenderManagerAndroid(); return; -#else +#else //non-Android platforms if (s_render != nullptr) { osvrDestroyRenderManager(s_render); s_render = nullptr; @@ -1546,11 +1506,6 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context) { return OSVR_RETURN_FAILURE; } - /*if (setLibraryFromOpenDisplayReturn) { - // Set our library from the one RenderManager created. - s_libraryD3D = ret.library; - }*/ - // create a new set of RenderParams for passing to GetRenderInfo() osvrRenderManagerGetDefaultRenderParams(&s_renderParams); @@ -1758,7 +1713,7 @@ inline void CleanupBufferD3D11(OSVR_RenderBufferD3D11 &rb) { OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { #if UNITY_ANDROID if (!setupRenderTextures(gRenderManager)) { - return 10; + return OSVR_RETURN_FAILURE; } else return OSVR_RETURN_SUCCESS; #else @@ -1769,7 +1724,7 @@ OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { UpdateRenderInfoCollection(); // construct buffers - const int n = static_cast(s_renderInfo.size()); + const int n = static_cast(numRenderInfo); switch (s_deviceType.getDeviceTypeEnum()) { #if SUPPORT_D3D11 case OSVRSupportedRenderers::D3D11: @@ -1825,9 +1780,9 @@ GetViewport(std::uint8_t eye) { viewDesc.left = currentRenderInfo.viewport.left; viewDesc.lower = currentRenderInfo.viewport.lower; return viewDesc; -#else +#else //non-Android platoforms OSVR_ViewportDescription viewportDescription; - if (s_lastRenderInfo.size() > 0 && eye <= s_lastRenderInfo.size() - 1) + if (numRenderInfo > 0 && eye <= numRenderInfo - 1) { viewportDescription = s_lastRenderInfo[eye].viewport; @@ -1878,7 +1833,7 @@ GetProjectionMatrix(std::uint8_t eye) { return proj; #else OSVR_ProjectionMatrix pm; - if (s_lastRenderInfo.size() > 0 && eye <= s_lastRenderInfo.size() - 1) + if (numRenderInfo > 0 && eye <= numRenderInfo - 1) { pm = s_lastRenderInfo[eye].projection; lastGoodProjMatrix = pm; @@ -1904,7 +1859,7 @@ OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { #else OSVR_Pose3 pose; osvrPose3SetIdentity(&pose); - if (s_lastRenderInfo.size() > 0 && eye <= s_lastRenderInfo.size() - 1) + if (numRenderInfo > 0 && eye <= numRenderInfo - 1) { pose = s_lastRenderInfo[eye].pose; lastGoodPose = pose; @@ -2052,7 +2007,7 @@ inline void DoRender() { switch (s_deviceType.getDeviceTypeEnum()) { #if SUPPORT_D3D11 case OSVRSupportedRenderers::D3D11: { - const auto n = static_cast(s_renderInfo.size()); + const auto n = static_cast(numRenderInfo); // Render into each buffer using the specified information. for (int i = 0; i < n; ++i) { RenderViewD3D11(s_renderInfo[i], From 1acd482aa7bef8c8386e67a817f31a6286de6d4c Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Thu, 22 Jun 2017 02:31:49 -0400 Subject: [PATCH 31/43] clang format --- OsvrRenderingPlugin.cpp | 2633 ++++++++++++++++++++------------------- 1 file changed, 1331 insertions(+), 1302 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 4fa4126..bb00f4d 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -37,26 +37,25 @@ Sensics, Inc. #if UNITY_ANDROID #include -#include -#include #include -#include #include +#include +#include +#include #include //#include //already in OsvrRenderingPlugin.h -#include +#include +#include #include +#include +#include +#include #include #include -#include #include #include -#include -#include -#include #endif - #if UNITY_WIN #define NO_MINMAX #define WIN32_LEAN_AND_MEAN @@ -64,7 +63,7 @@ Sensics, Inc. #if defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) #include #include -#endif //end define ENABLE_LOGGING +#endif // end define ENABLE_LOGGING #include #endif @@ -93,7 +92,7 @@ Sensics, Inc. #elif UNITY_ANDROID #include #include -#endif //end unity_android +#endif // end unity_android #include #endif // SUPPORT_OPENGL @@ -109,12 +108,12 @@ static double s_farClipDistance = 1000.0; /// @todo is this redundant? (given renderParams) static double s_ipd = 0.063; -//cached viewport values +// cached viewport values static std::uint32_t viewportWidth = 0; static std::uint32_t viewportHeight = 0; #if UNITY_ANDROID -static JNIEnv* jniEnvironment = 0; +static JNIEnv *jniEnvironment = 0; static jclass osvrJniWrapperClass; static jmethodID logMsgId; static jobject unityActivityClassInstance; @@ -133,15 +132,16 @@ static GLuint gFrameBuffer; static GLuint gTextureID; static GLuint gLeftEyeTextureID; static GLuint gRightEyeTextureID; -static bool gGraphicsInitializedOnce = false; // if setupGraphics has been called at least once +static bool gGraphicsInitializedOnce = + false; // if setupGraphics has been called at least once static bool gOSVRInitialized = false; static bool gRenderManagerInitialized = false; typedef struct OSVR_RenderTargetInfo { - GLuint colorBufferName; - GLuint depthBufferName; - GLuint frameBufferName; - GLuint renderBufferName; // @todo - do we need this? + GLuint colorBufferName; + GLuint depthBufferName; + GLuint frameBufferName; + GLuint renderBufferName; // @todo - do we need this? } OSVR_RenderTargetInfo; static OSVR_ClientContext gClientContext = NULL; static OSVR_ClientInterface gCamera = NULL; @@ -151,44 +151,41 @@ static OSVR_ImageBufferElement *gLastFrame = nullptr; static GLuint gLastFrameWidth = 0; static GLuint gLastFrameHeight = 0; static GLubyte *gTextureBuffer = nullptr; -static OSVR_GraphicsLibraryOpenGL gGraphicsLibrary = { 0 }; +static OSVR_GraphicsLibraryOpenGL gGraphicsLibrary = {0}; static OSVR_RenderManager gRenderManager = nullptr; static OSVR_RenderManagerOpenGL gRenderManagerOGL = nullptr; -static OSVR_RenderParams gRenderParams = { 0 }; +static OSVR_RenderParams gRenderParams = {0}; static std::vector buffers; static std::vector gRenderTargets; static bool contextSet = false; - - static const char gVertexShader[] = -"uniform mat4 model;\n" -"uniform mat4 view;\n" -"uniform mat4 projection;\n" -"attribute vec4 vPosition;\n" -"attribute vec4 vColor;\n" -"attribute vec2 vTexCoordinate;\n" -"varying vec2 texCoordinate;\n" -"varying vec4 fragmentColor;\n" -"void main() {\n" -" gl_Position = projection * view * model * vPosition;\n" -" fragmentColor = vColor;\n" -" texCoordinate = vTexCoordinate;\n" -"}\n"; + "uniform mat4 model;\n" + "uniform mat4 view;\n" + "uniform mat4 projection;\n" + "attribute vec4 vPosition;\n" + "attribute vec4 vColor;\n" + "attribute vec2 vTexCoordinate;\n" + "varying vec2 texCoordinate;\n" + "varying vec4 fragmentColor;\n" + "void main() {\n" + " gl_Position = projection * view * model * vPosition;\n" + " fragmentColor = vColor;\n" + " texCoordinate = vTexCoordinate;\n" + "}\n"; static const char gFragmentShader[] = -"precision mediump float;\n" -"uniform sampler2D uTexture;\n" -"varying vec2 texCoordinate;\n" -"varying vec4 fragmentColor;\n" -"void main()\n" -"{\n" -" gl_FragColor = fragmentColor * texture2D(uTexture, texCoordinate);\n" -//" gl_FragColor = texture2D(uTexture, texCoordinate);\n" -"}\n"; - - -#else //Windows, Linux, OSX static variables + "precision mediump float;\n" + "uniform sampler2D uTexture;\n" + "varying vec2 texCoordinate;\n" + "varying vec4 fragmentColor;\n" + "void main()\n" + "{\n" + " gl_FragColor = fragmentColor * texture2D(uTexture, texCoordinate);\n" + //" gl_FragColor = texture2D(uTexture, texCoordinate);\n" + "}\n"; + +#else // Windows, Linux, OSX static variables static OSVR_RenderParams s_renderParams; static OSVR_RenderManager s_render = nullptr; static OSVR_RenderManagerD3D11 s_renderD3D = nullptr; @@ -204,13 +201,13 @@ static OSVR_ProjectionMatrix lastGoodProjMatrix; static OSVR_Pose3 lastGoodPose; static OSVR_ViewportDescription lastGoodViewportDescription; -//logging +// logging #if defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) static std::ofstream s_debugLogFile; static std::streambuf *s_oldCout = nullptr; static std::streambuf *s_oldCerr = nullptr; #endif // defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) -#endif //end Windows, Linux, OSX +#endif // end Windows, Linux, OSX static void *s_leftEyeTexturePtr = nullptr; static void *s_rightEyeTexturePtr = nullptr; @@ -244,11 +241,11 @@ void UNITY_INTERFACE_API LinkDebug(DebugFnPtr d) { s_debugLog = d; } // Only for debugging purposes, as this causes some errors at shutdown inline void DebugLog(const char *str) { - //@todo complete logMsg implementation in JNI plugin - //for now just return on Android +//@todo complete logMsg implementation in JNI plugin +// for now just return on Android #if UNITY_ANDROID - return; -#else //all platforms besides Android + return; +#else // all platforms besides Android #if !defined(NDEBUG) || defined(ENABLE_LOGGING) if (s_debugLog != nullptr) { s_debugLog(str); @@ -260,17 +257,17 @@ inline void DebugLog(const char *str) { s_debugLogFile << str << std::endl; } #endif // defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) -#endif //all platforms besides Android +#endif // all platforms besides Android } -//JNI hook +// JNI hook //@todo look into JNI version. Should this match in JNI plugin? #if UNITY_ANDROID -//this OnLoad gets called automatically -jint JNI_OnLoad(JavaVM* vm, void* reserved) { - jniEnvironment = 0; - vm->AttachCurrentThread(&jniEnvironment, 0); - return JNI_VERSION_1_6; +// this OnLoad gets called automatically +jint JNI_OnLoad(JavaVM *vm, void *reserved) { + jniEnvironment = 0; + vm->AttachCurrentThread(&jniEnvironment, 0); + return JNI_VERSION_1_6; } #endif @@ -363,8 +360,6 @@ inline void dispatchEventToRenderer(UnityRendererType renderer, //@TODO InitSDLGL, ShareContext on OpenGL path - - /// Needs the calling convention, even though it's static and not exported, /// because it's registered as a callback on plugin load. static void UNITY_INTERFACE_API @@ -372,41 +367,53 @@ OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) { switch (eventType) { case kUnityGfxDeviceEventInitialize: { #if UNITY_ANDROID - osvrJniWrapperClass = jniEnvironment->FindClass("org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class - if (osvrJniWrapperClass == nullptr) { - return; - } - else { // if osvrJniWrapperClass found, continue - - //get the Android logger method ID - jmethodID logmid = jniEnvironment->GetStaticMethodID(osvrJniWrapperClass, "logMsg", "(Ljava/lang/String;)V"); // find method - //get the method ID for setting the GL context - jmethodID setGlContextId = jniEnvironment->GetStaticMethodID(osvrJniWrapperClass, "setUnityMainContext", "()J"); // find method - if (setGlContextId == nullptr) - return; - else { - jlong currentEglContextHandle = jniEnvironment->CallStaticLongMethod(osvrJniWrapperClass, setGlContextId); //call mathod - //example code for logging the context ID - /*long myLongValue = (long)currentEglContextHandle; - std::string stringy = "[OSVR-Unity-Android] setCurrentContext with handle: " + std::to_string(myLongValue); - jstring jstr2 = jniEnvironment->NewStringUTF(stringy.c_str()); - jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, logmid, jstr2);*/ - contextSet = true; - } - //get the display width and height via JNI - jmethodID getWidthMID = jniEnvironment->GetStaticMethodID(osvrJniWrapperClass, "getDisplayWidth", "()I"); // find method - jmethodID getHeightMID = jniEnvironment->GetStaticMethodID(osvrJniWrapperClass, "getDisplayHeight", "()I"); // find method - if (getWidthMID == nullptr || getHeightMID == nullptr) - return; - else { - jint displayWidth = jniEnvironment->CallStaticIntMethod(osvrJniWrapperClass, getWidthMID); // call method - jint displayHeight = jniEnvironment->CallStaticIntMethod(osvrJniWrapperClass, getHeightMID); // call method - gWidth = (int)displayWidth; - gHeight = (int)displayHeight; - } - } + osvrJniWrapperClass = jniEnvironment->FindClass( + "org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class + if (osvrJniWrapperClass == nullptr) { + return; + } else { // if osvrJniWrapperClass found, continue + + // get the Android logger method ID + jmethodID logmid = jniEnvironment->GetStaticMethodID( + osvrJniWrapperClass, "logMsg", + "(Ljava/lang/String;)V"); // find method + // get the method ID for setting the GL context + jmethodID setGlContextId = jniEnvironment->GetStaticMethodID( + osvrJniWrapperClass, "setUnityMainContext", + "()J"); // find method + if (setGlContextId == nullptr) + return; + else { + jlong currentEglContextHandle = + jniEnvironment->CallStaticLongMethod( + osvrJniWrapperClass, setGlContextId); // call mathod + // example code for logging the context ID + /*long myLongValue = (long)currentEglContextHandle; + std::string stringy = "[OSVR-Unity-Android] setCurrentContext + with handle: " + std::to_string(myLongValue); + jstring jstr2 = jniEnvironment->NewStringUTF(stringy.c_str()); + jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, + logmid, jstr2);*/ + contextSet = true; + } + // get the display width and height via JNI + jmethodID getWidthMID = jniEnvironment->GetStaticMethodID( + osvrJniWrapperClass, "getDisplayWidth", "()I"); // find method + jmethodID getHeightMID = jniEnvironment->GetStaticMethodID( + osvrJniWrapperClass, "getDisplayHeight", "()I"); // find method + if (getWidthMID == nullptr || getHeightMID == nullptr) + return; + else { + jint displayWidth = jniEnvironment->CallStaticIntMethod( + osvrJniWrapperClass, getWidthMID); // call method + jint displayHeight = jniEnvironment->CallStaticIntMethod( + osvrJniWrapperClass, getHeightMID); // call method + gWidth = (int)displayWidth; + gHeight = (int)displayHeight; + } + } #endif - //@todo windows, osx context sharing + //@todo windows, osx context sharing DebugLog( "[OSVR Rendering Plugin] OnGraphicsDeviceEvent(Initialize).\n"); s_deviceType = s_Graphics->GetRenderer(); @@ -459,7 +466,7 @@ void UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces *unityInterfaces) { std::cerr.rdbuf(s_debugLogFile.rdbuf()); } #endif // defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) -#endif //UNITY_WIN +#endif // UNITY_WIN s_UnityInterfaces = unityInterfaces; s_Graphics = s_UnityInterfaces->Get(); s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent); @@ -480,34 +487,37 @@ void UNITY_INTERFACE_API UnityPluginUnload() { s_debugLogFile.close(); } #endif // defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) -#endif //UNITY_WIN +#endif // UNITY_WIN } #if UNITY_WIN inline void UpdateRenderInfoCollection() { - if ((OSVR_RETURN_SUCCESS != osvrRenderManagerGetRenderInfoCollection( - s_render, s_renderParams, &s_renderInfoCollection))) { - DebugLog("[OSVR Rendering Plugin] UpdateRenderInfo Could not get renderinfo collection."); - ShutdownRenderManager(); - } - osvrRenderManagerGetNumRenderInfoInCollection(s_renderInfoCollection, &numRenderInfo); - - //update renderinfo - s_renderInfo.clear(); - for (OSVR_RenderInfoCount i = 0; i < numRenderInfo; i++) { - OSVR_RenderInfoD3D11 info; - if ((OSVR_RETURN_SUCCESS != osvrRenderManagerGetRenderInfoFromCollectionD3D11( - s_renderInfoCollection, i, &info))) { - DebugLog("[OSVR Rendering Plugin] Could not get render info."); - } - s_renderInfo.push_back(info); - } - if (numRenderInfo > 0) - { - s_lastRenderInfo = s_renderInfo; - } + if ((OSVR_RETURN_SUCCESS != + osvrRenderManagerGetRenderInfoCollection(s_render, s_renderParams, + &s_renderInfoCollection))) { + DebugLog("[OSVR Rendering Plugin] UpdateRenderInfo Could not get " + "renderinfo collection."); + ShutdownRenderManager(); + } + osvrRenderManagerGetNumRenderInfoInCollection(s_renderInfoCollection, + &numRenderInfo); + + // update renderinfo + s_renderInfo.clear(); + for (OSVR_RenderInfoCount i = 0; i < numRenderInfo; i++) { + OSVR_RenderInfoD3D11 info; + if ((OSVR_RETURN_SUCCESS != + osvrRenderManagerGetRenderInfoFromCollectionD3D11( + s_renderInfoCollection, i, &info))) { + DebugLog("[OSVR Rendering Plugin] Could not get render info."); + } + s_renderInfo.push_back(info); + } + if (numRenderInfo > 0) { + s_lastRenderInfo = s_renderInfo; + } } -#endif //UNITY_WIN +#endif // UNITY_WIN // Updates the internal "room to world" transformation (applied to all // tracker data for this client context instance) based on the user's head @@ -517,901 +527,905 @@ inline void UpdateRenderInfoCollection() { // Note that this method internally calls osvrClientUpdate() to get a head pose // so your callbacks may be called during its execution! /// @todo does this actually get called from anywhere or is it dead code? -void SetRoomRotationUsingHead() {/* s_renderD3D-> SetRoomRotationUsingHead(); */} +void SetRoomRotationUsingHead() { /* s_renderD3D-> SetRoomRotationUsingHead(); + */ +} // Clears/resets the internal "room to world" transformation back to an // identity transformation - that is, clears the effect of any other // manipulation of the room to world transform. /// @todo does this actually get called from anywhere or is it dead code? -void ClearRoomToWorldTransform() { /*s_render->ClearRoomToWorldTransform(); */} +void ClearRoomToWorldTransform() { /*s_render->ClearRoomToWorldTransform(); */ +} -//Android-specific implementation +// Android-specific implementation #if UNITY_ANDROID -inline osvr::renderkit::OSVR_ProjectionMatrix ConvertProjectionMatrix(::OSVR_ProjectionMatrix matrix) -{ - osvr::renderkit::OSVR_ProjectionMatrix ret = { 0 }; - ret.bottom = matrix.bottom; - ret.top = matrix.top; - ret.left = matrix.left; - ret.right = matrix.right; - ret.nearClip = matrix.nearClip; - ret.farClip = matrix.farClip; - return ret; +inline osvr::renderkit::OSVR_ProjectionMatrix +ConvertProjectionMatrix(::OSVR_ProjectionMatrix matrix) { + osvr::renderkit::OSVR_ProjectionMatrix ret = {0}; + ret.bottom = matrix.bottom; + ret.top = matrix.top; + ret.left = matrix.left; + ret.right = matrix.right; + ret.nearClip = matrix.nearClip; + ret.farClip = matrix.farClip; + return ret; } static void checkReturnCode(OSVR_ReturnCode returnCode, const char *msg) { - if (returnCode != OSVR_RETURN_SUCCESS) { - //LOGI("[OSVR] OSVR method returned a failure: %s", msg); - throw std::runtime_error(msg); - } + if (returnCode != OSVR_RETURN_SUCCESS) { + // LOGI("[OSVR] OSVR method returned a failure: %s", msg); + throw std::runtime_error(msg); + } } // RAII wrapper around the RenderManager collection APIs for OpenGL class RenderInfoCollectionOpenGL { -private: - OSVR_RenderManager mRenderManager = nullptr; - OSVR_RenderInfoCollection mRenderInfoCollection = nullptr; - OSVR_RenderParams mRenderParams = { 0 }; - -public: - RenderInfoCollectionOpenGL(OSVR_RenderManager renderManager, OSVR_RenderParams renderParams) - : mRenderManager(renderManager), mRenderParams(renderParams) { - OSVR_ReturnCode rc; - rc = osvrRenderManagerGetRenderInfoCollection(mRenderManager, mRenderParams, &mRenderInfoCollection); - checkReturnCode(rc, "osvrRenderManagerGetRenderInfoCollection call failed."); - } - - OSVR_RenderInfoCount getNumRenderInfo() { - OSVR_RenderInfoCount ret; - OSVR_ReturnCode rc; - rc = osvrRenderManagerGetNumRenderInfoInCollection(mRenderInfoCollection, &ret); - checkReturnCode(rc, "osvrRenderManagerGetNumRenderInfoInCollection call failed."); - return ret; - } - - OSVR_RenderInfoOpenGL getRenderInfo(OSVR_RenderInfoCount index) { - if (index < 0 || index >= getNumRenderInfo()) { - const static char* err = "getRenderInfo called with invalid index"; - //LOGE(err); - throw std::runtime_error(err); - } - OSVR_RenderInfoOpenGL ret; - OSVR_ReturnCode rc; - rc = osvrRenderManagerGetRenderInfoFromCollectionOpenGL(mRenderInfoCollection, index, &ret); - checkReturnCode(rc, "osvrRenderManagerGetRenderInfoFromCollectionOpenGL call failed."); - return ret; - } - - ~RenderInfoCollectionOpenGL() { - if (mRenderInfoCollection) { - osvrRenderManagerReleaseRenderInfoCollection(mRenderInfoCollection); - } - } + private: + OSVR_RenderManager mRenderManager = nullptr; + OSVR_RenderInfoCollection mRenderInfoCollection = nullptr; + OSVR_RenderParams mRenderParams = {0}; + + public: + RenderInfoCollectionOpenGL(OSVR_RenderManager renderManager, + OSVR_RenderParams renderParams) + : mRenderManager(renderManager), mRenderParams(renderParams) { + OSVR_ReturnCode rc; + rc = osvrRenderManagerGetRenderInfoCollection( + mRenderManager, mRenderParams, &mRenderInfoCollection); + checkReturnCode( + rc, "osvrRenderManagerGetRenderInfoCollection call failed."); + } + + OSVR_RenderInfoCount getNumRenderInfo() { + OSVR_RenderInfoCount ret; + OSVR_ReturnCode rc; + rc = osvrRenderManagerGetNumRenderInfoInCollection( + mRenderInfoCollection, &ret); + checkReturnCode( + rc, "osvrRenderManagerGetNumRenderInfoInCollection call failed."); + return ret; + } + + OSVR_RenderInfoOpenGL getRenderInfo(OSVR_RenderInfoCount index) { + if (index < 0 || index >= getNumRenderInfo()) { + const static char *err = "getRenderInfo called with invalid index"; + // LOGE(err); + throw std::runtime_error(err); + } + OSVR_RenderInfoOpenGL ret; + OSVR_ReturnCode rc; + rc = osvrRenderManagerGetRenderInfoFromCollectionOpenGL( + mRenderInfoCollection, index, &ret); + checkReturnCode( + rc, + "osvrRenderManagerGetRenderInfoFromCollectionOpenGL call failed."); + return ret; + } + + ~RenderInfoCollectionOpenGL() { + if (mRenderInfoCollection) { + osvrRenderManagerReleaseRenderInfoCollection(mRenderInfoCollection); + } + } }; static void checkGlError(const char *op) { - std::stringstream ss; - for (GLint error = glGetError(); error; error = glGetError()) { - // gluErrorString without glu - std::string errorString; - switch (error) { - case GL_NO_ERROR: - errorString = "GL_NO_ERROR"; - break; - case GL_INVALID_ENUM: - errorString = "GL_INVALID_ENUM"; - break; - case GL_INVALID_VALUE: - errorString = "GL_INVALID_VALUE"; - break; - case GL_INVALID_OPERATION: - errorString = "GL_INVALID_OPERATION"; - break; - case GL_INVALID_FRAMEBUFFER_OPERATION: - errorString = "GL_INVALID_FRAMEBUFFER_OPERATION"; - break; - case GL_OUT_OF_MEMORY: - errorString = "GL_OUT_OF_MEMORY"; - break; - default: - errorString = "(unknown error)"; - break; - } - //LOGI("after %s() glError (%s)\n", op, errorString.c_str()); - } + std::stringstream ss; + for (GLint error = glGetError(); error; error = glGetError()) { + // gluErrorString without glu + std::string errorString; + switch (error) { + case GL_NO_ERROR: + errorString = "GL_NO_ERROR"; + break; + case GL_INVALID_ENUM: + errorString = "GL_INVALID_ENUM"; + break; + case GL_INVALID_VALUE: + errorString = "GL_INVALID_VALUE"; + break; + case GL_INVALID_OPERATION: + errorString = "GL_INVALID_OPERATION"; + break; + case GL_INVALID_FRAMEBUFFER_OPERATION: + errorString = "GL_INVALID_FRAMEBUFFER_OPERATION"; + break; + case GL_OUT_OF_MEMORY: + errorString = "GL_OUT_OF_MEMORY"; + break; + default: + errorString = "(unknown error)"; + break; + } + // LOGI("after %s() glError (%s)\n", op, errorString.c_str()); + } } class PassThroughOpenGLContextImpl { - OSVR_OpenGLToolkitFunctions toolkit; - int mWidth; - int mHeight; - - static void createImpl(void* data) { - } - static void destroyImpl(void* data) { - delete ((PassThroughOpenGLContextImpl*)data); - } - static OSVR_CBool addOpenGLContextImpl(void* data, const OSVR_OpenGLContextParams* p) { - return ((PassThroughOpenGLContextImpl*)data)->addOpenGLContext(p); - } - static OSVR_CBool removeOpenGLContextsImpl(void* data) { - return ((PassThroughOpenGLContextImpl*)data)->removeOpenGLContexts(); - } - static OSVR_CBool makeCurrentImpl(void* data, size_t display) { - return ((PassThroughOpenGLContextImpl*)data)->makeCurrent(display); - } - static OSVR_CBool swapBuffersImpl(void* data, size_t display) { - return ((PassThroughOpenGLContextImpl*)data)->swapBuffers(display); - } - static OSVR_CBool setVerticalSyncImpl(void* data, OSVR_CBool verticalSync) { - return ((PassThroughOpenGLContextImpl*)data)->setVerticalSync(verticalSync); - } - static OSVR_CBool handleEventsImpl(void* data) { - return ((PassThroughOpenGLContextImpl*)data)->handleEvents(); - } - static OSVR_CBool getDisplayFrameBufferImpl(void* data, size_t display, GLuint* displayFrameBufferOut) { - return ((PassThroughOpenGLContextImpl*)data)->getDisplayFrameBuffer(display, displayFrameBufferOut); - } - static OSVR_CBool getDisplaySizeOverrideImpl(void* data, size_t display, int* width, int* height) { - return ((PassThroughOpenGLContextImpl*)data)->getDisplaySizeOverride(display, width, height); - } - - -public: - PassThroughOpenGLContextImpl() { - memset(&toolkit, 0, sizeof(toolkit)); - toolkit.size = sizeof(toolkit); - toolkit.data = this; - - toolkit.create = createImpl; - toolkit.destroy = destroyImpl; - toolkit.addOpenGLContext = addOpenGLContextImpl; - toolkit.removeOpenGLContexts = removeOpenGLContextsImpl; - toolkit.makeCurrent = makeCurrentImpl; - toolkit.swapBuffers = swapBuffersImpl; - toolkit.setVerticalSync = setVerticalSyncImpl; - toolkit.handleEvents = handleEventsImpl; - toolkit.getDisplaySizeOverride = getDisplaySizeOverrideImpl; - toolkit.getDisplayFrameBuffer = getDisplayFrameBufferImpl; - } - - ~PassThroughOpenGLContextImpl() { - } - - const OSVR_OpenGLToolkitFunctions* getToolkit() const { return &toolkit; } - - bool addOpenGLContext(const OSVR_OpenGLContextParams* p) { - return true; - } - - bool removeOpenGLContexts() { - return true; - } - - bool makeCurrent(size_t display) { - return true; - } - - bool swapBuffers(size_t display) { - return true; - } - - bool setVerticalSync(bool verticalSync) { - return true; - } - - bool handleEvents() { - return true; - } - bool getDisplayFrameBuffer(size_t display, GLuint* displayFrameBufferOut) { - *displayFrameBufferOut = gFrameBuffer; - return true; - } - - bool getDisplaySizeOverride(size_t display, int* width, int* height) { - *width = gWidth; - *height = gHeight; - return false; - } + OSVR_OpenGLToolkitFunctions toolkit; + int mWidth; + int mHeight; + + static void createImpl(void *data) {} + static void destroyImpl(void *data) { + delete ((PassThroughOpenGLContextImpl *)data); + } + static OSVR_CBool addOpenGLContextImpl(void *data, + const OSVR_OpenGLContextParams *p) { + return ((PassThroughOpenGLContextImpl *)data)->addOpenGLContext(p); + } + static OSVR_CBool removeOpenGLContextsImpl(void *data) { + return ((PassThroughOpenGLContextImpl *)data)->removeOpenGLContexts(); + } + static OSVR_CBool makeCurrentImpl(void *data, size_t display) { + return ((PassThroughOpenGLContextImpl *)data)->makeCurrent(display); + } + static OSVR_CBool swapBuffersImpl(void *data, size_t display) { + return ((PassThroughOpenGLContextImpl *)data)->swapBuffers(display); + } + static OSVR_CBool setVerticalSyncImpl(void *data, OSVR_CBool verticalSync) { + return ((PassThroughOpenGLContextImpl *)data) + ->setVerticalSync(verticalSync); + } + static OSVR_CBool handleEventsImpl(void *data) { + return ((PassThroughOpenGLContextImpl *)data)->handleEvents(); + } + static OSVR_CBool getDisplayFrameBufferImpl(void *data, size_t display, + GLuint *displayFrameBufferOut) { + return ((PassThroughOpenGLContextImpl *)data) + ->getDisplayFrameBuffer(display, displayFrameBufferOut); + } + static OSVR_CBool getDisplaySizeOverrideImpl(void *data, size_t display, + int *width, int *height) { + return ((PassThroughOpenGLContextImpl *)data) + ->getDisplaySizeOverride(display, width, height); + } + + public: + PassThroughOpenGLContextImpl() { + memset(&toolkit, 0, sizeof(toolkit)); + toolkit.size = sizeof(toolkit); + toolkit.data = this; + + toolkit.create = createImpl; + toolkit.destroy = destroyImpl; + toolkit.addOpenGLContext = addOpenGLContextImpl; + toolkit.removeOpenGLContexts = removeOpenGLContextsImpl; + toolkit.makeCurrent = makeCurrentImpl; + toolkit.swapBuffers = swapBuffersImpl; + toolkit.setVerticalSync = setVerticalSyncImpl; + toolkit.handleEvents = handleEventsImpl; + toolkit.getDisplaySizeOverride = getDisplaySizeOverrideImpl; + toolkit.getDisplayFrameBuffer = getDisplayFrameBufferImpl; + } + + ~PassThroughOpenGLContextImpl() {} + + const OSVR_OpenGLToolkitFunctions *getToolkit() const { return &toolkit; } + + bool addOpenGLContext(const OSVR_OpenGLContextParams *p) { return true; } + + bool removeOpenGLContexts() { return true; } + + bool makeCurrent(size_t display) { return true; } + + bool swapBuffers(size_t display) { return true; } + + bool setVerticalSync(bool verticalSync) { return true; } + + bool handleEvents() { return true; } + bool getDisplayFrameBuffer(size_t display, GLuint *displayFrameBufferOut) { + *displayFrameBufferOut = gFrameBuffer; + return true; + } + + bool getDisplaySizeOverride(size_t display, int *width, int *height) { + *width = gWidth; + *height = gHeight; + return false; + } }; static GLuint loadShader(GLenum shaderType, const char *pSource) { - GLuint shader = glCreateShader(shaderType); - if (shader) { - glShaderSource(shader, 1, &pSource, NULL); - glCompileShader(shader); - GLint compiled = 0; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); - if (!compiled) { - GLint infoLen = 0; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); - if (infoLen) { - char *buf = (char *)malloc(infoLen); - if (buf) { - glGetShaderInfoLog(shader, infoLen, NULL, buf); - //LOGE("Could not compile shader %d:\n%s\n", - // shaderType, buf); - free(buf); - } - glDeleteShader(shader); - shader = 0; - } - } - } - return shader; + GLuint shader = glCreateShader(shaderType); + if (shader) { + glShaderSource(shader, 1, &pSource, NULL); + glCompileShader(shader); + GLint compiled = 0; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (!compiled) { + GLint infoLen = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen) { + char *buf = (char *)malloc(infoLen); + if (buf) { + glGetShaderInfoLog(shader, infoLen, NULL, buf); + // LOGE("Could not compile shader %d:\n%s\n", + // shaderType, buf); + free(buf); + } + glDeleteShader(shader); + shader = 0; + } + } + } + return shader; } -static GLuint createProgram(const char *pVertexSource, const char *pFragmentSource) { - GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); - if (!vertexShader) { - return 0; - } - - GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); - if (!pixelShader) { - return 0; - } - - GLuint program = glCreateProgram(); - if (program) { - glAttachShader(program, vertexShader); - checkGlError("glAttachShader"); - - glAttachShader(program, pixelShader); - checkGlError("glAttachShader"); - - glBindAttribLocation(program, 0, "vPosition"); - glBindAttribLocation(program, 1, "vColor"); - glBindAttribLocation(program, 2, "vTexCoordinate"); - - glLinkProgram(program); - GLint linkStatus = GL_FALSE; - glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); - if (linkStatus != GL_TRUE) { - GLint bufLength = 0; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); - if (bufLength) { - char *buf = (char *)malloc(bufLength); - if (buf) { - glGetProgramInfoLog(program, bufLength, NULL, buf); - // LOGE("Could not link program:\n%s\n", buf); - free(buf); - } - } - glDeleteProgram(program); - program = 0; - } - } - return program; +static GLuint createProgram(const char *pVertexSource, + const char *pFragmentSource) { + GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); + if (!vertexShader) { + return 0; + } + + GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); + if (!pixelShader) { + return 0; + } + + GLuint program = glCreateProgram(); + if (program) { + glAttachShader(program, vertexShader); + checkGlError("glAttachShader"); + + glAttachShader(program, pixelShader); + checkGlError("glAttachShader"); + + glBindAttribLocation(program, 0, "vPosition"); + glBindAttribLocation(program, 1, "vColor"); + glBindAttribLocation(program, 2, "vTexCoordinate"); + + glLinkProgram(program); + GLint linkStatus = GL_FALSE; + glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); + if (linkStatus != GL_TRUE) { + GLint bufLength = 0; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); + if (bufLength) { + char *buf = (char *)malloc(bufLength); + if (buf) { + glGetProgramInfoLog(program, bufLength, NULL, buf); + // LOGE("Could not link program:\n%s\n", buf); + free(buf); + } + } + glDeleteProgram(program); + program = 0; + } + } + return program; } static GLuint createTexture(GLuint width, GLuint height) { - GLuint ret; - glGenTextures(1, &ret); - checkGlError("glGenTextures"); - - glBindTexture(GL_TEXTURE_2D, ret); - checkGlError("glBindTexture"); - - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - // // DEBUG CODE - should be passing null here, but then texture is always black. - GLubyte *dummyBuffer = new GLubyte[width * height * 4]; - for (GLuint i = 0; i < width * height * 4; i++) { - dummyBuffer[i] = (i % 4 ? 100 : 255); - } - - // This dummy texture successfully makes it into the texture and renders, but subsequent - // calls to glTexSubImage2D don't appear to do anything. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, - dummyBuffer); - checkGlError("glTexImage2D"); - delete[] dummyBuffer; - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - checkGlError("glTexParameteri"); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - checkGlError("glTexParameteri"); - return ret; + GLuint ret; + glGenTextures(1, &ret); + checkGlError("glGenTextures"); + + glBindTexture(GL_TEXTURE_2D, ret); + checkGlError("glBindTexture"); + + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + // // DEBUG CODE - should be passing null here, but then texture is + // always black. + GLubyte *dummyBuffer = new GLubyte[width * height * 4]; + for (GLuint i = 0; i < width * height * 4; i++) { + dummyBuffer[i] = (i % 4 ? 100 : 255); + } + + // This dummy texture successfully makes it into the texture and renders, + // but subsequent + // calls to glTexSubImage2D don't appear to do anything. + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, dummyBuffer); + checkGlError("glTexImage2D"); + delete[] dummyBuffer; + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + checkGlError("glTexParameteri"); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + checkGlError("glTexParameteri"); + return ret; } static void updateTexture(GLuint width, GLuint height, GLubyte *data) { - glBindTexture(GL_TEXTURE_2D, gTextureID); - checkGlError("glBindTexture"); + glBindTexture(GL_TEXTURE_2D, gTextureID); + checkGlError("glBindTexture"); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ALIGNMENT, 1); - // @todo use glTexSubImage2D to be faster here, but add check to make sure height/width are the same. - //glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); - //checkGlError("glTexSubImage2D"); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - checkGlError("glTexImage2D"); + // @todo use glTexSubImage2D to be faster here, but add check to make sure + // height/width are the same. + // glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, + // GL_UNSIGNED_BYTE, data); + // checkGlError("glTexSubImage2D"); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, data); + checkGlError("glTexImage2D"); } static void imagingCallback(void *userdata, const OSVR_TimeValue *timestamp, - const OSVR_ImagingReport *report) { + const OSVR_ImagingReport *report) { - OSVR_ClientContext *ctx = (OSVR_ClientContext *)userdata; + OSVR_ClientContext *ctx = (OSVR_ClientContext *)userdata; - gReportNumber++; - GLuint width = report->state.metadata.width; - GLuint height = report->state.metadata.height; - gLastFrameWidth = width; - gLastFrameHeight = height; - GLuint size = width * height * 4; + gReportNumber++; + GLuint width = report->state.metadata.width; + GLuint height = report->state.metadata.height; + gLastFrameWidth = width; + gLastFrameHeight = height; + GLuint size = width * height * 4; - gLastFrame = report->state.data; + gLastFrame = report->state.data; } #if SUPPORT_OPENGL inline GLuint GetEyeTextureOpenGL(int eye) { - return (eye == 0) ? gLeftEyeTextureID : gRightEyeTextureID; + return (eye == 0) ? gLeftEyeTextureID : gRightEyeTextureID; } #endif static bool setupRenderTextures(OSVR_RenderManager renderManager) { - try { - OSVR_ReturnCode rc; - rc = osvrRenderManagerGetDefaultRenderParams(&gRenderParams); - checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); - - gRenderParams.farClipDistanceMeters = 1000000.0f; - gRenderParams.nearClipDistanceMeters = 0.0000001f; - RenderInfoCollectionOpenGL renderInfo(renderManager, gRenderParams); - - OSVR_RenderManagerRegisterBufferState state; - rc = osvrRenderManagerStartRegisterRenderBuffers(&state); - checkReturnCode(rc, "osvrRenderManagerStartRegisterRenderBuffers call failed."); - - for (OSVR_RenderInfoCount i = 0; i < renderInfo.getNumRenderInfo(); i++) { - OSVR_RenderInfoOpenGL currentRenderInfo = renderInfo.getRenderInfo(i); - - // Determine the appropriate size for the frame buffer to be used for - // all eyes when placed horizontally size by side. - int width = static_cast(currentRenderInfo.viewport.width); - int height = static_cast(currentRenderInfo.viewport.height); - - GLuint frameBufferName = 0; - glGenFramebuffers(1, &frameBufferName); - glBindFramebuffer(GL_FRAMEBUFFER, frameBufferName); - - GLuint renderBufferName = 0; - glGenRenderbuffers(1, &renderBufferName); - - GLuint colorBufferName = GetEyeTextureOpenGL(i); - rc = osvrRenderManagerCreateColorBufferOpenGL(width, height, GL_RGBA, - &colorBufferName); - checkReturnCode(rc, "osvrRenderManagerCreateColorBufferOpenGL call failed."); - - // bind it to our framebuffer - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - colorBufferName, 0); - - // The depth buffer - GLuint depthBuffer; - rc = osvrRenderManagerCreateDepthBufferOpenGL(width, height, &depthBuffer); - checkReturnCode(rc, "osvrRenderManagerCreateDepthBufferOpenGL call failed."); - - glGenRenderbuffers(1, &depthBuffer); - glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, - depthBuffer); - - glBindRenderbuffer(GL_RENDERBUFFER, renderBufferName); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBufferName, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderBufferName); - - - // unbind the framebuffer - glBindTexture(GL_TEXTURE_2D, 0); - glBindRenderbuffer(GL_RENDERBUFFER, 0); - glBindFramebuffer(GL_FRAMEBUFFER, gFrameBuffer); - - OSVR_RenderBufferOpenGL buffer = { 0 }; - buffer.colorBufferName = colorBufferName; - buffer.depthStencilBufferName = depthBuffer; - rc = osvrRenderManagerRegisterRenderBufferOpenGL(state, buffer); - checkReturnCode(rc, "osvrRenderManagerRegisterRenderBufferOpenGL call failed."); - - OSVR_RenderTargetInfo renderTarget = { 0 }; - renderTarget.frameBufferName = frameBufferName; - renderTarget.renderBufferName = renderBufferName; - renderTarget.colorBufferName = colorBufferName; - renderTarget.depthBufferName = depthBuffer; - gRenderTargets.push_back(renderTarget); - } - - rc = osvrRenderManagerFinishRegisterRenderBuffers(renderManager, state, true); - checkReturnCode(rc, "osvrRenderManagerFinishRegisterRenderBuffers call failed."); - } - catch (...) { - //LOGE("Error durring render target creation."); - return false; - } - return true; + try { + OSVR_ReturnCode rc; + rc = osvrRenderManagerGetDefaultRenderParams(&gRenderParams); + checkReturnCode(rc, + "osvrRenderManagerGetDefaultRenderParams call failed."); + + gRenderParams.farClipDistanceMeters = 1000000.0f; + gRenderParams.nearClipDistanceMeters = 0.0000001f; + RenderInfoCollectionOpenGL renderInfo(renderManager, gRenderParams); + + OSVR_RenderManagerRegisterBufferState state; + rc = osvrRenderManagerStartRegisterRenderBuffers(&state); + checkReturnCode( + rc, "osvrRenderManagerStartRegisterRenderBuffers call failed."); + + for (OSVR_RenderInfoCount i = 0; i < renderInfo.getNumRenderInfo(); + i++) { + OSVR_RenderInfoOpenGL currentRenderInfo = + renderInfo.getRenderInfo(i); + + // Determine the appropriate size for the frame buffer to be used + // for + // all eyes when placed horizontally size by side. + int width = static_cast(currentRenderInfo.viewport.width); + int height = static_cast(currentRenderInfo.viewport.height); + + GLuint frameBufferName = 0; + glGenFramebuffers(1, &frameBufferName); + glBindFramebuffer(GL_FRAMEBUFFER, frameBufferName); + + GLuint renderBufferName = 0; + glGenRenderbuffers(1, &renderBufferName); + + GLuint colorBufferName = GetEyeTextureOpenGL(i); + rc = osvrRenderManagerCreateColorBufferOpenGL( + width, height, GL_RGBA, &colorBufferName); + checkReturnCode( + rc, "osvrRenderManagerCreateColorBufferOpenGL call failed."); + + // bind it to our framebuffer + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, colorBufferName, 0); + + // The depth buffer + GLuint depthBuffer; + rc = osvrRenderManagerCreateDepthBufferOpenGL(width, height, + &depthBuffer); + checkReturnCode( + rc, "osvrRenderManagerCreateDepthBufferOpenGL call failed."); + + glGenRenderbuffers(1, &depthBuffer); + glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, + height); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, depthBuffer); + + glBindRenderbuffer(GL_RENDERBUFFER, renderBufferName); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, + height); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, colorBufferName, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, renderBufferName); + + // unbind the framebuffer + glBindTexture(GL_TEXTURE_2D, 0); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, gFrameBuffer); + + OSVR_RenderBufferOpenGL buffer = {0}; + buffer.colorBufferName = colorBufferName; + buffer.depthStencilBufferName = depthBuffer; + rc = osvrRenderManagerRegisterRenderBufferOpenGL(state, buffer); + checkReturnCode( + rc, "osvrRenderManagerRegisterRenderBufferOpenGL call failed."); + + OSVR_RenderTargetInfo renderTarget = {0}; + renderTarget.frameBufferName = frameBufferName; + renderTarget.renderBufferName = renderBufferName; + renderTarget.colorBufferName = colorBufferName; + renderTarget.depthBufferName = depthBuffer; + gRenderTargets.push_back(renderTarget); + } + + rc = osvrRenderManagerFinishRegisterRenderBuffers(renderManager, state, + true); + checkReturnCode( + rc, "osvrRenderManagerFinishRegisterRenderBuffers call failed."); + } catch (...) { + // LOGE("Error durring render target creation."); + return false; + } + return true; } static bool setupOSVR() { - if (gOSVRInitialized) { - return true; - } - OSVR_ReturnCode rc = 0; - try { - // On Android, the current working directory is added to the default plugin search path. - // it also helps the server find its configuration and display files. - // boost::filesystem::current_path("/data/data/com.osvr.android.gles2sample/files"); - // auto workingDirectory = boost::filesystem::current_path(); - // //LOGI("[OSVR] Current working directory: %s", workingDirectory.string().c_str()); - - // auto-start the server - osvrClientAttemptServerAutoStart(); - - if (!gClientContext) { - //LOGI("[OSVR] Creating ClientContext..."); - gClientContext = osvrClientInit("com.osvr.android.examples.OSVROpenGL", 0); - if (!gClientContext) { - //LOGI("[OSVR] could not create client context"); - return false; - } - - // temporary workaround to DisplayConfig issue, - // display sometimes fails waiting for the tree from the server. - //LOGI("[OSVR] Calling update a few times..."); - for (int i = 0; i < 10000; i++) { - rc = osvrClientUpdate(gClientContext); - if (rc != OSVR_RETURN_SUCCESS) { - //LOGI("[OSVR] Error while updating client context."); - return false; - } - } - - - rc = osvrClientCheckStatus(gClientContext); - if (rc != OSVR_RETURN_SUCCESS) { - //LOGI("[OSVR] Client context reported bad status."); - return false; - } - else { - //LOGI("[OSVR] Client context reported good status."); - } - - - // if (OSVR_RETURN_SUCCESS != - // osvrClientGetInterface(gClientContext, "/camera", &gCamera)) { - // //LOGI("Error, could not get the camera interface at /camera."); - // return false; - // } - // - // // Register the imaging callback. - // if (OSVR_RETURN_SUCCESS != - // osvrRegisterImagingCallback(gCamera, &imagingCallback, &gClientContext)) { - // //LOGI("Error, could not register image callback."); - // return false; - // } - } - - gOSVRInitialized = true; - return true; - } - catch (const std::runtime_error &ex) { - //LOGI("[OSVR] OSVR initialization failed: %s", ex.what()); - return false; - } + if (gOSVRInitialized) { + return true; + } + OSVR_ReturnCode rc = 0; + try { + // On Android, the current working directory is added to the default + // plugin search path. + // it also helps the server find its configuration and display files. + // boost::filesystem::current_path("/data/data/com.osvr.android.gles2sample/files"); + // auto workingDirectory = boost::filesystem::current_path(); + // //LOGI("[OSVR] Current working directory: %s", + // workingDirectory.string().c_str()); + + // auto-start the server + osvrClientAttemptServerAutoStart(); + + if (!gClientContext) { + // LOGI("[OSVR] Creating ClientContext..."); + gClientContext = + osvrClientInit("com.osvr.android.examples.OSVROpenGL", 0); + if (!gClientContext) { + // LOGI("[OSVR] could not create client context"); + return false; + } + + // temporary workaround to DisplayConfig issue, + // display sometimes fails waiting for the tree from the server. + // LOGI("[OSVR] Calling update a few times..."); + for (int i = 0; i < 10000; i++) { + rc = osvrClientUpdate(gClientContext); + if (rc != OSVR_RETURN_SUCCESS) { + // LOGI("[OSVR] Error while updating client context."); + return false; + } + } + + rc = osvrClientCheckStatus(gClientContext); + if (rc != OSVR_RETURN_SUCCESS) { + // LOGI("[OSVR] Client context reported bad status."); + return false; + } else { + // LOGI("[OSVR] Client context reported good status."); + } + + // if (OSVR_RETURN_SUCCESS != + // osvrClientGetInterface(gClientContext, + // "/camera", &gCamera)) { + // //LOGI("Error, could not get the camera + // interface at /camera."); + // return false; + // } + // + // // Register the imaging callback. + // if (OSVR_RETURN_SUCCESS != + // osvrRegisterImagingCallback(gCamera, + // &imagingCallback, &gClientContext)) { + // //LOGI("Error, could not register image + // callback."); + // return false; + // } + } + + gOSVRInitialized = true; + return true; + } catch (const std::runtime_error &ex) { + // LOGI("[OSVR] OSVR initialization failed: %s", ex.what()); + return false; + } } // Idempotent call to setup render manager static bool setupRenderManager() { - if (!gOSVRInitialized || !gGraphicsInitializedOnce) { - return false; - } - if (gRenderManagerInitialized) { - return true; - } - try { - PassThroughOpenGLContextImpl* glContextImpl = new PassThroughOpenGLContextImpl(); - gGraphicsLibrary.toolkit = glContextImpl->getToolkit(); - - if (OSVR_RETURN_SUCCESS != osvrCreateRenderManagerOpenGL( - gClientContext, "OpenGL", gGraphicsLibrary, &gRenderManager, &gRenderManagerOGL)) { - std::cerr << "Could not create the RenderManager" << std::endl; - return false; - } - - - - // Open the display and make sure this worked - OSVR_OpenResultsOpenGL openResults; - if (OSVR_RETURN_SUCCESS != osvrRenderManagerOpenDisplayOpenGL( - gRenderManagerOGL, &openResults) || - (openResults.status == OSVR_OPEN_STATUS_FAILURE)) { - std::cerr << "Could not open display" << std::endl; - osvrDestroyRenderManager(gRenderManager); - gRenderManager = gRenderManagerOGL = nullptr; - return false; - } - - gRenderManagerInitialized = true; - return true; - } - catch (const std::runtime_error &ex) { - //LOGI("[OSVR] RenderManager initialization failed: %s", ex.what()); - return false; - } + if (!gOSVRInitialized || !gGraphicsInitializedOnce) { + return false; + } + if (gRenderManagerInitialized) { + return true; + } + try { + PassThroughOpenGLContextImpl *glContextImpl = + new PassThroughOpenGLContextImpl(); + gGraphicsLibrary.toolkit = glContextImpl->getToolkit(); + + if (OSVR_RETURN_SUCCESS != + osvrCreateRenderManagerOpenGL(gClientContext, "OpenGL", + gGraphicsLibrary, &gRenderManager, + &gRenderManagerOGL)) { + std::cerr << "Could not create the RenderManager" << std::endl; + return false; + } + + // Open the display and make sure this worked + OSVR_OpenResultsOpenGL openResults; + if (OSVR_RETURN_SUCCESS != osvrRenderManagerOpenDisplayOpenGL( + gRenderManagerOGL, &openResults) || + (openResults.status == OSVR_OPEN_STATUS_FAILURE)) { + std::cerr << "Could not open display" << std::endl; + osvrDestroyRenderManager(gRenderManager); + gRenderManager = gRenderManagerOGL = nullptr; + return false; + } + + gRenderManagerInitialized = true; + return true; + } catch (const std::runtime_error &ex) { + // LOGI("[OSVR] RenderManager initialization failed: %s", ex.what()); + return false; + } } static const GLfloat gTriangleColors[] = { - // white - 1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, - - // green - 0.0f, 0.75f, 0.0f, 1.0f, - 0.0f, 0.75f, 0.0f, 1.0f, - 0.0f, 1.0f, 0.0f, 1.0f, - 0.0f, 0.75f, 0.0f, 1.0f, - 0.0f, 1.0f, 0.0f, 1.0f, - 0.0f, 1.0f, 0.0f, 1.0f, - - // blue - 0.0f, 0.0f, 0.75f, 1.0f, - 0.0f, 0.0f, 0.75f, 1.0f, - 0.0f, 0.0f, 1.0f, 1.0f, - 0.0f, 0.0f, 0.75f, 1.0f, - 0.0f, 0.0f, 1.0f, 1.0f, - 0.0f, 0.0f, 1.0f, 1.0f, - - // green/purple - 0.0f, 0.75f, 0.75f, 1.0f, - 0.0f, 0.75f, 0.75f, 1.0f, - 0.0f, 1.0f, 1.0f, 1.0f, - 0.0f, 0.75f, 0.75f, 1.0f, - 0.0f, 1.0f, 1.0f, 1.0f, - 0.0f, 1.0f, 1.0f, 1.0f, - - // red/green - 0.75f, 0.75f, 0.0f, 1.0f, - 0.75f, 0.75f, 0.0f, 1.0f, - 1.0f, 1.0f, 0.0f, 1.0f, - 0.75f, 0.75f, 0.0f, 1.0f, - 1.0f, 1.0f, 0.0f, 1.0f, - 1.0f, 1.0f, 0.0f, 1.0f, - - // red/blue - 0.75f, 0.0f, 0.75f, 1.0f, - 0.75f, 0.0f, 0.75f, 1.0f, - 1.0f, 0.0f, 1.0f, 1.0f, - 0.75f, 0.0f, 0.75f, 1.0f, - 1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, 0.0f, 1.0f, 1.0f -}; + // white + 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + + // green + 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, + 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, + + // blue + 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + + // green/purple + 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, + 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, + + // red/green + 0.75f, 0.75f, 0.0f, 1.0f, 0.75f, 0.75f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, + 0.75f, 0.75f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, + + // red/blue + 0.75f, 0.0f, 0.75f, 1.0f, 0.75f, 0.0f, 0.75f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 0.75f, 0.0f, 0.75f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f}; static const GLfloat gTriangleTexCoordinates[] = { - // A cube face (letters are unique vertices) - // A--B - // | | - // D--C - - // As two triangles (clockwise) - // A B D - // B C D - - // white - 1.0f, 0.0f, // A - 1.0f, 1.0f, // B - 0.0f, 0.0f, // D - 1.0f, 1.0f, // B - 0.0f, 1.0f, // C - 0.0f, 0.0f, // D - - // green - 1.0f, 0.0f, // A - 1.0f, 1.0f, // B - 0.0f, 0.0f, // D - 1.0f, 1.0f, // B - 0.0f, 1.0f, // C - 0.0f, 0.0f, // D - - // blue - 1.0f, 1.0f, // A - 0.0f, 1.0f, // B - 1.0f, 0.0f, // D - 0.0f, 1.0f, // B - 0.0f, 0.0f, // C - 1.0f, 0.0f, // D - - // blue-green - 1.0f, 0.0f, // A - 1.0f, 1.0f, // B - 0.0f, 0.0f, // D - 1.0f, 1.0f, // B - 0.0f, 1.0f, // C - 0.0f, 0.0f, // D - - // yellow - 0.0f, 0.0f, // A - 1.0f, 0.0f, // B - 0.0f, 1.0f, // D - 1.0f, 0.0f, // B - 1.0f, 1.0f, // C - 0.0f, 1.0f, // D - - // purple/magenta - 1.0f, 1.0f, // A - 0.0f, 1.0f, // B - 1.0f, 0.0f, // D - 0.0f, 1.0f, // B - 0.0f, 0.0f, // C - 1.0f, 0.0f, // D + // A cube face (letters are unique vertices) + // A--B + // | | + // D--C + + // As two triangles (clockwise) + // A B D + // B C D + + // white + 1.0f, 0.0f, // A + 1.0f, 1.0f, // B + 0.0f, 0.0f, // D + 1.0f, 1.0f, // B + 0.0f, 1.0f, // C + 0.0f, 0.0f, // D + + // green + 1.0f, 0.0f, // A + 1.0f, 1.0f, // B + 0.0f, 0.0f, // D + 1.0f, 1.0f, // B + 0.0f, 1.0f, // C + 0.0f, 0.0f, // D + + // blue + 1.0f, 1.0f, // A + 0.0f, 1.0f, // B + 1.0f, 0.0f, // D + 0.0f, 1.0f, // B + 0.0f, 0.0f, // C + 1.0f, 0.0f, // D + + // blue-green + 1.0f, 0.0f, // A + 1.0f, 1.0f, // B + 0.0f, 0.0f, // D + 1.0f, 1.0f, // B + 0.0f, 1.0f, // C + 0.0f, 0.0f, // D + + // yellow + 0.0f, 0.0f, // A + 1.0f, 0.0f, // B + 0.0f, 1.0f, // D + 1.0f, 0.0f, // B + 1.0f, 1.0f, // C + 0.0f, 1.0f, // D + + // purple/magenta + 1.0f, 1.0f, // A + 0.0f, 1.0f, // B + 1.0f, 0.0f, // D + 0.0f, 1.0f, // B + 0.0f, 0.0f, // C + 1.0f, 0.0f, // D }; static const GLfloat gTriangleVertices[] = { - // A cube face (letters are unique vertices) - // A--B - // | | - // D--C - - // As two triangles (clockwise) - // A B D - // B C D - - //glNormal3f(0.0, 0.0, -1.0); - 1.0f, 1.0f, -1.0f, // A - 1.0f, -1.0f, -1.0f, // B - -1.0f, 1.0f, -1.0f, // D - 1.0f, -1.0f, -1.0f, // B - -1.0f, -1.0f, -1.0f, // C - -1.0f, 1.0f, -1.0f, // D - - //glNormal3f(0.0, 0.0, 1.0); - -1.0f, 1.0f, 1.0f, // A - -1.0f, -1.0f, 1.0f, // B - 1.0f, 1.0f, 1.0f, // D - -1.0f, -1.0f, 1.0f, // B - 1.0f, -1.0f, 1.0f, // C - 1.0f, 1.0f, 1.0f, // D - - // glNormal3f(0.0, -1.0, 0.0); - 1.0f, -1.0f, 1.0f, // A - -1.0f, -1.0f, 1.0f, // B - 1.0f, -1.0f, -1.0f, // D - -1.0f, -1.0f, 1.0f, // B - -1.0f, -1.0f, -1.0f, // C - 1.0f, -1.0f, -1.0f, // D - - // glNormal3f(0.0, 1.0, 0.0); - 1.0f, 1.0f, 1.0f, // A - 1.0f, 1.0f, -1.0f, // B - -1.0f, 1.0f, 1.0f, // D - 1.0f, 1.0f, -1.0f, // B - -1.0f, 1.0f, -1.0f, // C - -1.0f, 1.0f, 1.0f, // D - - // glNormal3f(-1.0, 0.0, 0.0); - -1.0f, 1.0f, 1.0f, // A - -1.0f, 1.0f, -1.0f, // B - -1.0f, -1.0f, 1.0f, // D - -1.0f, 1.0f, -1.0f, // B - -1.0f, -1.0f, -1.0f, // C - -1.0f, -1.0f, 1.0f, // D - - // glNormal3f(1.0, 0.0, 0.0); - 1.0f, -1.0f, 1.0f, // A - 1.0f, -1.0f, -1.0f, // B - 1.0f, 1.0f, 1.0f, // D - 1.0f, -1.0f, -1.0f, // B - 1.0f, 1.0f, -1.0f, // C - 1.0f, 1.0f, 1.0f // D + // A cube face (letters are unique vertices) + // A--B + // | | + // D--C + + // As two triangles (clockwise) + // A B D + // B C D + + // glNormal3f(0.0, 0.0, -1.0); + 1.0f, 1.0f, -1.0f, // A + 1.0f, -1.0f, -1.0f, // B + -1.0f, 1.0f, -1.0f, // D + 1.0f, -1.0f, -1.0f, // B + -1.0f, -1.0f, -1.0f, // C + -1.0f, 1.0f, -1.0f, // D + + // glNormal3f(0.0, 0.0, 1.0); + -1.0f, 1.0f, 1.0f, // A + -1.0f, -1.0f, 1.0f, // B + 1.0f, 1.0f, 1.0f, // D + -1.0f, -1.0f, 1.0f, // B + 1.0f, -1.0f, 1.0f, // C + 1.0f, 1.0f, 1.0f, // D + + // glNormal3f(0.0, -1.0, 0.0); + 1.0f, -1.0f, 1.0f, // A + -1.0f, -1.0f, 1.0f, // B + 1.0f, -1.0f, -1.0f, // D + -1.0f, -1.0f, 1.0f, // B + -1.0f, -1.0f, -1.0f, // C + 1.0f, -1.0f, -1.0f, // D + + // glNormal3f(0.0, 1.0, 0.0); + 1.0f, 1.0f, 1.0f, // A + 1.0f, 1.0f, -1.0f, // B + -1.0f, 1.0f, 1.0f, // D + 1.0f, 1.0f, -1.0f, // B + -1.0f, 1.0f, -1.0f, // C + -1.0f, 1.0f, 1.0f, // D + + // glNormal3f(-1.0, 0.0, 0.0); + -1.0f, 1.0f, 1.0f, // A + -1.0f, 1.0f, -1.0f, // B + -1.0f, -1.0f, 1.0f, // D + -1.0f, 1.0f, -1.0f, // B + -1.0f, -1.0f, -1.0f, // C + -1.0f, -1.0f, 1.0f, // D + + // glNormal3f(1.0, 0.0, 0.0); + 1.0f, -1.0f, 1.0f, // A + 1.0f, -1.0f, -1.0f, // B + 1.0f, 1.0f, 1.0f, // D + 1.0f, -1.0f, -1.0f, // B + 1.0f, 1.0f, -1.0f, // C + 1.0f, 1.0f, 1.0f // D }; static bool setupGraphics(int width, int height) { - //printGLString("Version", GL_VERSION); - //printGLString("Vendor", GL_VENDOR); - //printGLString("Renderer", GL_RENDERER); - //printGLString("Extensions", GL_EXTENSIONS); - - //initializeGLES2Ext(); - GLint frameBuffer; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &frameBuffer); - gFrameBuffer = (GLuint)frameBuffer; - //LOGI("Window GL_FRAMEBUFFER_BINDING: %d", gFrameBuffer); - - //LOGI("setupGraphics(%d, %d)", width, height); - //gWidth = width; - //gHeight = height; - - //bool osvrSetupSuccess = setupOSVR(); - - gProgram = createProgram(gVertexShader, gFragmentShader); - if (!gProgram) { - //LOGE("Could not create program."); - osvrJniWrapperClass = jniEnvironment->FindClass("org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class - if (osvrJniWrapperClass == nullptr) { - return false; - } - else { // if class found, continue - - jmethodID logmid = jniEnvironment->GetStaticMethodID(osvrJniWrapperClass, "logMsg", "(Ljava/lang/String;)V"); // find method - std::string stringy = "[OSVR-Unity-Android] Could not create program."; - jstring jstr2 = jniEnvironment->NewStringUTF(stringy.c_str()); - jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, logmid, jstr2); - } - return false; - } - gvPositionHandle = glGetAttribLocation(gProgram, "vPosition"); - checkGlError("glGetAttribLocation"); - //LOGI("glGetAttribLocation(\"vPosition\") = %d\n", gvPositionHandle); - - gvColorHandle = glGetAttribLocation(gProgram, "vColor"); - checkGlError("glGetAttribLocation"); - //LOGI("glGetAttribLocation(\"vColor\") = %d\n", gvColorHandle); - - gvTexCoordinateHandle = glGetAttribLocation(gProgram, "vTexCoordinate"); - checkGlError("glGetAttribLocation"); - //LOGI("glGetAttribLocation(\"vTexCoordinate\") = %d\n", gvTexCoordinateHandle); - - gvProjectionUniformId = glGetUniformLocation(gProgram, "projection"); - gvViewUniformId = glGetUniformLocation(gProgram, "view"); - gvModelUniformId = glGetUniformLocation(gProgram, "model"); - guTextureUniformId = glGetUniformLocation(gProgram, "uTexture"); - - glViewport(0, 0, width, height); - checkGlError("glViewport"); - - glDisable(GL_CULL_FACE); - - // @todo can we resize the texture after it has been created? - // if not, we may have to delete the dummy one and create a new one after - // the first imaging report. - //LOGI("Creating texture... here we go!"); - - gTextureID = createTexture(width, height); - - //return osvrSetupSuccess; - gGraphicsInitializedOnce = true; - return true; + // printGLString("Version", GL_VERSION); + // printGLString("Vendor", GL_VENDOR); + // printGLString("Renderer", GL_RENDERER); + // printGLString("Extensions", GL_EXTENSIONS); + + // initializeGLES2Ext(); + GLint frameBuffer; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &frameBuffer); + gFrameBuffer = (GLuint)frameBuffer; + // LOGI("Window GL_FRAMEBUFFER_BINDING: %d", gFrameBuffer); + + // LOGI("setupGraphics(%d, %d)", width, height); + // gWidth = width; + // gHeight = height; + + // bool osvrSetupSuccess = setupOSVR(); + + gProgram = createProgram(gVertexShader, gFragmentShader); + if (!gProgram) { + // LOGE("Could not create program."); + osvrJniWrapperClass = jniEnvironment->FindClass( + "org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class + if (osvrJniWrapperClass == nullptr) { + return false; + } else { // if class found, continue + + jmethodID logmid = jniEnvironment->GetStaticMethodID( + osvrJniWrapperClass, "logMsg", + "(Ljava/lang/String;)V"); // find method + std::string stringy = + "[OSVR-Unity-Android] Could not create program."; + jstring jstr2 = jniEnvironment->NewStringUTF(stringy.c_str()); + jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, logmid, + jstr2); + } + return false; + } + gvPositionHandle = glGetAttribLocation(gProgram, "vPosition"); + checkGlError("glGetAttribLocation"); + // LOGI("glGetAttribLocation(\"vPosition\") = %d\n", gvPositionHandle); + + gvColorHandle = glGetAttribLocation(gProgram, "vColor"); + checkGlError("glGetAttribLocation"); + // LOGI("glGetAttribLocation(\"vColor\") = %d\n", gvColorHandle); + + gvTexCoordinateHandle = glGetAttribLocation(gProgram, "vTexCoordinate"); + checkGlError("glGetAttribLocation"); + // LOGI("glGetAttribLocation(\"vTexCoordinate\") = %d\n", + // gvTexCoordinateHandle); + + gvProjectionUniformId = glGetUniformLocation(gProgram, "projection"); + gvViewUniformId = glGetUniformLocation(gProgram, "view"); + gvModelUniformId = glGetUniformLocation(gProgram, "model"); + guTextureUniformId = glGetUniformLocation(gProgram, "uTexture"); + + glViewport(0, 0, width, height); + checkGlError("glViewport"); + + glDisable(GL_CULL_FACE); + + // @todo can we resize the texture after it has been created? + // if not, we may have to delete the dummy one and create a new one after + // the first imaging report. + // LOGI("Creating texture... here we go!"); + + gTextureID = createTexture(width, height); + + // return osvrSetupSuccess; + gGraphicsInitializedOnce = true; + return true; } /** * Just the current frame in the display. */ static void renderFrame() { - if (!gOSVRInitialized) { - // @todo implement some logging/error handling? - return; - } - - // this call is idempotent, so we can make it every frame. - // have to ensure render manager is setup from the rendering thread with - // a current GLES context, so this is a lazy setup call - if (!setupRenderManager()) { - // @todo implement some logging/error handling? - return; - } - - OSVR_ReturnCode rc; - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - checkGlError("glClearColor"); - glViewport(0, 0, gWidth, gHeight); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - checkGlError("glClear"); - - - if (gRenderManager && gClientContext) { - osvrClientUpdate(gClientContext); - if (gLastFrame != nullptr) { - updateTexture(gLastFrameWidth, gLastFrameHeight, gLastFrame); - osvrClientFreeImage(gClientContext, gLastFrame); - gLastFrame = nullptr; - } - - OSVR_RenderParams renderParams; - rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); - checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); - - RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, renderParams); - - // Get the present started - OSVR_RenderManagerPresentState presentState; - rc = osvrRenderManagerStartPresentRenderBuffers(&presentState); - checkReturnCode(rc, "osvrRenderManagerStartPresentRenderBuffers call failed."); - - for (OSVR_RenderInfoCount renderInfoCount = 0; - renderInfoCount < renderInfoCollection.getNumRenderInfo(); - renderInfoCount++) { - - // get the current render info - OSVR_RenderInfoOpenGL currentRenderInfo = renderInfoCollection.getRenderInfo(renderInfoCount); - // Set color and depth buffers for the frame buffer - OSVR_RenderTargetInfo renderTargetInfo = gRenderTargets[renderInfoCount]; - - // present this render target (deferred until the finish call below) - OSVR_ViewportDescription normalizedViewport = { 0 }; - normalizedViewport.left = 0.0f; - normalizedViewport.lower = 0.0f; - normalizedViewport.width = 1.0f; - normalizedViewport.height = 1.0f; - OSVR_RenderBufferOpenGL buffer = { 0 }; - buffer.colorBufferName = GetEyeTextureOpenGL(renderInfoCount); - buffer.depthStencilBufferName = renderTargetInfo.depthBufferName; - - rc = osvrRenderManagerPresentRenderBufferOpenGL( - presentState, buffer, currentRenderInfo, normalizedViewport); - checkReturnCode(rc, "osvrRenderManagerPresentRenderBufferOpenGL call failed."); - } - - // actually kick off the present - rc = osvrRenderManagerFinishPresentRenderBuffers( - gRenderManager, presentState, renderParams, false); - checkReturnCode(rc, "osvrRenderManagerFinishPresentRenderBuffers call failed."); - } + if (!gOSVRInitialized) { + // @todo implement some logging/error handling? + return; + } -} + // this call is idempotent, so we can make it every frame. + // have to ensure render manager is setup from the rendering thread with + // a current GLES context, so this is a lazy setup call + if (!setupRenderManager()) { + // @todo implement some logging/error handling? + return; + } + + OSVR_ReturnCode rc; + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + checkGlError("glClearColor"); + glViewport(0, 0, gWidth, gHeight); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + checkGlError("glClear"); + + if (gRenderManager && gClientContext) { + osvrClientUpdate(gClientContext); + if (gLastFrame != nullptr) { + updateTexture(gLastFrameWidth, gLastFrameHeight, gLastFrame); + osvrClientFreeImage(gClientContext, gLastFrame); + gLastFrame = nullptr; + } + OSVR_RenderParams renderParams; + rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); + checkReturnCode(rc, + "osvrRenderManagerGetDefaultRenderParams call failed."); + + RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, + renderParams); + + // Get the present started + OSVR_RenderManagerPresentState presentState; + rc = osvrRenderManagerStartPresentRenderBuffers(&presentState); + checkReturnCode( + rc, "osvrRenderManagerStartPresentRenderBuffers call failed."); + + for (OSVR_RenderInfoCount renderInfoCount = 0; + renderInfoCount < renderInfoCollection.getNumRenderInfo(); + renderInfoCount++) { + + // get the current render info + OSVR_RenderInfoOpenGL currentRenderInfo = + renderInfoCollection.getRenderInfo(renderInfoCount); + // Set color and depth buffers for the frame buffer + OSVR_RenderTargetInfo renderTargetInfo = + gRenderTargets[renderInfoCount]; + + // present this render target (deferred until the finish call below) + OSVR_ViewportDescription normalizedViewport = {0}; + normalizedViewport.left = 0.0f; + normalizedViewport.lower = 0.0f; + normalizedViewport.width = 1.0f; + normalizedViewport.height = 1.0f; + OSVR_RenderBufferOpenGL buffer = {0}; + buffer.colorBufferName = GetEyeTextureOpenGL(renderInfoCount); + buffer.depthStencilBufferName = renderTargetInfo.depthBufferName; + + rc = osvrRenderManagerPresentRenderBufferOpenGL( + presentState, buffer, currentRenderInfo, normalizedViewport); + checkReturnCode( + rc, "osvrRenderManagerPresentRenderBufferOpenGL call failed."); + } + + // actually kick off the present + rc = osvrRenderManagerFinishPresentRenderBuffers( + gRenderManager, presentState, renderParams, false); + checkReturnCode( + rc, "osvrRenderManagerFinishPresentRenderBuffers call failed."); + } +} static void stop() { - //LOGI("[OSVR] Shutting down..."); + // LOGI("[OSVR] Shutting down..."); - if (gRenderManager) { - osvrDestroyRenderManager(gRenderManager); - gRenderManager = gRenderManagerOGL = nullptr; - } + if (gRenderManager) { + osvrDestroyRenderManager(gRenderManager); + gRenderManager = gRenderManagerOGL = nullptr; + } - // is this needed? Maybe not. the display config manages the lifetime. - if (gClientContext != nullptr) { - osvrClientShutdown(gClientContext); - gClientContext = nullptr; - } + // is this needed? Maybe not. the display config manages the lifetime. + if (gClientContext != nullptr) { + osvrClientShutdown(gClientContext); + gClientContext = nullptr; + } - osvrClientReleaseAutoStartedServer(); + osvrClientReleaseAutoStartedServer(); } OSVR_ReturnCode CreateRenderManagerAndroid(OSVR_ClientContext context) { - gClientContext = context; - if(setupOSVR()) - { - if (setupGraphics(gWidth, gHeight)) - { - if (setupRenderManager()) - { - return OSVR_RETURN_SUCCESS; - } - else return 3; - } - else return 2; -} - else return 1; + gClientContext = context; + if (setupOSVR()) { + if (setupGraphics(gWidth, gHeight)) { + if (setupRenderManager()) { + return OSVR_RETURN_SUCCESS; + } else + return 3; + } else + return 2; + } else + return 1; - return OSVR_RETURN_SUCCESS; + return OSVR_RETURN_SUCCESS; } -void ShutdownRenderManagerAndroid() -{ - stop(); - contextSet = false; +void ShutdownRenderManagerAndroid() { + stop(); + contextSet = false; } #endif void UNITY_INTERFACE_API ShutdownRenderManager() { - DebugLog("[OSVR Rendering Plugin] Shutting down RenderManager."); + DebugLog("[OSVR Rendering Plugin] Shutting down RenderManager."); #if UNITY_ANDROID - ShutdownRenderManagerAndroid(); - return; -#else //non-Android platforms - if (s_render != nullptr) { - osvrDestroyRenderManager(s_render); - s_render = nullptr; - s_rightEyeTexturePtr = nullptr; - s_leftEyeTexturePtr = nullptr; - } - s_clientContext = nullptr; + ShutdownRenderManagerAndroid(); + return; +#else // non-Android platforms + if (s_render != nullptr) { + osvrDestroyRenderManager(s_render); + s_render = nullptr; + s_rightEyeTexturePtr = nullptr; + s_leftEyeTexturePtr = nullptr; + } + s_clientContext = nullptr; #endif } @@ -1419,20 +1433,20 @@ void UNITY_INTERFACE_API ShutdownRenderManager() { OSVR_ReturnCode UNITY_INTERFACE_API CreateRenderManagerFromUnity(OSVR_ClientContext context) { #if UNITY_ANDROID - return CreateRenderManagerAndroid(context); + return CreateRenderManagerAndroid(context); #else - if (s_render != nullptr) { - if (osvrRenderManagerGetDoingOkay(s_render)) { - DebugLog("[OSVR Rendering Plugin] RenderManager already created " - "and doing OK - will just return success without trying " - "to re-initialize."); - return OSVR_RETURN_SUCCESS; - } - - DebugLog("[OSVR Rendering Plugin] RenderManager already created, " - "but not doing OK. Will shut down before creating again."); - ShutdownRenderManager(); - } + if (s_render != nullptr) { + if (osvrRenderManagerGetDoingOkay(s_render)) { + DebugLog("[OSVR Rendering Plugin] RenderManager already created " + "and doing OK - will just return success without trying " + "to re-initialize."); + return OSVR_RETURN_SUCCESS; + } + + DebugLog("[OSVR Rendering Plugin] RenderManager already created, " + "but not doing OK. Will shut down before creating again."); + ShutdownRenderManager(); + } if (s_clientContext != nullptr) { DebugLog( "[OSVR Rendering Plugin] Client context already set! Replacing..."); @@ -1440,13 +1454,13 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context) { s_clientContext = context; if (!s_deviceType) { - // @todo pass the platform from Unity - // This is a patch to workaround a bug in Unity where the renderer type - // is not being set on Windows x86 builds. Until the OpenGL path is - // working, it's safe to assume we're using D3D11, but we'd rather get - // the platform from Unity than assume it's D3D11. + // @todo pass the platform from Unity + // This is a patch to workaround a bug in Unity where the renderer type + // is not being set on Windows x86 builds. Until the OpenGL path is + // working, it's safe to assume we're using D3D11, but we'd rather get + // the platform from Unity than assume it's D3D11. - s_deviceType = kUnityGfxRendererD3D11; + s_deviceType = kUnityGfxRendererD3D11; } bool setLibraryFromOpenDisplayReturn = false; @@ -1456,11 +1470,12 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context) { #if SUPPORT_D3D11 case OSVRSupportedRenderers::D3D11: - if (OSVR_RETURN_SUCCESS != osvrCreateRenderManagerD3D11( - context, "Direct3D11", s_libraryD3D, &s_render, &s_renderD3D)) { - DebugLog("[OSVR Rendering Plugin] Could not create RenderManager"); - return OSVR_RETURN_FAILURE; - } + if (OSVR_RETURN_SUCCESS != + osvrCreateRenderManagerD3D11(context, "Direct3D11", s_libraryD3D, + &s_render, &s_renderD3D)) { + DebugLog("[OSVR Rendering Plugin] Could not create RenderManager"); + return OSVR_RETURN_FAILURE; + } #ifdef ATTEMPT_D3D_SHARING setLibraryFromOpenDisplayReturn = true; #endif // ATTEMPT_D3D_SHARING @@ -1469,14 +1484,14 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context) { #if SUPPORT_OPENGL case OSVRSupportedRenderers::OpenGL: - // s_render = osvr::renderkit::createRenderManager(context, "OpenGL"); + // s_render = osvr::renderkit::createRenderManager(context, "OpenGL"); setLibraryFromOpenDisplayReturn = true; break; #endif // SUPPORT_OPENGL } if (s_render == nullptr) { - DebugLog("[OSVR Rendering Plugin] here we aer."); + DebugLog("[OSVR Rendering Plugin] here we aer."); DebugLog("[OSVR Rendering Plugin] Could not create RenderManager"); @@ -1484,36 +1499,38 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context) { return OSVR_RETURN_FAILURE; } - // Open the display and make sure this worked. - OSVR_OpenResultsD3D11 openResults; - if ((OSVR_RETURN_SUCCESS != osvrRenderManagerOpenDisplayD3D11( - s_renderD3D, &openResults)) || - (openResults.status == OSVR_OPEN_STATUS_FAILURE)) { - DebugLog("[OSVR Rendering Plugin] Could not open display"); - ShutdownRenderManager(); - return OSVR_RETURN_FAILURE; - } - if (openResults.library.device == nullptr) { - DebugLog("[OSVR Rendering Plugin] Could not get device when opening display"); + // Open the display and make sure this worked. + OSVR_OpenResultsD3D11 openResults; + if ((OSVR_RETURN_SUCCESS != + osvrRenderManagerOpenDisplayD3D11(s_renderD3D, &openResults)) || + (openResults.status == OSVR_OPEN_STATUS_FAILURE)) { + DebugLog("[OSVR Rendering Plugin] Could not open display"); + ShutdownRenderManager(); + return OSVR_RETURN_FAILURE; + } + if (openResults.library.device == nullptr) { + DebugLog("[OSVR Rendering Plugin] Could not get device when opening " + "display"); ShutdownRenderManager(); - return OSVR_RETURN_FAILURE; - } - if (openResults.library.context == nullptr) { - DebugLog("[OSVR Rendering Plugin] Could not get context when opening display"); + return OSVR_RETURN_FAILURE; + } + if (openResults.library.context == nullptr) { + DebugLog("[OSVR Rendering Plugin] Could not get context when opening " + "display"); - ShutdownRenderManager(); - return OSVR_RETURN_FAILURE; - } + ShutdownRenderManager(); + return OSVR_RETURN_FAILURE; + } // create a new set of RenderParams for passing to GetRenderInfo() - osvrRenderManagerGetDefaultRenderParams(&s_renderParams); - - UpdateRenderInfoCollection(); + osvrRenderManagerGetDefaultRenderParams(&s_renderParams); + + UpdateRenderInfoCollection(); DebugLog("[OSVR Rendering Plugin] CreateRenderManagerFromUnity Success!"); return OSVR_RETURN_SUCCESS; -#endif //non-Android platforms +#endif // non-Android platforms } /// Helper function that handles doing the loop of constructing buffers, and @@ -1523,18 +1540,18 @@ inline OSVR_ReturnCode applyRenderBufferConstructor(const int numBuffers, F &&bufferConstructor, G &&bufferCleanup) { #if UNITY_ANDROID - return OSVR_RETURN_SUCCESS; + return OSVR_RETURN_SUCCESS; #else /// If we bail any time before the end, we'll automatically clean up the /// render buffers with this lambda. - /* auto cleanupBuffers = osvr::util::finally([&] { - DebugLog("[OSVR Rendering Plugin] Cleaning up render buffers."); - for (auto &rb : s_renderBuffers) { - bufferCleanup(rb); - } - s_renderBuffers.clear(); - DebugLog("[OSVR Rendering Plugin] Render buffer cleanup complete."); - });*/ + /* auto cleanupBuffers = osvr::util::finally([&] { + DebugLog("[OSVR Rendering Plugin] Cleaning up render buffers."); + for (auto &rb : s_renderBuffers) { + bufferCleanup(rb); + } + s_renderBuffers.clear(); + DebugLog("[OSVR Rendering Plugin] Render buffer cleanup complete."); + });*/ /// Construct all the buffers as isntructed for (int i = 0; i < numBuffers; ++i) { @@ -1547,35 +1564,39 @@ inline OSVR_ReturnCode applyRenderBufferConstructor(const int numBuffers, /// Register our constructed buffers so that we can use them for /// presentation. - /* if (!s_render->RegisterRenderBuffers(s_renderBuffers)) { - DebugLog("RegisterRenderBuffers() returned false, cannot continue"); - return OSVR_RETURN_FAILURE; - }*/ - // Register our constructed buffers so that we can use them for - // presentation. - - UpdateRenderInfoCollection(); - - OSVR_RenderManagerRegisterBufferState registerBufferState; - if ((OSVR_RETURN_SUCCESS != osvrRenderManagerStartRegisterRenderBuffers( - ®isterBufferState))) { - DebugLog("[OSVR Rendering Plugin]Could not start registering render buffers"); - ShutdownRenderManager(); - } - for (size_t i = 0; i < numRenderInfo; i++) { - if ((OSVR_RETURN_SUCCESS != osvrRenderManagerRegisterRenderBufferD3D11( - registerBufferState, s_renderBuffers[i]))) { - DebugLog("[OSVR Rendering Plugin]Could not register render buffers"); - ShutdownRenderManager(); - } - } - if ((OSVR_RETURN_SUCCESS != osvrRenderManagerFinishRegisterRenderBuffers( - s_render, registerBufferState, false))) { - DebugLog("[OSVR Rendering Plugin]Could not finish registering render buffers"); - ShutdownRenderManager(); - } + /* if (!s_render->RegisterRenderBuffers(s_renderBuffers)) { + DebugLog("RegisterRenderBuffers() returned false, cannot continue"); + return OSVR_RETURN_FAILURE; + }*/ + // Register our constructed buffers so that we can use them for + // presentation. + + UpdateRenderInfoCollection(); + + OSVR_RenderManagerRegisterBufferState registerBufferState; + if ((OSVR_RETURN_SUCCESS != + osvrRenderManagerStartRegisterRenderBuffers(®isterBufferState))) { + DebugLog("[OSVR Rendering Plugin]Could not start registering render " + "buffers"); + ShutdownRenderManager(); + } + for (size_t i = 0; i < numRenderInfo; i++) { + if ((OSVR_RETURN_SUCCESS != + osvrRenderManagerRegisterRenderBufferD3D11(registerBufferState, + s_renderBuffers[i]))) { + DebugLog( + "[OSVR Rendering Plugin]Could not register render buffers"); + ShutdownRenderManager(); + } + } + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerFinishRegisterRenderBuffers( + s_render, registerBufferState, false))) { + DebugLog("[OSVR Rendering Plugin]Could not finish registering render " + "buffers"); + ShutdownRenderManager(); + } /// Only if we succeed, do we cancel the cleanup and carry on. - // cleanupBuffers.cancel(); + // cleanupBuffers.cancel(); return OSVR_RETURN_SUCCESS; #endif } @@ -1583,72 +1604,74 @@ inline OSVR_ReturnCode applyRenderBufferConstructor(const int numBuffers, #if SUPPORT_OPENGL inline OSVR_ReturnCode ConstructBuffersOpenGL(int eye) { // Init glew - /* glewExperimental = 1u; - /// @todo doesn't rendermanager do this glewInit for us? - GLenum err = glewInit(); - if (err != GLEW_OK) { - DebugLog("glewInit failed, aborting."); - /// @todo shouldn't we return here then? - } - - if (eye == 0) { - // do this once - glGenFramebuffers(1, &s_frameBuffer); - glBindFramebuffer(GL_FRAMEBUFFER, s_frameBuffer); - } - - // The color buffer for this eye. We need to put this into - // a generic structure for the Present function, but we only need - // to fill in the OpenGL portion. - if (eye == 0) // left eye - { - GLuint leftEyeColorBuffer = 0; - glGenRenderbuffers(1, &leftEyeColorBuffer); - osvr::renderkit::RenderBuffer rb; - rb.OpenGL = new osvr::renderkit::RenderBufferOpenGL; - rb.OpenGL->colorBufferName = leftEyeColorBuffer; - s_renderBuffers.push_back(rb); - // "Bind" the newly created texture : all future texture - // functions will modify this texture glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, leftEyeColorBuffer); - - // Give an empty image to OpenGL ( the last "0" means "empty" ) - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, - static_cast(s_renderInfo[eye].viewport.width), - static_cast(s_renderInfo[eye].viewport.height), 0, - GL_RGB, GL_UNSIGNED_BYTE, &leftEyeColorBuffer); - } else // right eye - { - GLuint rightEyeColorBuffer = 0; - glGenRenderbuffers(1, &rightEyeColorBuffer); - osvr::renderkit::RenderBuffer rb; - rb.OpenGL = new osvr::renderkit::RenderBufferOpenGL; - rb.OpenGL->colorBufferName = rightEyeColorBuffer; - s_renderBuffers.push_back(rb); - // "Bind" the newly created texture : all future texture - // functions will modify this texture glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, rightEyeColorBuffer); - - // Give an empty image to OpenGL ( the last "0" means "empty" ) - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, - static_cast(s_renderInfo[eye].viewport.width), - static_cast(s_renderInfo[eye].viewport.height), 0, - GL_RGB, GL_UNSIGNED_BYTE, &rightEyeColorBuffer); - } - - // Bilinear filtering - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - */ + /* glewExperimental = 1u; + /// @todo doesn't rendermanager do this glewInit for us? + GLenum err = glewInit(); + if (err != GLEW_OK) { + DebugLog("glewInit failed, aborting."); + /// @todo shouldn't we return here then? + } + + if (eye == 0) { + // do this once + glGenFramebuffers(1, &s_frameBuffer); + glBindFramebuffer(GL_FRAMEBUFFER, s_frameBuffer); + } + + // The color buffer for this eye. We need to put this into + // a generic structure for the Present function, but we only need + // to fill in the OpenGL portion. + if (eye == 0) // left eye + { + GLuint leftEyeColorBuffer = 0; + glGenRenderbuffers(1, &leftEyeColorBuffer); + osvr::renderkit::RenderBuffer rb; + rb.OpenGL = new osvr::renderkit::RenderBufferOpenGL; + rb.OpenGL->colorBufferName = leftEyeColorBuffer; + s_renderBuffers.push_back(rb); + // "Bind" the newly created texture : all future texture + // functions will modify this texture glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, leftEyeColorBuffer); + + // Give an empty image to OpenGL ( the last "0" means "empty" ) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, + static_cast(s_renderInfo[eye].viewport.width), + static_cast(s_renderInfo[eye].viewport.height), + 0, + GL_RGB, GL_UNSIGNED_BYTE, &leftEyeColorBuffer); + } else // right eye + { + GLuint rightEyeColorBuffer = 0; + glGenRenderbuffers(1, &rightEyeColorBuffer); + osvr::renderkit::RenderBuffer rb; + rb.OpenGL = new osvr::renderkit::RenderBufferOpenGL; + rb.OpenGL->colorBufferName = rightEyeColorBuffer; + s_renderBuffers.push_back(rb); + // "Bind" the newly created texture : all future texture + // functions will modify this texture glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, rightEyeColorBuffer); + + // Give an empty image to OpenGL ( the last "0" means "empty" ) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, + static_cast(s_renderInfo[eye].viewport.width), + static_cast(s_renderInfo[eye].viewport.height), + 0, + GL_RGB, GL_UNSIGNED_BYTE, &rightEyeColorBuffer); + } + + // Bilinear filtering + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + */ return OSVR_RETURN_SUCCESS; } inline void CleanupBufferOpenGL(OSVR_RenderBufferOpenGL &rb) { /// @todo incomplete cleanup - but better than leaking in case of failure. - // delete rb.OpenGL; - // rb.OpenGL = nullptr; + // delete rb.OpenGL; + // rb.OpenGL = nullptr; } #endif // SUPPORT_OPENGL @@ -1696,26 +1719,23 @@ inline OSVR_ReturnCode ConstructBuffersD3D11(int eye) { } // Push the filled-in RenderBuffer onto the stack. - OSVR_RenderBufferD3D11 rbD3D; + OSVR_RenderBufferD3D11 rbD3D; rbD3D.colorBuffer = D3DTexture; rbD3D.colorBufferView = renderTargetView; - s_renderBuffers.push_back(rbD3D); + s_renderBuffers.push_back(rbD3D); return OSVR_RETURN_SUCCESS; } -inline void CleanupBufferD3D11(OSVR_RenderBufferD3D11 &rb) { - delete &rb; - -} +inline void CleanupBufferD3D11(OSVR_RenderBufferD3D11 &rb) { delete &rb; } #endif // SUPPORT_D3D11 OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { #if UNITY_ANDROID - if (!setupRenderTextures(gRenderManager)) { - return OSVR_RETURN_FAILURE; - } - else return OSVR_RETURN_SUCCESS; + if (!setupRenderTextures(gRenderManager)) { + return OSVR_RETURN_FAILURE; + } else + return OSVR_RETURN_SUCCESS; #else if (!s_deviceType) { DebugLog("[OSVR Rendering Plugin] Device type not supported."); @@ -1724,7 +1744,7 @@ OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { UpdateRenderInfoCollection(); // construct buffers - const int n = static_cast(numRenderInfo); + const int n = static_cast(numRenderInfo); switch (s_deviceType.getDeviceTypeEnum()) { #if SUPPORT_D3D11 case OSVRSupportedRenderers::D3D11: @@ -1743,7 +1763,7 @@ OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { DebugLog("Device type not supported."); return OSVR_RETURN_FAILURE; } -#endif //non-Android platforms +#endif // non-Android platforms } void UNITY_INTERFACE_API SetNearClipDistance(double distance) { @@ -1758,120 +1778,121 @@ void UNITY_INTERFACE_API SetFarClipDistance(double distance) { #if !UNITY_ANDROID s_renderParams.farClipDistanceMeters = s_farClipDistance; #endif - } void UNITY_INTERFACE_API SetIPD(double ipdMeters) { s_ipd = ipdMeters; - // s_renderParams.IPDMeters = s_ipd; + // s_renderParams.IPDMeters = s_ipd; } -OSVR_ViewportDescription UNITY_INTERFACE_API -GetViewport(std::uint8_t eye) { +OSVR_ViewportDescription UNITY_INTERFACE_API GetViewport(std::uint8_t eye) { #if UNITY_ANDROID - OSVR_RenderParams renderParams; - OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); - checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); - RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, renderParams); - OSVR_RenderInfoOpenGL currentRenderInfo = renderInfoCollection.getRenderInfo(eye); - OSVR_ViewportDescription viewDesc; - viewDesc.width = currentRenderInfo.viewport.width; - viewDesc.height = currentRenderInfo.viewport.height; - viewDesc.left = currentRenderInfo.viewport.left; - viewDesc.lower = currentRenderInfo.viewport.lower; - return viewDesc; -#else //non-Android platoforms - OSVR_ViewportDescription viewportDescription; - if (numRenderInfo > 0 && eye <= numRenderInfo - 1) - { - viewportDescription = s_lastRenderInfo[eye].viewport; - - //cache the viewport width and height - //patches issue where sometimes empty viewport is returned - //@todo fix the real cause of why this method bugs out occasionally on some machines, more often on others - if (viewportWidth == 0 && s_lastRenderInfo[eye].viewport.width != 0) - { - viewportWidth = s_lastRenderInfo[eye].viewport.width; - } - if (viewportHeight == 0 && s_lastRenderInfo[eye].viewport.height != 0) - { - viewportHeight = s_lastRenderInfo[eye].viewport.height; - } - lastGoodViewportDescription = viewportDescription; - } - else - { - //we shouldn't be here unless we hit a bug, in which case, we avoid error by returning cached viewport values - std::string errorLog = "[OSVR Rendering Plugin] Error in GetViewport, returning cached values. Eye = " + std::to_string(int(eye)); - DebugLog(errorLog.c_str()); - /*viewportDescription.left = 0; - viewportDescription.lower = 0; - viewportDescription.width = viewportWidth; - viewportDescription.height = viewportHeight;*/ - lastGoodViewportDescription = viewportDescription; - } - return viewportDescription; -#endif //non-Android platforms + OSVR_RenderParams renderParams; + OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); + checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); + RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, + renderParams); + OSVR_RenderInfoOpenGL currentRenderInfo = + renderInfoCollection.getRenderInfo(eye); + OSVR_ViewportDescription viewDesc; + viewDesc.width = currentRenderInfo.viewport.width; + viewDesc.height = currentRenderInfo.viewport.height; + viewDesc.left = currentRenderInfo.viewport.left; + viewDesc.lower = currentRenderInfo.viewport.lower; + return viewDesc; +#else // non-Android platoforms + OSVR_ViewportDescription viewportDescription; + if (numRenderInfo > 0 && eye <= numRenderInfo - 1) { + viewportDescription = s_lastRenderInfo[eye].viewport; + + // cache the viewport width and height + // patches issue where sometimes empty viewport is returned + //@todo fix the real cause of why this method bugs out occasionally on + //some machines, more often on others + if (viewportWidth == 0 && s_lastRenderInfo[eye].viewport.width != 0) { + viewportWidth = s_lastRenderInfo[eye].viewport.width; + } + if (viewportHeight == 0 && s_lastRenderInfo[eye].viewport.height != 0) { + viewportHeight = s_lastRenderInfo[eye].viewport.height; + } + lastGoodViewportDescription = viewportDescription; + } else { + // we shouldn't be here unless we hit a bug, in which case, we avoid + // error by returning cached viewport values + std::string errorLog = "[OSVR Rendering Plugin] Error in GetViewport, " + "returning cached values. Eye = " + + std::to_string(int(eye)); + DebugLog(errorLog.c_str()); + /*viewportDescription.left = 0; + viewportDescription.lower = 0; + viewportDescription.width = viewportWidth; + viewportDescription.height = viewportHeight;*/ + lastGoodViewportDescription = viewportDescription; + } + return viewportDescription; +#endif // non-Android platforms } - OSVR_ProjectionMatrix UNITY_INTERFACE_API GetProjectionMatrix(std::uint8_t eye) { #if UNITY_ANDROID - OSVR_RenderParams renderParams; - OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); - checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); - RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, renderParams); - OSVR_RenderInfoOpenGL currentRenderInfo = renderInfoCollection.getRenderInfo(eye); - OSVR_ProjectionMatrix proj; - proj.left = currentRenderInfo.projection.left; - proj.right = currentRenderInfo.projection.right; - proj.top = currentRenderInfo.projection.top; - proj.bottom = currentRenderInfo.projection.bottom; - proj.nearClip = currentRenderInfo.projection.nearClip; - proj.farClip = currentRenderInfo.projection.farClip; - return proj; + OSVR_RenderParams renderParams; + OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); + checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); + RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, + renderParams); + OSVR_RenderInfoOpenGL currentRenderInfo = + renderInfoCollection.getRenderInfo(eye); + OSVR_ProjectionMatrix proj; + proj.left = currentRenderInfo.projection.left; + proj.right = currentRenderInfo.projection.right; + proj.top = currentRenderInfo.projection.top; + proj.bottom = currentRenderInfo.projection.bottom; + proj.nearClip = currentRenderInfo.projection.nearClip; + proj.farClip = currentRenderInfo.projection.farClip; + return proj; #else - OSVR_ProjectionMatrix pm; - if (numRenderInfo > 0 && eye <= numRenderInfo - 1) - { - pm = s_lastRenderInfo[eye].projection; - lastGoodProjMatrix = pm; - } - else - { - std::string errorLog = "[OSVR Rendering Plugin] Error in GetProjectionMatrix, returning default values. Eye = " + std::to_string(int(eye)); - DebugLog(errorLog.c_str()); - pm = lastGoodProjMatrix; - } - return pm; -#endif //non-Android platforms + OSVR_ProjectionMatrix pm; + if (numRenderInfo > 0 && eye <= numRenderInfo - 1) { + pm = s_lastRenderInfo[eye].projection; + lastGoodProjMatrix = pm; + } else { + std::string errorLog = "[OSVR Rendering Plugin] Error in " + "GetProjectionMatrix, returning default values. " + "Eye = " + + std::to_string(int(eye)); + DebugLog(errorLog.c_str()); + pm = lastGoodProjMatrix; + } + return pm; +#endif // non-Android platforms } OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { #if UNITY_ANDROID - OSVR_RenderParams renderParams; - OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); - checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); - RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, renderParams); - OSVR_RenderInfoOpenGL currentRenderInfo = renderInfoCollection.getRenderInfo(eye); - return currentRenderInfo.pose; + OSVR_RenderParams renderParams; + OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); + checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); + RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, + renderParams); + OSVR_RenderInfoOpenGL currentRenderInfo = + renderInfoCollection.getRenderInfo(eye); + return currentRenderInfo.pose; #else - OSVR_Pose3 pose; - osvrPose3SetIdentity(&pose); - if (numRenderInfo > 0 && eye <= numRenderInfo - 1) - { - pose = s_lastRenderInfo[eye].pose; - lastGoodPose = pose; - } - else - { - std::string errorLog = "[OSVR Rendering Plugin] Error in GetEyePose, returning default values. Eye = " + std::to_string(int(eye)); - DebugLog(errorLog.c_str()); - pose = lastGoodPose; - } - return pose; -#endif //non-Android platforms + OSVR_Pose3 pose; + osvrPose3SetIdentity(&pose); + if (numRenderInfo > 0 && eye <= numRenderInfo - 1) { + pose = s_lastRenderInfo[eye].pose; + lastGoodPose = pose; + } else { + std::string errorLog = "[OSVR Rendering Plugin] Error in GetEyePose, " + "returning default values. Eye = " + + std::to_string(int(eye)); + DebugLog(errorLog.c_str()); + pose = lastGoodPose; + } + return pose; +#endif // non-Android platforms } // -------------------------------------------------------------------------- @@ -1887,7 +1908,8 @@ OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { // to set up needed texture pointers only at initialization time. // For more reference, see: // http://docs.unity3d.com/ScriptReference/Texture.GetNativeTexturePtr.html -int UNITY_INTERFACE_API SetColorBufferFromUnity(void *texturePtr, std::uint8_t eye) { +int UNITY_INTERFACE_API SetColorBufferFromUnity(void *texturePtr, + std::uint8_t eye) { if (!s_deviceType) { return OSVR_RETURN_FAILURE; } @@ -1895,12 +1917,12 @@ int UNITY_INTERFACE_API SetColorBufferFromUnity(void *texturePtr, std::uint8_t e DebugLog("[OSVR Rendering Plugin] SetColorBufferFromUnity"); #if UNITY_ANDROID - if (eye == 0) { - gLeftEyeTextureID = (GLuint)texturePtr; - } else { - gRightEyeTextureID = (GLuint)texturePtr; - } - return OSVR_RETURN_SUCCESS; + if (eye == 0) { + gLeftEyeTextureID = (GLuint)texturePtr; + } else { + gRightEyeTextureID = (GLuint)texturePtr; + } + return OSVR_RETURN_SUCCESS; #else if (eye == 0) { s_leftEyeTexturePtr = texturePtr; @@ -1915,13 +1937,13 @@ int UNITY_INTERFACE_API SetColorBufferFromUnity(void *texturePtr, std::uint8_t e // Renders the view from our Unity cameras by copying data at // Unity.RenderTexture.GetNativeTexturePtr() to RenderManager colorBuffers void RenderViewD3D11(const OSVR_RenderInfoD3D11 &ri, - ID3D11RenderTargetView *renderTargetView, int eyeIndex) { - auto context = ri.library.context; - // Set up to render to the textures for this eye - context->OMSetRenderTargets(1, &renderTargetView, NULL); + ID3D11RenderTargetView *renderTargetView, int eyeIndex) { + auto context = ri.library.context; + // Set up to render to the textures for this eye + context->OMSetRenderTargets(1, &renderTargetView, NULL); - // copy the updated RenderTexture from Unity to RenderManager colorBuffer - s_renderBuffers[eyeIndex].colorBuffer = GetEyeTextureD3D11(eyeIndex); + // copy the updated RenderTexture from Unity to RenderManager colorBuffer + s_renderBuffers[eyeIndex].colorBuffer = GetEyeTextureD3D11(eyeIndex); } #endif // SUPPORT_D3D11 @@ -1929,74 +1951,75 @@ void RenderViewD3D11(const OSVR_RenderInfoD3D11 &ri, // Render the world from the specified point of view. //@todo This is not functional yet. inline void RenderViewOpenGL( - const OSVR_RenderInfoOpenGL &ri, //< Info needed to render + const OSVR_RenderInfoOpenGL &ri, //< Info needed to render GLuint frameBufferObj, //< Frame buffer object to bind our buffers to GLuint colorBuffer, //< Color buffer to render into int eyeIndex) { // Render to our framebuffer - /* glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObj); - - // Set color and depth buffers for the frame buffer - glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorBuffer, 0); - // glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - // GL_RENDERBUFFER, depthBuffer); - - // Set the list of draw buffers. - GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0}; - glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers - - // Always check that our framebuffer is ok - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - DebugLog("RenderView: Incomplete Framebuffer"); - return; - } - - // Set the viewport to cover our entire render texture. - glViewport(0, 0, static_cast(ri.viewport.width), - static_cast(ri.viewport.height)); - - // Set the OpenGL projection matrix - GLdouble projection[16]; - osvr::renderkit::OSVR_Projection_to_OpenGL(projection, ri.projection); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMultMatrixd(projection); - - /// Put the transform into the OpenGL ModelView matrix - GLdouble modelView[16]; - osvr::renderkit::OSVR_PoseState_to_OpenGL(modelView, ri.pose); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glMultMatrixd(modelView); - - // Clear the screen to red and clear depth - glClearColor(1, 0, 0, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // ================================================================= - // This is where we draw our world and hands and any other objects. - // We're in World Space. To find out about where to render objects - // in OSVR spaces (like left/right hand space) we need to query the - // interface and handle the coordinate tranforms ourselves. - - // update native texture from code - glBindTexture(GL_TEXTURE_2D, - s_renderBuffers[eyeIndex].OpenGL->colorBufferName); - int texWidth, texHeight; - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texWidth); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texHeight); - - GLuint glTex = eyeIndex == 0 ? (GLuint)s_leftEyeTexturePtr - : (GLuint)s_rightEyeTexturePtr; - - // unsigned char* data = new unsigned char[texWidth*texHeight * 4]; - // FillTextureFromCode(texWidth, texHeight, texHeight * 4, data); - // glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, - // GL_UNSIGNED_BYTE, (GLuint)); - // delete[] data; - // Draw a cube with a 5-meter radius as the room we are floating in. - // draw_cube(5.0); - */ + /* glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObj); + + // Set color and depth buffers for the frame buffer + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorBuffer, + 0); + // glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + // GL_RENDERBUFFER, depthBuffer); + + // Set the list of draw buffers. + GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0}; + glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers + + // Always check that our framebuffer is ok + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + DebugLog("RenderView: Incomplete Framebuffer"); + return; + } + + // Set the viewport to cover our entire render texture. + glViewport(0, 0, static_cast(ri.viewport.width), + static_cast(ri.viewport.height)); + + // Set the OpenGL projection matrix + GLdouble projection[16]; + osvr::renderkit::OSVR_Projection_to_OpenGL(projection, ri.projection); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMultMatrixd(projection); + + /// Put the transform into the OpenGL ModelView matrix + GLdouble modelView[16]; + osvr::renderkit::OSVR_PoseState_to_OpenGL(modelView, ri.pose); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glMultMatrixd(modelView); + + // Clear the screen to red and clear depth + glClearColor(1, 0, 0, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // ================================================================= + // This is where we draw our world and hands and any other objects. + // We're in World Space. To find out about where to render objects + // in OSVR spaces (like left/right hand space) we need to query the + // interface and handle the coordinate tranforms ourselves. + + // update native texture from code + glBindTexture(GL_TEXTURE_2D, + s_renderBuffers[eyeIndex].OpenGL->colorBufferName); + int texWidth, texHeight; + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texWidth); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texHeight); + + GLuint glTex = eyeIndex == 0 ? (GLuint)s_leftEyeTexturePtr + : (GLuint)s_rightEyeTexturePtr; + + // unsigned char* data = new unsigned char[texWidth*texHeight * 4]; + // FillTextureFromCode(texWidth, texHeight, texHeight * 4, data); + // glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, + // GL_UNSIGNED_BYTE, (GLuint)); + // delete[] data; + // Draw a cube with a 5-meter radius as the room we are floating in. + // draw_cube(5.0); + */ } #endif // SUPPORT_OPENGL @@ -2007,36 +2030,42 @@ inline void DoRender() { switch (s_deviceType.getDeviceTypeEnum()) { #if SUPPORT_D3D11 case OSVRSupportedRenderers::D3D11: { - const auto n = static_cast(numRenderInfo); - // Render into each buffer using the specified information. - for (int i = 0; i < n; ++i) { - RenderViewD3D11(s_renderInfo[i], - s_renderBuffers[i].colorBufferView, i); - } - - // Send the rendered results to the screen - OSVR_RenderManagerPresentState presentState; - if ((OSVR_RETURN_SUCCESS != osvrRenderManagerStartPresentRenderBuffers( - &presentState))) { - DebugLog("[OSVR Rendering Plugin] Could not start presenting render buffers"); - ShutdownRenderManager(); - } - OSVR_ViewportDescription fullView; - fullView.left = fullView.lower = 0; - fullView.width = fullView.height = 1; - for (size_t i = 0; i < numRenderInfo; i++) { - if ((OSVR_RETURN_SUCCESS != osvrRenderManagerPresentRenderBufferD3D11( - presentState, s_renderBuffers[i], s_renderInfo[i], fullView))) { - DebugLog("[OSVR Rendering Plugin] Could not present render buffer "); - ShutdownRenderManager(); - } - } - - if ((OSVR_RETURN_SUCCESS != osvrRenderManagerFinishPresentRenderBuffers( - s_render, presentState, s_renderParams, true))) { - DebugLog("[OSVR Rendering Plugin] Could not finish presenting render buffers"); - ShutdownRenderManager(); - } + const auto n = static_cast(numRenderInfo); + // Render into each buffer using the specified information. + for (int i = 0; i < n; ++i) { + RenderViewD3D11(s_renderInfo[i], s_renderBuffers[i].colorBufferView, + i); + } + + // Send the rendered results to the screen + OSVR_RenderManagerPresentState presentState; + if ((OSVR_RETURN_SUCCESS != + osvrRenderManagerStartPresentRenderBuffers(&presentState))) { + DebugLog("[OSVR Rendering Plugin] Could not start presenting " + "render buffers"); + ShutdownRenderManager(); + } + OSVR_ViewportDescription fullView; + fullView.left = fullView.lower = 0; + fullView.width = fullView.height = 1; + for (size_t i = 0; i < numRenderInfo; i++) { + if ((OSVR_RETURN_SUCCESS != + osvrRenderManagerPresentRenderBufferD3D11( + presentState, s_renderBuffers[i], s_renderInfo[i], + fullView))) { + DebugLog( + "[OSVR Rendering Plugin] Could not present render buffer "); + ShutdownRenderManager(); + } + } + + if ((OSVR_RETURN_SUCCESS != + osvrRenderManagerFinishPresentRenderBuffers( + s_render, presentState, s_renderParams, true))) { + DebugLog("[OSVR Rendering Plugin] Could not finish presenting " + "render buffers"); + ShutdownRenderManager(); + } break; } #endif // SUPPORT_D3D11 @@ -2044,23 +2073,23 @@ inline void DoRender() { #if SUPPORT_OPENGL case OSVRSupportedRenderers::OpenGL: { #if UNITY_ANDROID - renderFrame(); + renderFrame(); #endif // OpenGL //@todo OpenGL path is not working yet // Render into each buffer using the specified information. - /* for (int i = 0; i < n; ++i) { - RenderViewOpenGL(s_renderInfo[i], s_frameBuffer, - s_renderBuffers[i].OpenGL->colorBufferName, i); - } - - // Send the rendered results to the screen - if (!s_render->PresentRenderBuffers(s_renderBuffers, s_renderInfo)) { - DebugLog("PresentRenderBuffers() returned false, maybe because " - "it was asked to quit"); - } - break;*/ + /* for (int i = 0; i < n; ++i) { + RenderViewOpenGL(s_renderInfo[i], s_frameBuffer, + s_renderBuffers[i].OpenGL->colorBufferName, i); + } + + // Send the rendered results to the screen + if (!s_render->PresentRenderBuffers(s_renderBuffers, s_renderInfo)) { + DebugLog("PresentRenderBuffers() returned false, maybe because " + "it was asked to quit"); + } + break;*/ } #endif // SUPPORT_OPENGL From 0681c81cf137a1e3dcfb830a1663db3d98b6e0d4 Mon Sep 17 00:00:00 2001 From: JeroMiya Date: Mon, 31 Jul 2017 12:14:45 -0400 Subject: [PATCH 32/43] Added experimental android vsync timings to Unity's OpenGL custom toolkit. --- OsvrRenderingPlugin.cpp | 118 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 1 deletion(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index bb00f4d..5596469 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -96,6 +96,12 @@ Sensics, Inc. #include #endif // SUPPORT_OPENGL +#if OSVR_ANDROID +#include +#include +#include +#endif + // VARIABLES static IUnityInterfaces *s_UnityInterfaces = nullptr; static IUnityGraphics *s_Graphics = nullptr; @@ -641,11 +647,74 @@ static void checkGlError(const char *op) { } } +#if OSVR_ANDROID +static long gPreviousFrameTimeNanos = 0; +static long gLastFrameTimeNanos = 0; +static std::mutex gFrameTimeMutex; + +/** + * This func is called on an app frame callback by the + * Choreographer on Android. + * NOTE: This is offset from the real "last vsync" when the + * Android build has offset. @todo account for this offset using JNI. + */ +static void frameCallbackImpl(long frameTimeNanos, void *data) { + std::lock_guard lockGuard(gFrameTimeMutex); + gPreviousFrameTimeNanos = gLastFrameTimeNanos; + gLastFrameTimeNanos = frameTimeNanos; + // LOGI("frameTimeNanos: %d", frameTimeNanos); + // LOGI("diff: %d", frameTimeNanos - gPreviousFrameTimeNanos); + AChoreographer *choreographer = AChoreographer_getInstance(); + if (!choreographer) { + LOGE("Couldn't get the choreographer from the frame callback"); + } + AChoreographer_postFrameCallback(choreographer, frameCallbackImpl, nullptr); +} + +/** + * Use this function in a std::thread to keep the ALooper pumping AChoreographer + * callbacks on a separate thread from where it's consumed. Otherwise the polling + * here will stall the render thread. + * @TODO - provide a way to signal graceful thread exit. + */ +static void choreographerThreadRun() { + ALooper *looper = ALooper_forThread(); + if (!looper) { + looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); + if (!looper) { + LOGE("Couldn't prepare an ALooper for the choreographer thread"); + return; + } + } + + AChoreographer *choreographer = AChoreographer_getInstance(); + if (!choreographer) { + LOGE("Could not get choreographer."); + return; + } + + AChoreographer_postFrameCallback(choreographer, frameCallbackImpl, nullptr); + + while (true) { + // @TODO provide a signal for graceful thread exit? + int fd_unused = 0; + int outEvents_unused = 0; + void *outData_unused = nullptr; + int rc = ALooper_pollAll(100, &fd_unused, &outEvents_unused, + &outData_unused); + } +} +#endif + class PassThroughOpenGLContextImpl { OSVR_OpenGLToolkitFunctions toolkit; int mWidth; int mHeight; +#if OSVR_ANDROID + std::thread mChoreographerThread; +#endif + static void createImpl(void *data) {} static void destroyImpl(void *data) { delete ((PassThroughOpenGLContextImpl *)data); @@ -680,9 +749,17 @@ class PassThroughOpenGLContextImpl { return ((PassThroughOpenGLContextImpl *)data) ->getDisplaySizeOverride(display, width, height); } + static OSVR_CBool getRenderTimingInfoImpl(void* data, size_t display, size_t whichEye, OSVR_RenderTimingInfo* renderTimingInfoOut) { + return ((PassThroughOpenGLContextImpl*)data) + ->getRenderTimingInfo(display, whichEye, renderTimingInfoOut); + } public: - PassThroughOpenGLContextImpl() { +#if OSVR_ANDROID + PassThroughOpenGLContextImpl() : mChoreographerThread(choreographerThreadRun) { +#else + PassThroughOpenGLContextImpl() { +#endif memset(&toolkit, 0, sizeof(toolkit)); toolkit.size = sizeof(toolkit); toolkit.data = this; @@ -697,8 +774,10 @@ class PassThroughOpenGLContextImpl { toolkit.handleEvents = handleEventsImpl; toolkit.getDisplaySizeOverride = getDisplaySizeOverrideImpl; toolkit.getDisplayFrameBuffer = getDisplayFrameBufferImpl; + toolkit.getRenderTimingInfo = getRenderTimingInfoImpl; } + // @TODO: gracefully exit the Choreographer thread on Android ~PassThroughOpenGLContextImpl() {} const OSVR_OpenGLToolkitFunctions *getToolkit() const { return &toolkit; } @@ -724,6 +803,43 @@ class PassThroughOpenGLContextImpl { *height = gHeight; return false; } + + bool getRenderTimingInfo(size_t display, size_t whichEye, + OSVR_RenderTimingInfo *renderTimingInfoOut) { +#if OSVR_ANDROID + timespec tp; + int rv = clock_gettime(CLOCK_MONOTONIC, &tp); + if (!rv) { + std::lock_guard lockGuard(gFrameTimeMutex); + // uint64_t presentationDeadline = 17683333L; // Shouldn't this bee + // at least less than 16,666,666? (1 billion / 60) + // that's 1,016,666 nanoseconds greater than the hardware interval + // uint64_t hardwareDisplayIntervalNanos = 11111111L; // 90Hz hard + // coded, TODO measure this or get it from the API? + uint64_t hardwareDisplayIntervalNanos = gLastFrameTimeNanos - gPreviousFrameTimeNanos; + uint64_t nowNanos = ((tp.tv_sec * 1000000000L) + tp.tv_nsec); + uint64_t timeFromLastNanos = nowNanos >= gLastFrameTimeNanos + ? nowNanos - gLastFrameTimeNanos + : 0; // just being safe + uint64_t nextNanos = gLastFrameTimeNanos + hardwareDisplayIntervalNanos; + uint64_t timeUntilNextNanos = + nextNanos >= nowNanos ? nextNanos - nowNanos + : 0; // 0 here means we missed a vsync + + nanoSecondsToTimeValue(timeFromLastNanos, + &renderTimingInfoOut->timeSincelastVerticalRetrace); + + nanoSecondsToTimeValue(timeUntilNextNanos, + &renderTimingInfoOut->timeUntilNextPresentRequired); + + nanoSecondsToTimeValue(hardwareDisplayIntervalNanos, + &renderTimingInfoOut->hardwareDisplayInterval); + return true; + } + LOGI("clock_gettime call failed."); +#endif + return false; + } }; static GLuint loadShader(GLenum shaderType, const char *pSource) { From 5bfd6a53a52fec75b4416c6641c76be957a3dca2 Mon Sep 17 00:00:00 2001 From: JeroMiya Date: Tue, 1 Aug 2017 13:09:13 -0400 Subject: [PATCH 33/43] Fixed build errors on Android. --- OsvrRenderingPlugin.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 5596469..155caf6 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -53,6 +53,7 @@ Sensics, Inc. #include #include #include +#include #include #endif @@ -100,8 +101,13 @@ Sensics, Inc. #include #include #include + +#define LOG_TAG "osvrUnityRendering" +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) +#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) #endif + // VARIABLES static IUnityInterfaces *s_UnityInterfaces = nullptr; static IUnityGraphics *s_Graphics = nullptr; @@ -191,6 +197,12 @@ static const char gFragmentShader[] = //" gl_FragColor = texture2D(uTexture, texCoordinate);\n" "}\n"; +inline void nanoSecondsToTimeValue(uint64_t nanos, OSVR_TimeValue *tvOut) { + tvOut->seconds = 0; + tvOut->microseconds = nanos / 1000; + osvrTimeValueNormalize(tvOut); +} + #else // Windows, Linux, OSX static variables static OSVR_RenderParams s_renderParams; static OSVR_RenderManager s_render = nullptr; From 70925c9d45b70e928ec708a0c8cb94a571e7faa5 Mon Sep 17 00:00:00 2001 From: JeroMiya Date: Tue, 8 Aug 2017 09:50:07 -0400 Subject: [PATCH 34/43] Attempt to cleanup a bad copy/paste --- OsvrRenderingPlugin.cpp | 483 ++++++++++++++++++++-------------------- 1 file changed, 244 insertions(+), 239 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 155caf6..5c0d329 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -132,16 +132,16 @@ static jobject unityActivityClassInstance; static int gWidth = 0; static int gHeight = 0; -static GLuint gProgram; -static GLuint gvPositionHandle; -static GLuint gvColorHandle; -static GLuint gvTexCoordinateHandle; -static GLuint guTextureUniformId; -static GLuint gvProjectionUniformId; -static GLuint gvViewUniformId; -static GLuint gvModelUniformId; +//static GLuint gProgram; +//static GLuint gvPositionHandle; +//static GLuint gvColorHandle; +//static GLuint gvTexCoordinateHandle; +//static GLuint guTextureUniformId; +//static GLuint gvProjectionUniformId; +//static GLuint gvViewUniformId; +//static GLuint gvModelUniformId; static GLuint gFrameBuffer; -static GLuint gTextureID; +//static GLuint gTextureID; static GLuint gLeftEyeTextureID; static GLuint gRightEyeTextureID; static bool gGraphicsInitializedOnce = @@ -156,12 +156,12 @@ typedef struct OSVR_RenderTargetInfo { GLuint renderBufferName; // @todo - do we need this? } OSVR_RenderTargetInfo; static OSVR_ClientContext gClientContext = NULL; -static OSVR_ClientInterface gCamera = NULL; -static OSVR_ClientInterface gHead = NULL; -static int gReportNumber = 0; -static OSVR_ImageBufferElement *gLastFrame = nullptr; -static GLuint gLastFrameWidth = 0; -static GLuint gLastFrameHeight = 0; +//static OSVR_ClientInterface gCamera = NULL; +//static OSVR_ClientInterface gHead = NULL; +//static int gReportNumber = 0; +//static OSVR_ImageBufferElement *gLastFrame = nullptr; +//static GLuint gLastFrameWidth = 0; +//static GLuint gLastFrameHeight = 0; static GLubyte *gTextureBuffer = nullptr; static OSVR_GraphicsLibraryOpenGL gGraphicsLibrary = {0}; static OSVR_RenderManager gRenderManager = nullptr; @@ -262,6 +262,7 @@ inline void DebugLog(const char *str) { //@todo complete logMsg implementation in JNI plugin // for now just return on Android #if UNITY_ANDROID + LOGE(str); return; #else // all platforms besides Android #if !defined(NDEBUG) || defined(ENABLE_LOGGING) @@ -674,8 +675,11 @@ static void frameCallbackImpl(long frameTimeNanos, void *data) { std::lock_guard lockGuard(gFrameTimeMutex); gPreviousFrameTimeNanos = gLastFrameTimeNanos; gLastFrameTimeNanos = frameTimeNanos; - // LOGI("frameTimeNanos: %d", frameTimeNanos); - // LOGI("diff: %d", frameTimeNanos - gPreviousFrameTimeNanos); + /// LOGI("frameTimeNanos: %d", frameTimeNanos); + static long frameIndex = 0; + if((frameIndex++) % 60 == 0) { + LOGI("frame diff: %d", frameTimeNanos - gPreviousFrameTimeNanos); + } AChoreographer *choreographer = AChoreographer_getInstance(); if (!choreographer) { LOGE("Couldn't get the choreographer from the frame callback"); @@ -690,6 +694,7 @@ static void frameCallbackImpl(long frameTimeNanos, void *data) { * @TODO - provide a way to signal graceful thread exit. */ static void choreographerThreadRun() { + LOGI("On Choreographer thread"); ALooper *looper = ALooper_forThread(); if (!looper) { looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); @@ -959,38 +964,38 @@ static GLuint createTexture(GLuint width, GLuint height) { return ret; } -static void updateTexture(GLuint width, GLuint height, GLubyte *data) { +// static void updateTexture(GLuint width, GLuint height, GLubyte *data) { - glBindTexture(GL_TEXTURE_2D, gTextureID); - checkGlError("glBindTexture"); +// glBindTexture(GL_TEXTURE_2D, gTextureID); +// checkGlError("glBindTexture"); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_PACK_ALIGNMENT, 1); +// glPixelStorei(GL_UNPACK_ALIGNMENT, 1); +// glPixelStorei(GL_PACK_ALIGNMENT, 1); - // @todo use glTexSubImage2D to be faster here, but add check to make sure - // height/width are the same. - // glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, - // GL_UNSIGNED_BYTE, data); - // checkGlError("glTexSubImage2D"); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, - GL_UNSIGNED_BYTE, data); - checkGlError("glTexImage2D"); -} +// // @todo use glTexSubImage2D to be faster here, but add check to make sure +// // height/width are the same. +// // glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, +// // GL_UNSIGNED_BYTE, data); +// // checkGlError("glTexSubImage2D"); +// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, +// GL_UNSIGNED_BYTE, data); +// checkGlError("glTexImage2D"); +// } -static void imagingCallback(void *userdata, const OSVR_TimeValue *timestamp, - const OSVR_ImagingReport *report) { +// static void imagingCallback(void *userdata, const OSVR_TimeValue *timestamp, +// const OSVR_ImagingReport *report) { - OSVR_ClientContext *ctx = (OSVR_ClientContext *)userdata; +// OSVR_ClientContext *ctx = (OSVR_ClientContext *)userdata; - gReportNumber++; - GLuint width = report->state.metadata.width; - GLuint height = report->state.metadata.height; - gLastFrameWidth = width; - gLastFrameHeight = height; - GLuint size = width * height * 4; +// gReportNumber++; +// GLuint width = report->state.metadata.width; +// GLuint height = report->state.metadata.height; +// gLastFrameWidth = width; +// gLastFrameHeight = height; +// GLuint size = width * height * 4; - gLastFrame = report->state.data; -} +// gLastFrame = report->state.data; +// } #if SUPPORT_OPENGL inline GLuint GetEyeTextureOpenGL(int eye) { return (eye == 0) ? gLeftEyeTextureID : gRightEyeTextureID; @@ -1109,7 +1114,7 @@ static bool setupOSVR() { // workingDirectory.string().c_str()); // auto-start the server - osvrClientAttemptServerAutoStart(); + //osvrClientAttemptServerAutoStart(); if (!gClientContext) { // LOGI("[OSVR] Creating ClientContext..."); @@ -1204,148 +1209,148 @@ static bool setupRenderManager() { return false; } } -static const GLfloat gTriangleColors[] = { - // white - 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, - - // green - 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, - 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, - - // blue - 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - - // green/purple - 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, - 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, - - // red/green - 0.75f, 0.75f, 0.0f, 1.0f, 0.75f, 0.75f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, - 0.75f, 0.75f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, - - // red/blue - 0.75f, 0.0f, 0.75f, 1.0f, 0.75f, 0.0f, 0.75f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 0.75f, 0.0f, 0.75f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f}; - -static const GLfloat gTriangleTexCoordinates[] = { - // A cube face (letters are unique vertices) - // A--B - // | | - // D--C - - // As two triangles (clockwise) - // A B D - // B C D - - // white - 1.0f, 0.0f, // A - 1.0f, 1.0f, // B - 0.0f, 0.0f, // D - 1.0f, 1.0f, // B - 0.0f, 1.0f, // C - 0.0f, 0.0f, // D - - // green - 1.0f, 0.0f, // A - 1.0f, 1.0f, // B - 0.0f, 0.0f, // D - 1.0f, 1.0f, // B - 0.0f, 1.0f, // C - 0.0f, 0.0f, // D - - // blue - 1.0f, 1.0f, // A - 0.0f, 1.0f, // B - 1.0f, 0.0f, // D - 0.0f, 1.0f, // B - 0.0f, 0.0f, // C - 1.0f, 0.0f, // D - - // blue-green - 1.0f, 0.0f, // A - 1.0f, 1.0f, // B - 0.0f, 0.0f, // D - 1.0f, 1.0f, // B - 0.0f, 1.0f, // C - 0.0f, 0.0f, // D - - // yellow - 0.0f, 0.0f, // A - 1.0f, 0.0f, // B - 0.0f, 1.0f, // D - 1.0f, 0.0f, // B - 1.0f, 1.0f, // C - 0.0f, 1.0f, // D - - // purple/magenta - 1.0f, 1.0f, // A - 0.0f, 1.0f, // B - 1.0f, 0.0f, // D - 0.0f, 1.0f, // B - 0.0f, 0.0f, // C - 1.0f, 0.0f, // D -}; - -static const GLfloat gTriangleVertices[] = { - // A cube face (letters are unique vertices) - // A--B - // | | - // D--C - - // As two triangles (clockwise) - // A B D - // B C D - - // glNormal3f(0.0, 0.0, -1.0); - 1.0f, 1.0f, -1.0f, // A - 1.0f, -1.0f, -1.0f, // B - -1.0f, 1.0f, -1.0f, // D - 1.0f, -1.0f, -1.0f, // B - -1.0f, -1.0f, -1.0f, // C - -1.0f, 1.0f, -1.0f, // D - - // glNormal3f(0.0, 0.0, 1.0); - -1.0f, 1.0f, 1.0f, // A - -1.0f, -1.0f, 1.0f, // B - 1.0f, 1.0f, 1.0f, // D - -1.0f, -1.0f, 1.0f, // B - 1.0f, -1.0f, 1.0f, // C - 1.0f, 1.0f, 1.0f, // D - - // glNormal3f(0.0, -1.0, 0.0); - 1.0f, -1.0f, 1.0f, // A - -1.0f, -1.0f, 1.0f, // B - 1.0f, -1.0f, -1.0f, // D - -1.0f, -1.0f, 1.0f, // B - -1.0f, -1.0f, -1.0f, // C - 1.0f, -1.0f, -1.0f, // D - - // glNormal3f(0.0, 1.0, 0.0); - 1.0f, 1.0f, 1.0f, // A - 1.0f, 1.0f, -1.0f, // B - -1.0f, 1.0f, 1.0f, // D - 1.0f, 1.0f, -1.0f, // B - -1.0f, 1.0f, -1.0f, // C - -1.0f, 1.0f, 1.0f, // D - - // glNormal3f(-1.0, 0.0, 0.0); - -1.0f, 1.0f, 1.0f, // A - -1.0f, 1.0f, -1.0f, // B - -1.0f, -1.0f, 1.0f, // D - -1.0f, 1.0f, -1.0f, // B - -1.0f, -1.0f, -1.0f, // C - -1.0f, -1.0f, 1.0f, // D - - // glNormal3f(1.0, 0.0, 0.0); - 1.0f, -1.0f, 1.0f, // A - 1.0f, -1.0f, -1.0f, // B - 1.0f, 1.0f, 1.0f, // D - 1.0f, -1.0f, -1.0f, // B - 1.0f, 1.0f, -1.0f, // C - 1.0f, 1.0f, 1.0f // D -}; +// static const GLfloat gTriangleColors[] = { +// // white +// 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, +// 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + +// // green +// 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, +// 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, + +// // blue +// 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, +// 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + +// // green/purple +// 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, +// 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, + +// // red/green +// 0.75f, 0.75f, 0.0f, 1.0f, 0.75f, 0.75f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, +// 0.75f, 0.75f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, + +// // red/blue +// 0.75f, 0.0f, 0.75f, 1.0f, 0.75f, 0.0f, 0.75f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, +// 0.75f, 0.0f, 0.75f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f}; + +// static const GLfloat gTriangleTexCoordinates[] = { +// // A cube face (letters are unique vertices) +// // A--B +// // | | +// // D--C + +// // As two triangles (clockwise) +// // A B D +// // B C D + +// // white +// 1.0f, 0.0f, // A +// 1.0f, 1.0f, // B +// 0.0f, 0.0f, // D +// 1.0f, 1.0f, // B +// 0.0f, 1.0f, // C +// 0.0f, 0.0f, // D + +// // green +// 1.0f, 0.0f, // A +// 1.0f, 1.0f, // B +// 0.0f, 0.0f, // D +// 1.0f, 1.0f, // B +// 0.0f, 1.0f, // C +// 0.0f, 0.0f, // D + +// // blue +// 1.0f, 1.0f, // A +// 0.0f, 1.0f, // B +// 1.0f, 0.0f, // D +// 0.0f, 1.0f, // B +// 0.0f, 0.0f, // C +// 1.0f, 0.0f, // D + +// // blue-green +// 1.0f, 0.0f, // A +// 1.0f, 1.0f, // B +// 0.0f, 0.0f, // D +// 1.0f, 1.0f, // B +// 0.0f, 1.0f, // C +// 0.0f, 0.0f, // D + +// // yellow +// 0.0f, 0.0f, // A +// 1.0f, 0.0f, // B +// 0.0f, 1.0f, // D +// 1.0f, 0.0f, // B +// 1.0f, 1.0f, // C +// 0.0f, 1.0f, // D + +// // purple/magenta +// 1.0f, 1.0f, // A +// 0.0f, 1.0f, // B +// 1.0f, 0.0f, // D +// 0.0f, 1.0f, // B +// 0.0f, 0.0f, // C +// 1.0f, 0.0f, // D +// }; + +// static const GLfloat gTriangleVertices[] = { +// // A cube face (letters are unique vertices) +// // A--B +// // | | +// // D--C + +// // As two triangles (clockwise) +// // A B D +// // B C D + +// // glNormal3f(0.0, 0.0, -1.0); +// 1.0f, 1.0f, -1.0f, // A +// 1.0f, -1.0f, -1.0f, // B +// -1.0f, 1.0f, -1.0f, // D +// 1.0f, -1.0f, -1.0f, // B +// -1.0f, -1.0f, -1.0f, // C +// -1.0f, 1.0f, -1.0f, // D + +// // glNormal3f(0.0, 0.0, 1.0); +// -1.0f, 1.0f, 1.0f, // A +// -1.0f, -1.0f, 1.0f, // B +// 1.0f, 1.0f, 1.0f, // D +// -1.0f, -1.0f, 1.0f, // B +// 1.0f, -1.0f, 1.0f, // C +// 1.0f, 1.0f, 1.0f, // D + +// // glNormal3f(0.0, -1.0, 0.0); +// 1.0f, -1.0f, 1.0f, // A +// -1.0f, -1.0f, 1.0f, // B +// 1.0f, -1.0f, -1.0f, // D +// -1.0f, -1.0f, 1.0f, // B +// -1.0f, -1.0f, -1.0f, // C +// 1.0f, -1.0f, -1.0f, // D + +// // glNormal3f(0.0, 1.0, 0.0); +// 1.0f, 1.0f, 1.0f, // A +// 1.0f, 1.0f, -1.0f, // B +// -1.0f, 1.0f, 1.0f, // D +// 1.0f, 1.0f, -1.0f, // B +// -1.0f, 1.0f, -1.0f, // C +// -1.0f, 1.0f, 1.0f, // D + +// // glNormal3f(-1.0, 0.0, 0.0); +// -1.0f, 1.0f, 1.0f, // A +// -1.0f, 1.0f, -1.0f, // B +// -1.0f, -1.0f, 1.0f, // D +// -1.0f, 1.0f, -1.0f, // B +// -1.0f, -1.0f, -1.0f, // C +// -1.0f, -1.0f, 1.0f, // D + +// // glNormal3f(1.0, 0.0, 0.0); +// 1.0f, -1.0f, 1.0f, // A +// 1.0f, -1.0f, -1.0f, // B +// 1.0f, 1.0f, 1.0f, // D +// 1.0f, -1.0f, -1.0f, // B +// 1.0f, 1.0f, -1.0f, // C +// 1.0f, 1.0f, 1.0f // D +// }; static bool setupGraphics(int width, int height) { // printGLString("Version", GL_VERSION); @@ -1365,55 +1370,55 @@ static bool setupGraphics(int width, int height) { // bool osvrSetupSuccess = setupOSVR(); - gProgram = createProgram(gVertexShader, gFragmentShader); - if (!gProgram) { - // LOGE("Could not create program."); - osvrJniWrapperClass = jniEnvironment->FindClass( - "org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class - if (osvrJniWrapperClass == nullptr) { - return false; - } else { // if class found, continue - - jmethodID logmid = jniEnvironment->GetStaticMethodID( - osvrJniWrapperClass, "logMsg", - "(Ljava/lang/String;)V"); // find method - std::string stringy = - "[OSVR-Unity-Android] Could not create program."; - jstring jstr2 = jniEnvironment->NewStringUTF(stringy.c_str()); - jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, logmid, - jstr2); - } - return false; - } - gvPositionHandle = glGetAttribLocation(gProgram, "vPosition"); - checkGlError("glGetAttribLocation"); - // LOGI("glGetAttribLocation(\"vPosition\") = %d\n", gvPositionHandle); - - gvColorHandle = glGetAttribLocation(gProgram, "vColor"); - checkGlError("glGetAttribLocation"); - // LOGI("glGetAttribLocation(\"vColor\") = %d\n", gvColorHandle); - - gvTexCoordinateHandle = glGetAttribLocation(gProgram, "vTexCoordinate"); - checkGlError("glGetAttribLocation"); - // LOGI("glGetAttribLocation(\"vTexCoordinate\") = %d\n", - // gvTexCoordinateHandle); - - gvProjectionUniformId = glGetUniformLocation(gProgram, "projection"); - gvViewUniformId = glGetUniformLocation(gProgram, "view"); - gvModelUniformId = glGetUniformLocation(gProgram, "model"); - guTextureUniformId = glGetUniformLocation(gProgram, "uTexture"); - - glViewport(0, 0, width, height); - checkGlError("glViewport"); - - glDisable(GL_CULL_FACE); + // gProgram = createProgram(gVertexShader, gFragmentShader); + // if (!gProgram) { + // // LOGE("Could not create program."); + // osvrJniWrapperClass = jniEnvironment->FindClass( + // "org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class + // if (osvrJniWrapperClass == nullptr) { + // return false; + // } else { // if class found, continue + + // jmethodID logmid = jniEnvironment->GetStaticMethodID( + // osvrJniWrapperClass, "logMsg", + // "(Ljava/lang/String;)V"); // find method + // std::string stringy = + // "[OSVR-Unity-Android] Could not create program."; + // jstring jstr2 = jniEnvironment->NewStringUTF(stringy.c_str()); + // jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, logmid, + // jstr2); + // } + // return false; + // } + // gvPositionHandle = glGetAttribLocation(gProgram, "vPosition"); + // checkGlError("glGetAttribLocation"); + // // LOGI("glGetAttribLocation(\"vPosition\") = %d\n", gvPositionHandle); + + // gvColorHandle = glGetAttribLocation(gProgram, "vColor"); + // checkGlError("glGetAttribLocation"); + // // LOGI("glGetAttribLocation(\"vColor\") = %d\n", gvColorHandle); + + // gvTexCoordinateHandle = glGetAttribLocation(gProgram, "vTexCoordinate"); + // checkGlError("glGetAttribLocation"); + // // LOGI("glGetAttribLocation(\"vTexCoordinate\") = %d\n", + // // gvTexCoordinateHandle); + + // gvProjectionUniformId = glGetUniformLocation(gProgram, "projection"); + // gvViewUniformId = glGetUniformLocation(gProgram, "view"); + // gvModelUniformId = glGetUniformLocation(gProgram, "model"); + // guTextureUniformId = glGetUniformLocation(gProgram, "uTexture"); + + // glViewport(0, 0, width, height); + // checkGlError("glViewport"); + + //glDisable(GL_CULL_FACE); // @todo can we resize the texture after it has been created? // if not, we may have to delete the dummy one and create a new one after // the first imaging report. // LOGI("Creating texture... here we go!"); - gTextureID = createTexture(width, height); + //gTextureID = createTexture(width, height); // return osvrSetupSuccess; gGraphicsInitializedOnce = true; @@ -1439,19 +1444,19 @@ static void renderFrame() { OSVR_ReturnCode rc; - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - checkGlError("glClearColor"); - glViewport(0, 0, gWidth, gHeight); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - checkGlError("glClear"); + // glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + // checkGlError("glClearColor"); + // glViewport(0, 0, gWidth, gHeight); + // glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + // checkGlError("glClear"); if (gRenderManager && gClientContext) { osvrClientUpdate(gClientContext); - if (gLastFrame != nullptr) { - updateTexture(gLastFrameWidth, gLastFrameHeight, gLastFrame); - osvrClientFreeImage(gClientContext, gLastFrame); - gLastFrame = nullptr; - } + // if (gLastFrame != nullptr) { + // updateTexture(gLastFrameWidth, gLastFrameHeight, gLastFrame); + // osvrClientFreeImage(gClientContext, gLastFrame); + // gLastFrame = nullptr; + // } OSVR_RenderParams renderParams; rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); @@ -1516,7 +1521,7 @@ static void stop() { gClientContext = nullptr; } - osvrClientReleaseAutoStartedServer(); + //osvrClientReleaseAutoStartedServer(); } OSVR_ReturnCode CreateRenderManagerAndroid(OSVR_ClientContext context) { From 74431766ab3c25176c6ea86bef226002119257ed Mon Sep 17 00:00:00 2001 From: JeroMiya Date: Wed, 9 Aug 2017 12:22:20 -0400 Subject: [PATCH 35/43] Removed commented out code, plus more cleanup. Refactored render info collection code in the android branch to work similarly to the windows branch. Also fixed some link issues in the cmake for newer NDK API level targets, which fixes EntryPointNotFound exceptions. --- CMakeLists.txt | 16 +- OsvrRenderingPlugin.cpp | 821 ++++++++-------------------------------- 2 files changed, 177 insertions(+), 660 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 830056e..9eca44f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,15 @@ if(WIN32) # list(APPEND osvrUnityRenderingPlugin_SOURCES OsvrRenderingPlugin.def) endif() -add_library(osvrUnityRenderingPlugin MODULE ${osvrUnityRenderingPlugin_SOURCES}) +set(EXTRA_ANDROID_LINKER_FLAGS "") + +if(ANDROID) + add_library(osvrUnityRenderingPlugin SHARED ${osvrUnityRenderingPlugin_SOURCES}) + set(EXTRA_ANDROID_LINKER_FLAGS "log -z global") +else() + add_library(osvrUnityRenderingPlugin MODULE ${osvrUnityRenderingPlugin_SOURCES}) +endif() + #set_target_properties(osvrUnityRenderingPlugin PROPERTIES LINK_FLAGS "/DEF:${CMAKE_CURRENT_SOURCE_DIR}/OsvrRenderingPlugin.def") #target_link_libraries(osvrUnityRenderingPlugin osvr::osvrClientKit) #target_link_libraries(osvrUnityRenderingPlugin osvrRenderManager::osvrRenderManager) @@ -48,7 +56,7 @@ target_include_directories(osvrUnityRenderingPlugin PRIVATE ${Boost_INCLUDE_DIRS if (OPENGL_FOUND AND GLEW_FOUND) target_include_directories(osvrUnityRenderingPlugin PRIVATE ${OPENGL_INCLUDE_DIRS}) - target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} GLEW::GLEW JsonCpp::JsonCpp SDL2::SDL2 osvr::osvrClientKit osvrRenderManager::osvrRenderManager) + target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} GLEW::GLEW JsonCpp::JsonCpp SDL2::SDL2 osvr::osvrClientKit osvrRenderManager::osvrRenderManager ${EXTRA_ANDROID_LINKER_FLAGS}) # Handle static glew. if(GLEW_LIBRARY MATCHES ".*s.lib") target_compile_definitions(osvrUnityRenderingPlugin PRIVATE GLEW_STATIC) @@ -56,11 +64,11 @@ if (OPENGL_FOUND AND GLEW_FOUND) endif() if (OPENGL_FOUND) target_include_directories(osvrUnityRenderingPlugin PRIVATE ${OPENGL_INCLUDE_DIRS}) - target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} JsonCpp::JsonCpp osvr::osvrClientKit osvrRenderManager::osvrRenderManager) + target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} JsonCpp::JsonCpp osvr::osvrClientKit osvrRenderManager::osvrRenderManager ${EXTRA_ANDROID_LINKER_FLAGS}) endif() if(OPENGLES2_FOUND) target_include_directories(osvrUnityRenderingPlugin PRIVATE ${OPENGLES2_INCLUDE_DIR}) - target_link_libraries(osvrUnityRenderingPlugin PRIVATE ${OPENGLES2_LIBRARIES} JsonCpp::JsonCpp osvr::osvrClientKit osvrRenderManager::osvrRenderManager) + target_link_libraries(osvrUnityRenderingPlugin PRIVATE ${OPENGLES2_LIBRARIES} JsonCpp::JsonCpp osvr::osvrClientKit osvrRenderManager::osvrRenderManager ${EXTRA_ANDROID_LINKER_FLAGS}) endif() # Install docs, license, sample config diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 5c0d329..1d6581c 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -99,8 +99,8 @@ Sensics, Inc. #if OSVR_ANDROID #include -#include -#include +// #include +// #include #define LOG_TAG "osvrUnityRendering" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) @@ -124,6 +124,16 @@ static double s_ipd = 0.063; static std::uint32_t viewportWidth = 0; static std::uint32_t viewportHeight = 0; +static OSVR_RenderManager s_render = nullptr; +static OSVR_RenderParams s_renderParams; +static std::vector s_renderInfo; +static std::vector s_lastRenderInfo; +static OSVR_RenderInfoCount numRenderInfo; +static OSVR_RenderInfoCollection s_renderInfoCollection; +static OSVR_ProjectionMatrix lastGoodProjMatrix; +static OSVR_Pose3 lastGoodPose; +static OSVR_ViewportDescription lastGoodViewportDescription; + #if UNITY_ANDROID static JNIEnv *jniEnvironment = 0; static jclass osvrJniWrapperClass; @@ -132,16 +142,7 @@ static jobject unityActivityClassInstance; static int gWidth = 0; static int gHeight = 0; -//static GLuint gProgram; -//static GLuint gvPositionHandle; -//static GLuint gvColorHandle; -//static GLuint gvTexCoordinateHandle; -//static GLuint guTextureUniformId; -//static GLuint gvProjectionUniformId; -//static GLuint gvViewUniformId; -//static GLuint gvModelUniformId; static GLuint gFrameBuffer; -//static GLuint gTextureID; static GLuint gLeftEyeTextureID; static GLuint gRightEyeTextureID; static bool gGraphicsInitializedOnce = @@ -155,48 +156,16 @@ typedef struct OSVR_RenderTargetInfo { GLuint frameBufferName; GLuint renderBufferName; // @todo - do we need this? } OSVR_RenderTargetInfo; + static OSVR_ClientContext gClientContext = NULL; -//static OSVR_ClientInterface gCamera = NULL; -//static OSVR_ClientInterface gHead = NULL; -//static int gReportNumber = 0; -//static OSVR_ImageBufferElement *gLastFrame = nullptr; -//static GLuint gLastFrameWidth = 0; -//static GLuint gLastFrameHeight = 0; static GLubyte *gTextureBuffer = nullptr; static OSVR_GraphicsLibraryOpenGL gGraphicsLibrary = {0}; -static OSVR_RenderManager gRenderManager = nullptr; static OSVR_RenderManagerOpenGL gRenderManagerOGL = nullptr; static OSVR_RenderParams gRenderParams = {0}; static std::vector buffers; static std::vector gRenderTargets; static bool contextSet = false; -static const char gVertexShader[] = - "uniform mat4 model;\n" - "uniform mat4 view;\n" - "uniform mat4 projection;\n" - "attribute vec4 vPosition;\n" - "attribute vec4 vColor;\n" - "attribute vec2 vTexCoordinate;\n" - "varying vec2 texCoordinate;\n" - "varying vec4 fragmentColor;\n" - "void main() {\n" - " gl_Position = projection * view * model * vPosition;\n" - " fragmentColor = vColor;\n" - " texCoordinate = vTexCoordinate;\n" - "}\n"; - -static const char gFragmentShader[] = - "precision mediump float;\n" - "uniform sampler2D uTexture;\n" - "varying vec2 texCoordinate;\n" - "varying vec4 fragmentColor;\n" - "void main()\n" - "{\n" - " gl_FragColor = fragmentColor * texture2D(uTexture, texCoordinate);\n" - //" gl_FragColor = texture2D(uTexture, texCoordinate);\n" - "}\n"; - inline void nanoSecondsToTimeValue(uint64_t nanos, OSVR_TimeValue *tvOut) { tvOut->seconds = 0; tvOut->microseconds = nanos / 1000; @@ -204,21 +173,14 @@ inline void nanoSecondsToTimeValue(uint64_t nanos, OSVR_TimeValue *tvOut) { } #else // Windows, Linux, OSX static variables -static OSVR_RenderParams s_renderParams; -static OSVR_RenderManager s_render = nullptr; + static OSVR_RenderManagerD3D11 s_renderD3D = nullptr; static OSVR_ClientContext s_clientContext = nullptr; static std::vector s_renderBuffers; static std::vector s_renderInfo; static std::vector s_lastRenderInfo; -static OSVR_RenderInfoCount numRenderInfo; -static OSVR_RenderInfoCollection s_renderInfoCollection; static OSVR_GraphicsLibraryD3D11 s_libraryD3D; -static OSVR_ProjectionMatrix lastGoodProjMatrix; -static OSVR_Pose3 lastGoodPose; -static OSVR_ViewportDescription lastGoodViewportDescription; - // logging #if defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) static std::ofstream s_debugLogFile; @@ -509,8 +471,10 @@ void UNITY_INTERFACE_API UnityPluginUnload() { #endif // UNITY_WIN } -#if UNITY_WIN inline void UpdateRenderInfoCollection() { +#if !UNITY_WIN && !UNITY_ANDROID + return; +#endif if ((OSVR_RETURN_SUCCESS != osvrRenderManagerGetRenderInfoCollection(s_render, s_renderParams, &s_renderInfoCollection))) { @@ -524,19 +488,28 @@ inline void UpdateRenderInfoCollection() { // update renderinfo s_renderInfo.clear(); for (OSVR_RenderInfoCount i = 0; i < numRenderInfo; i++) { +#if UNITY_WIN OSVR_RenderInfoD3D11 info; if ((OSVR_RETURN_SUCCESS != osvrRenderManagerGetRenderInfoFromCollectionD3D11( s_renderInfoCollection, i, &info))) { - DebugLog("[OSVR Rendering Plugin] Could not get render info."); + DebugLog("[OSVR Rendering Plugin] Could not get render info (D3D11)."); + } +#elif UNITY_ANDROID // UNITY_WIN + OSVR_RenderInfoOpenGL info; + if ((OSVR_RETURN_SUCCESS != + osvrRenderManagerGetRenderInfoFromCollectionOpenGL( + s_renderInfoCollection, i, &info))) { + DebugLog("[OSVR Rendering Plugin] Could not get render info (OpenGL)."); } +#endif + s_renderInfo.push_back(info); } if (numRenderInfo > 0) { s_lastRenderInfo = s_renderInfo; } } -#endif // UNITY_WIN // Updates the internal "room to world" transformation (applied to all // tracker data for this client context instance) based on the user's head @@ -577,56 +550,6 @@ static void checkReturnCode(OSVR_ReturnCode returnCode, const char *msg) { throw std::runtime_error(msg); } } -// RAII wrapper around the RenderManager collection APIs for OpenGL -class RenderInfoCollectionOpenGL { - private: - OSVR_RenderManager mRenderManager = nullptr; - OSVR_RenderInfoCollection mRenderInfoCollection = nullptr; - OSVR_RenderParams mRenderParams = {0}; - - public: - RenderInfoCollectionOpenGL(OSVR_RenderManager renderManager, - OSVR_RenderParams renderParams) - : mRenderManager(renderManager), mRenderParams(renderParams) { - OSVR_ReturnCode rc; - rc = osvrRenderManagerGetRenderInfoCollection( - mRenderManager, mRenderParams, &mRenderInfoCollection); - checkReturnCode( - rc, "osvrRenderManagerGetRenderInfoCollection call failed."); - } - - OSVR_RenderInfoCount getNumRenderInfo() { - OSVR_RenderInfoCount ret; - OSVR_ReturnCode rc; - rc = osvrRenderManagerGetNumRenderInfoInCollection( - mRenderInfoCollection, &ret); - checkReturnCode( - rc, "osvrRenderManagerGetNumRenderInfoInCollection call failed."); - return ret; - } - - OSVR_RenderInfoOpenGL getRenderInfo(OSVR_RenderInfoCount index) { - if (index < 0 || index >= getNumRenderInfo()) { - const static char *err = "getRenderInfo called with invalid index"; - // LOGE(err); - throw std::runtime_error(err); - } - OSVR_RenderInfoOpenGL ret; - OSVR_ReturnCode rc; - rc = osvrRenderManagerGetRenderInfoFromCollectionOpenGL( - mRenderInfoCollection, index, &ret); - checkReturnCode( - rc, - "osvrRenderManagerGetRenderInfoFromCollectionOpenGL call failed."); - return ret; - } - - ~RenderInfoCollectionOpenGL() { - if (mRenderInfoCollection) { - osvrRenderManagerReleaseRenderInfoCollection(mRenderInfoCollection); - } - } -}; static void checkGlError(const char *op) { std::stringstream ss; @@ -660,77 +583,77 @@ static void checkGlError(const char *op) { } } -#if OSVR_ANDROID -static long gPreviousFrameTimeNanos = 0; -static long gLastFrameTimeNanos = 0; -static std::mutex gFrameTimeMutex; - -/** - * This func is called on an app frame callback by the - * Choreographer on Android. - * NOTE: This is offset from the real "last vsync" when the - * Android build has offset. @todo account for this offset using JNI. - */ -static void frameCallbackImpl(long frameTimeNanos, void *data) { - std::lock_guard lockGuard(gFrameTimeMutex); - gPreviousFrameTimeNanos = gLastFrameTimeNanos; - gLastFrameTimeNanos = frameTimeNanos; - /// LOGI("frameTimeNanos: %d", frameTimeNanos); - static long frameIndex = 0; - if((frameIndex++) % 60 == 0) { - LOGI("frame diff: %d", frameTimeNanos - gPreviousFrameTimeNanos); - } - AChoreographer *choreographer = AChoreographer_getInstance(); - if (!choreographer) { - LOGE("Couldn't get the choreographer from the frame callback"); - } - AChoreographer_postFrameCallback(choreographer, frameCallbackImpl, nullptr); -} - -/** - * Use this function in a std::thread to keep the ALooper pumping AChoreographer - * callbacks on a separate thread from where it's consumed. Otherwise the polling - * here will stall the render thread. - * @TODO - provide a way to signal graceful thread exit. - */ -static void choreographerThreadRun() { - LOGI("On Choreographer thread"); - ALooper *looper = ALooper_forThread(); - if (!looper) { - looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); - if (!looper) { - LOGE("Couldn't prepare an ALooper for the choreographer thread"); - return; - } - } - - AChoreographer *choreographer = AChoreographer_getInstance(); - if (!choreographer) { - LOGE("Could not get choreographer."); - return; - } - - AChoreographer_postFrameCallback(choreographer, frameCallbackImpl, nullptr); +// #if OSVR_ANDROID +// static long gPreviousFrameTimeNanos = 0; +// static long gLastFrameTimeNanos = 0; +// static std::mutex gFrameTimeMutex; + +// /** +// * This func is called on an app frame callback by the +// * Choreographer on Android. +// * NOTE: This is offset from the real "last vsync" when the +// * Android build has offset. @todo account for this offset using JNI. +// */ +// static void frameCallbackImpl(long frameTimeNanos, void *data) { +// std::lock_guard lockGuard(gFrameTimeMutex); +// gPreviousFrameTimeNanos = gLastFrameTimeNanos; +// gLastFrameTimeNanos = frameTimeNanos; +// /// LOGI("frameTimeNanos: %d", frameTimeNanos); +// static long frameIndex = 0; +// if((frameIndex++) % 60 == 0) { +// LOGI("frame diff: %d", frameTimeNanos - gPreviousFrameTimeNanos); +// } +// AChoreographer *choreographer = AChoreographer_getInstance(); +// if (!choreographer) { +// LOGE("Couldn't get the choreographer from the frame callback"); +// } +// AChoreographer_postFrameCallback(choreographer, frameCallbackImpl, nullptr); +// } - while (true) { - // @TODO provide a signal for graceful thread exit? - int fd_unused = 0; - int outEvents_unused = 0; - void *outData_unused = nullptr; - int rc = ALooper_pollAll(100, &fd_unused, &outEvents_unused, - &outData_unused); - } -} -#endif +// /** +// * Use this function in a std::thread to keep the ALooper pumping AChoreographer +// * callbacks on a separate thread from where it's consumed. Otherwise the polling +// * here will stall the render thread. +// * @TODO - provide a way to signal graceful thread exit. +// */ +// static void choreographerThreadRun() { +// LOGI("On Choreographer thread"); +// ALooper *looper = ALooper_forThread(); +// if (!looper) { +// looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); +// if (!looper) { +// LOGE("Couldn't prepare an ALooper for the choreographer thread"); +// return; +// } +// } + +// AChoreographer *choreographer = AChoreographer_getInstance(); +// if (!choreographer) { +// LOGE("Could not get choreographer."); +// return; +// } + +// AChoreographer_postFrameCallback(choreographer, frameCallbackImpl, nullptr); + +// while (true) { +// // @TODO provide a signal for graceful thread exit? +// int fd_unused = 0; +// int outEvents_unused = 0; +// void *outData_unused = nullptr; +// int rc = ALooper_pollAll(100, &fd_unused, &outEvents_unused, +// &outData_unused); +// } +// } +// #endif class PassThroughOpenGLContextImpl { OSVR_OpenGLToolkitFunctions toolkit; int mWidth; int mHeight; -#if OSVR_ANDROID - std::thread mChoreographerThread; -#endif +// #if OSVR_ANDROID +// std::thread mChoreographerThread; +// #endif static void createImpl(void *data) {} static void destroyImpl(void *data) { @@ -772,11 +695,11 @@ class PassThroughOpenGLContextImpl { } public: -#if OSVR_ANDROID - PassThroughOpenGLContextImpl() : mChoreographerThread(choreographerThreadRun) { -#else +// #if OSVR_ANDROID +// PassThroughOpenGLContextImpl() : mChoreographerThread(choreographerThreadRun) { +// #else PassThroughOpenGLContextImpl() { -#endif +// #endif memset(&toolkit, 0, sizeof(toolkit)); toolkit.size = sizeof(toolkit); toolkit.data = this; @@ -823,179 +746,42 @@ class PassThroughOpenGLContextImpl { bool getRenderTimingInfo(size_t display, size_t whichEye, OSVR_RenderTimingInfo *renderTimingInfoOut) { -#if OSVR_ANDROID - timespec tp; - int rv = clock_gettime(CLOCK_MONOTONIC, &tp); - if (!rv) { - std::lock_guard lockGuard(gFrameTimeMutex); - // uint64_t presentationDeadline = 17683333L; // Shouldn't this bee - // at least less than 16,666,666? (1 billion / 60) - // that's 1,016,666 nanoseconds greater than the hardware interval - // uint64_t hardwareDisplayIntervalNanos = 11111111L; // 90Hz hard - // coded, TODO measure this or get it from the API? - uint64_t hardwareDisplayIntervalNanos = gLastFrameTimeNanos - gPreviousFrameTimeNanos; - uint64_t nowNanos = ((tp.tv_sec * 1000000000L) + tp.tv_nsec); - uint64_t timeFromLastNanos = nowNanos >= gLastFrameTimeNanos - ? nowNanos - gLastFrameTimeNanos - : 0; // just being safe - uint64_t nextNanos = gLastFrameTimeNanos + hardwareDisplayIntervalNanos; - uint64_t timeUntilNextNanos = - nextNanos >= nowNanos ? nextNanos - nowNanos - : 0; // 0 here means we missed a vsync - - nanoSecondsToTimeValue(timeFromLastNanos, - &renderTimingInfoOut->timeSincelastVerticalRetrace); +// #if OSVR_ANDROID +// timespec tp; +// int rv = clock_gettime(CLOCK_MONOTONIC, &tp); +// if (!rv) { +// std::lock_guard lockGuard(gFrameTimeMutex); +// // uint64_t presentationDeadline = 17683333L; // Shouldn't this bee +// // at least less than 16,666,666? (1 billion / 60) +// // that's 1,016,666 nanoseconds greater than the hardware interval +// // uint64_t hardwareDisplayIntervalNanos = 11111111L; // 90Hz hard +// // coded, TODO measure this or get it from the API? +// uint64_t hardwareDisplayIntervalNanos = gLastFrameTimeNanos - gPreviousFrameTimeNanos; +// uint64_t nowNanos = ((tp.tv_sec * 1000000000L) + tp.tv_nsec); +// uint64_t timeFromLastNanos = nowNanos >= gLastFrameTimeNanos +// ? nowNanos - gLastFrameTimeNanos +// : 0; // just being safe +// uint64_t nextNanos = gLastFrameTimeNanos + hardwareDisplayIntervalNanos; +// uint64_t timeUntilNextNanos = +// nextNanos >= nowNanos ? nextNanos - nowNanos +// : 0; // 0 here means we missed a vsync + +// nanoSecondsToTimeValue(timeFromLastNanos, +// &renderTimingInfoOut->timeSincelastVerticalRetrace); - nanoSecondsToTimeValue(timeUntilNextNanos, - &renderTimingInfoOut->timeUntilNextPresentRequired); - - nanoSecondsToTimeValue(hardwareDisplayIntervalNanos, - &renderTimingInfoOut->hardwareDisplayInterval); - return true; - } - LOGI("clock_gettime call failed."); -#endif +// nanoSecondsToTimeValue(timeUntilNextNanos, +// &renderTimingInfoOut->timeUntilNextPresentRequired); + +// nanoSecondsToTimeValue(hardwareDisplayIntervalNanos, +// &renderTimingInfoOut->hardwareDisplayInterval); +// return true; +// } +// LOGI("clock_gettime call failed."); +// #endif return false; } }; -static GLuint loadShader(GLenum shaderType, const char *pSource) { - GLuint shader = glCreateShader(shaderType); - if (shader) { - glShaderSource(shader, 1, &pSource, NULL); - glCompileShader(shader); - GLint compiled = 0; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); - if (!compiled) { - GLint infoLen = 0; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); - if (infoLen) { - char *buf = (char *)malloc(infoLen); - if (buf) { - glGetShaderInfoLog(shader, infoLen, NULL, buf); - // LOGE("Could not compile shader %d:\n%s\n", - // shaderType, buf); - free(buf); - } - glDeleteShader(shader); - shader = 0; - } - } - } - return shader; -} - -static GLuint createProgram(const char *pVertexSource, - const char *pFragmentSource) { - GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); - if (!vertexShader) { - return 0; - } - - GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); - if (!pixelShader) { - return 0; - } - - GLuint program = glCreateProgram(); - if (program) { - glAttachShader(program, vertexShader); - checkGlError("glAttachShader"); - - glAttachShader(program, pixelShader); - checkGlError("glAttachShader"); - - glBindAttribLocation(program, 0, "vPosition"); - glBindAttribLocation(program, 1, "vColor"); - glBindAttribLocation(program, 2, "vTexCoordinate"); - - glLinkProgram(program); - GLint linkStatus = GL_FALSE; - glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); - if (linkStatus != GL_TRUE) { - GLint bufLength = 0; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); - if (bufLength) { - char *buf = (char *)malloc(bufLength); - if (buf) { - glGetProgramInfoLog(program, bufLength, NULL, buf); - // LOGE("Could not link program:\n%s\n", buf); - free(buf); - } - } - glDeleteProgram(program); - program = 0; - } - } - return program; -} - -static GLuint createTexture(GLuint width, GLuint height) { - GLuint ret; - glGenTextures(1, &ret); - checkGlError("glGenTextures"); - - glBindTexture(GL_TEXTURE_2D, ret); - checkGlError("glBindTexture"); - - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - // // DEBUG CODE - should be passing null here, but then texture is - // always black. - GLubyte *dummyBuffer = new GLubyte[width * height * 4]; - for (GLuint i = 0; i < width * height * 4; i++) { - dummyBuffer[i] = (i % 4 ? 100 : 255); - } - - // This dummy texture successfully makes it into the texture and renders, - // but subsequent - // calls to glTexSubImage2D don't appear to do anything. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, - GL_UNSIGNED_BYTE, dummyBuffer); - checkGlError("glTexImage2D"); - delete[] dummyBuffer; - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - checkGlError("glTexParameteri"); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - checkGlError("glTexParameteri"); - return ret; -} - -// static void updateTexture(GLuint width, GLuint height, GLubyte *data) { - -// glBindTexture(GL_TEXTURE_2D, gTextureID); -// checkGlError("glBindTexture"); - -// glPixelStorei(GL_UNPACK_ALIGNMENT, 1); -// glPixelStorei(GL_PACK_ALIGNMENT, 1); - -// // @todo use glTexSubImage2D to be faster here, but add check to make sure -// // height/width are the same. -// // glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, -// // GL_UNSIGNED_BYTE, data); -// // checkGlError("glTexSubImage2D"); -// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, -// GL_UNSIGNED_BYTE, data); -// checkGlError("glTexImage2D"); -// } - -// static void imagingCallback(void *userdata, const OSVR_TimeValue *timestamp, -// const OSVR_ImagingReport *report) { - -// OSVR_ClientContext *ctx = (OSVR_ClientContext *)userdata; - -// gReportNumber++; -// GLuint width = report->state.metadata.width; -// GLuint height = report->state.metadata.height; -// gLastFrameWidth = width; -// gLastFrameHeight = height; -// GLuint size = width * height * 4; - -// gLastFrame = report->state.data; -// } #if SUPPORT_OPENGL inline GLuint GetEyeTextureOpenGL(int eye) { return (eye == 0) ? gLeftEyeTextureID : gRightEyeTextureID; @@ -1010,17 +796,18 @@ static bool setupRenderTextures(OSVR_RenderManager renderManager) { gRenderParams.farClipDistanceMeters = 1000000.0f; gRenderParams.nearClipDistanceMeters = 0.0000001f; - RenderInfoCollectionOpenGL renderInfo(renderManager, gRenderParams); + + UpdateRenderInfoCollection(); OSVR_RenderManagerRegisterBufferState state; rc = osvrRenderManagerStartRegisterRenderBuffers(&state); checkReturnCode( rc, "osvrRenderManagerStartRegisterRenderBuffers call failed."); - for (OSVR_RenderInfoCount i = 0; i < renderInfo.getNumRenderInfo(); + for (OSVR_RenderInfoCount i = 0; i < s_lastRenderInfo.size(); i++) { OSVR_RenderInfoOpenGL currentRenderInfo = - renderInfo.getRenderInfo(i); + s_lastRenderInfo[i]; // Determine the appropriate size for the frame buffer to be used // for @@ -1105,16 +892,10 @@ static bool setupOSVR() { } OSVR_ReturnCode rc = 0; try { - // On Android, the current working directory is added to the default - // plugin search path. - // it also helps the server find its configuration and display files. - // boost::filesystem::current_path("/data/data/com.osvr.android.gles2sample/files"); - // auto workingDirectory = boost::filesystem::current_path(); - // //LOGI("[OSVR] Current working directory: %s", - // workingDirectory.string().c_str()); - // auto-start the server - //osvrClientAttemptServerAutoStart(); + // @todo we also auto-start the server from the C# scripts, + // should remove one set of calls. + osvrClientAttemptServerAutoStart(); if (!gClientContext) { // LOGI("[OSVR] Creating ClientContext..."); @@ -1143,23 +924,6 @@ static bool setupOSVR() { } else { // LOGI("[OSVR] Client context reported good status."); } - - // if (OSVR_RETURN_SUCCESS != - // osvrClientGetInterface(gClientContext, - // "/camera", &gCamera)) { - // //LOGI("Error, could not get the camera - // interface at /camera."); - // return false; - // } - // - // // Register the imaging callback. - // if (OSVR_RETURN_SUCCESS != - // osvrRegisterImagingCallback(gCamera, - // &imagingCallback, &gClientContext)) { - // //LOGI("Error, could not register image - // callback."); - // return false; - // } } gOSVRInitialized = true; @@ -1185,7 +949,7 @@ static bool setupRenderManager() { if (OSVR_RETURN_SUCCESS != osvrCreateRenderManagerOpenGL(gClientContext, "OpenGL", - gGraphicsLibrary, &gRenderManager, + gGraphicsLibrary, &s_render, &gRenderManagerOGL)) { std::cerr << "Could not create the RenderManager" << std::endl; return false; @@ -1197,8 +961,8 @@ static bool setupRenderManager() { gRenderManagerOGL, &openResults) || (openResults.status == OSVR_OPEN_STATUS_FAILURE)) { std::cerr << "Could not open display" << std::endl; - osvrDestroyRenderManager(gRenderManager); - gRenderManager = gRenderManagerOGL = nullptr; + osvrDestroyRenderManager(s_render); + s_render = gRenderManagerOGL = nullptr; return false; } @@ -1209,218 +973,14 @@ static bool setupRenderManager() { return false; } } -// static const GLfloat gTriangleColors[] = { -// // white -// 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -// 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, - -// // green -// 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, -// 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, - -// // blue -// 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, -// 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - -// // green/purple -// 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, -// 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, - -// // red/green -// 0.75f, 0.75f, 0.0f, 1.0f, 0.75f, 0.75f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, -// 0.75f, 0.75f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, - -// // red/blue -// 0.75f, 0.0f, 0.75f, 1.0f, 0.75f, 0.0f, 0.75f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -// 0.75f, 0.0f, 0.75f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f}; - -// static const GLfloat gTriangleTexCoordinates[] = { -// // A cube face (letters are unique vertices) -// // A--B -// // | | -// // D--C - -// // As two triangles (clockwise) -// // A B D -// // B C D - -// // white -// 1.0f, 0.0f, // A -// 1.0f, 1.0f, // B -// 0.0f, 0.0f, // D -// 1.0f, 1.0f, // B -// 0.0f, 1.0f, // C -// 0.0f, 0.0f, // D - -// // green -// 1.0f, 0.0f, // A -// 1.0f, 1.0f, // B -// 0.0f, 0.0f, // D -// 1.0f, 1.0f, // B -// 0.0f, 1.0f, // C -// 0.0f, 0.0f, // D - -// // blue -// 1.0f, 1.0f, // A -// 0.0f, 1.0f, // B -// 1.0f, 0.0f, // D -// 0.0f, 1.0f, // B -// 0.0f, 0.0f, // C -// 1.0f, 0.0f, // D - -// // blue-green -// 1.0f, 0.0f, // A -// 1.0f, 1.0f, // B -// 0.0f, 0.0f, // D -// 1.0f, 1.0f, // B -// 0.0f, 1.0f, // C -// 0.0f, 0.0f, // D - -// // yellow -// 0.0f, 0.0f, // A -// 1.0f, 0.0f, // B -// 0.0f, 1.0f, // D -// 1.0f, 0.0f, // B -// 1.0f, 1.0f, // C -// 0.0f, 1.0f, // D - -// // purple/magenta -// 1.0f, 1.0f, // A -// 0.0f, 1.0f, // B -// 1.0f, 0.0f, // D -// 0.0f, 1.0f, // B -// 0.0f, 0.0f, // C -// 1.0f, 0.0f, // D -// }; - -// static const GLfloat gTriangleVertices[] = { -// // A cube face (letters are unique vertices) -// // A--B -// // | | -// // D--C - -// // As two triangles (clockwise) -// // A B D -// // B C D - -// // glNormal3f(0.0, 0.0, -1.0); -// 1.0f, 1.0f, -1.0f, // A -// 1.0f, -1.0f, -1.0f, // B -// -1.0f, 1.0f, -1.0f, // D -// 1.0f, -1.0f, -1.0f, // B -// -1.0f, -1.0f, -1.0f, // C -// -1.0f, 1.0f, -1.0f, // D - -// // glNormal3f(0.0, 0.0, 1.0); -// -1.0f, 1.0f, 1.0f, // A -// -1.0f, -1.0f, 1.0f, // B -// 1.0f, 1.0f, 1.0f, // D -// -1.0f, -1.0f, 1.0f, // B -// 1.0f, -1.0f, 1.0f, // C -// 1.0f, 1.0f, 1.0f, // D - -// // glNormal3f(0.0, -1.0, 0.0); -// 1.0f, -1.0f, 1.0f, // A -// -1.0f, -1.0f, 1.0f, // B -// 1.0f, -1.0f, -1.0f, // D -// -1.0f, -1.0f, 1.0f, // B -// -1.0f, -1.0f, -1.0f, // C -// 1.0f, -1.0f, -1.0f, // D - -// // glNormal3f(0.0, 1.0, 0.0); -// 1.0f, 1.0f, 1.0f, // A -// 1.0f, 1.0f, -1.0f, // B -// -1.0f, 1.0f, 1.0f, // D -// 1.0f, 1.0f, -1.0f, // B -// -1.0f, 1.0f, -1.0f, // C -// -1.0f, 1.0f, 1.0f, // D - -// // glNormal3f(-1.0, 0.0, 0.0); -// -1.0f, 1.0f, 1.0f, // A -// -1.0f, 1.0f, -1.0f, // B -// -1.0f, -1.0f, 1.0f, // D -// -1.0f, 1.0f, -1.0f, // B -// -1.0f, -1.0f, -1.0f, // C -// -1.0f, -1.0f, 1.0f, // D - -// // glNormal3f(1.0, 0.0, 0.0); -// 1.0f, -1.0f, 1.0f, // A -// 1.0f, -1.0f, -1.0f, // B -// 1.0f, 1.0f, 1.0f, // D -// 1.0f, -1.0f, -1.0f, // B -// 1.0f, 1.0f, -1.0f, // C -// 1.0f, 1.0f, 1.0f // D -// }; static bool setupGraphics(int width, int height) { - // printGLString("Version", GL_VERSION); - // printGLString("Vendor", GL_VENDOR); - // printGLString("Renderer", GL_RENDERER); - // printGLString("Extensions", GL_EXTENSIONS); // initializeGLES2Ext(); GLint frameBuffer; glGetIntegerv(GL_FRAMEBUFFER_BINDING, &frameBuffer); gFrameBuffer = (GLuint)frameBuffer; - // LOGI("Window GL_FRAMEBUFFER_BINDING: %d", gFrameBuffer); - - // LOGI("setupGraphics(%d, %d)", width, height); - // gWidth = width; - // gHeight = height; - - // bool osvrSetupSuccess = setupOSVR(); - - // gProgram = createProgram(gVertexShader, gFragmentShader); - // if (!gProgram) { - // // LOGE("Could not create program."); - // osvrJniWrapperClass = jniEnvironment->FindClass( - // "org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class - // if (osvrJniWrapperClass == nullptr) { - // return false; - // } else { // if class found, continue - - // jmethodID logmid = jniEnvironment->GetStaticMethodID( - // osvrJniWrapperClass, "logMsg", - // "(Ljava/lang/String;)V"); // find method - // std::string stringy = - // "[OSVR-Unity-Android] Could not create program."; - // jstring jstr2 = jniEnvironment->NewStringUTF(stringy.c_str()); - // jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, logmid, - // jstr2); - // } - // return false; - // } - // gvPositionHandle = glGetAttribLocation(gProgram, "vPosition"); - // checkGlError("glGetAttribLocation"); - // // LOGI("glGetAttribLocation(\"vPosition\") = %d\n", gvPositionHandle); - - // gvColorHandle = glGetAttribLocation(gProgram, "vColor"); - // checkGlError("glGetAttribLocation"); - // // LOGI("glGetAttribLocation(\"vColor\") = %d\n", gvColorHandle); - - // gvTexCoordinateHandle = glGetAttribLocation(gProgram, "vTexCoordinate"); - // checkGlError("glGetAttribLocation"); - // // LOGI("glGetAttribLocation(\"vTexCoordinate\") = %d\n", - // // gvTexCoordinateHandle); - - // gvProjectionUniformId = glGetUniformLocation(gProgram, "projection"); - // gvViewUniformId = glGetUniformLocation(gProgram, "view"); - // gvModelUniformId = glGetUniformLocation(gProgram, "model"); - // guTextureUniformId = glGetUniformLocation(gProgram, "uTexture"); - - // glViewport(0, 0, width, height); - // checkGlError("glViewport"); - - //glDisable(GL_CULL_FACE); - - // @todo can we resize the texture after it has been created? - // if not, we may have to delete the dummy one and create a new one after - // the first imaging report. - // LOGI("Creating texture... here we go!"); - - //gTextureID = createTexture(width, height); - - // return osvrSetupSuccess; + gGraphicsInitializedOnce = true; return true; } @@ -1429,6 +989,7 @@ static bool setupGraphics(int width, int height) { * Just the current frame in the display. */ static void renderFrame() { + if (!gOSVRInitialized) { // @todo implement some logging/error handling? return; @@ -1444,28 +1005,14 @@ static void renderFrame() { OSVR_ReturnCode rc; - // glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - // checkGlError("glClearColor"); - // glViewport(0, 0, gWidth, gHeight); - // glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - // checkGlError("glClear"); - - if (gRenderManager && gClientContext) { + if (s_render && gClientContext) { osvrClientUpdate(gClientContext); - // if (gLastFrame != nullptr) { - // updateTexture(gLastFrameWidth, gLastFrameHeight, gLastFrame); - // osvrClientFreeImage(gClientContext, gLastFrame); - // gLastFrame = nullptr; - // } OSVR_RenderParams renderParams; rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); - RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, - renderParams); - // Get the present started OSVR_RenderManagerPresentState presentState; rc = osvrRenderManagerStartPresentRenderBuffers(&presentState); @@ -1473,12 +1020,13 @@ static void renderFrame() { rc, "osvrRenderManagerStartPresentRenderBuffers call failed."); for (OSVR_RenderInfoCount renderInfoCount = 0; - renderInfoCount < renderInfoCollection.getNumRenderInfo(); + renderInfoCount < s_lastRenderInfo.size(); renderInfoCount++) { // get the current render info OSVR_RenderInfoOpenGL currentRenderInfo = - renderInfoCollection.getRenderInfo(renderInfoCount); + s_lastRenderInfo[renderInfoCount]; + // Set color and depth buffers for the frame buffer OSVR_RenderTargetInfo renderTargetInfo = gRenderTargets[renderInfoCount]; @@ -1501,7 +1049,7 @@ static void renderFrame() { // actually kick off the present rc = osvrRenderManagerFinishPresentRenderBuffers( - gRenderManager, presentState, renderParams, false); + s_render, presentState, renderParams, false); checkReturnCode( rc, "osvrRenderManagerFinishPresentRenderBuffers call failed."); } @@ -1510,9 +1058,9 @@ static void renderFrame() { static void stop() { // LOGI("[OSVR] Shutting down..."); - if (gRenderManager) { - osvrDestroyRenderManager(gRenderManager); - gRenderManager = gRenderManagerOGL = nullptr; + if (s_render) { + osvrDestroyRenderManager(s_render); + s_render = gRenderManagerOGL = nullptr; } // is this needed? Maybe not. the display config manages the lifetime. @@ -1521,7 +1069,9 @@ static void stop() { gClientContext = nullptr; } - //osvrClientReleaseAutoStartedServer(); + // @todo: The C# scripts also call this. Only one set is necessary, though + // they are both idempotent + osvrClientReleaseAutoStartedServer(); } OSVR_ReturnCode CreateRenderManagerAndroid(OSVR_ClientContext context) { @@ -1566,7 +1116,10 @@ void UNITY_INTERFACE_API ShutdownRenderManager() { OSVR_ReturnCode UNITY_INTERFACE_API CreateRenderManagerFromUnity(OSVR_ClientContext context) { #if UNITY_ANDROID - return CreateRenderManagerAndroid(context); + OSVR_ReturnCode rc = CreateRenderManagerAndroid(context); + if(rc == OSVR_RETURN_FAILURE) { + return rc; + } #else if (s_render != nullptr) { if (osvrRenderManagerGetDoingOkay(s_render)) { @@ -1655,7 +1208,7 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context) { ShutdownRenderManager(); return OSVR_RETURN_FAILURE; } - +#endif // non-Android platforms // create a new set of RenderParams for passing to GetRenderInfo() osvrRenderManagerGetDefaultRenderParams(&s_renderParams); @@ -1663,7 +1216,6 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context) { DebugLog("[OSVR Rendering Plugin] CreateRenderManagerFromUnity Success!"); return OSVR_RETURN_SUCCESS; -#endif // non-Android platforms } /// Helper function that handles doing the loop of constructing buffers, and @@ -1673,6 +1225,7 @@ inline OSVR_ReturnCode applyRenderBufferConstructor(const int numBuffers, F &&bufferConstructor, G &&bufferCleanup) { #if UNITY_ANDROID + UpdateRenderInfoCollection(); return OSVR_RETURN_SUCCESS; #else /// If we bail any time before the end, we'll automatically clean up the @@ -1865,10 +1418,13 @@ inline void CleanupBufferD3D11(OSVR_RenderBufferD3D11 &rb) { delete &rb; } OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { #if UNITY_ANDROID - if (!setupRenderTextures(gRenderManager)) { + if (!setupRenderTextures(s_render)) { + DebugLog("[OSVR Rendering Plugin] Failed to create render textures."); return OSVR_RETURN_FAILURE; - } else + } else { + UpdateRenderInfoCollection(); return OSVR_RETURN_SUCCESS; + } #else if (!s_deviceType) { DebugLog("[OSVR Rendering Plugin] Device type not supported."); @@ -1901,16 +1457,16 @@ OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { void UNITY_INTERFACE_API SetNearClipDistance(double distance) { s_nearClipDistance = distance; -#if !UNITY_ANDROID +// #if !UNITY_ANDROID s_renderParams.nearClipDistanceMeters = s_nearClipDistance; -#endif +// #endif } void UNITY_INTERFACE_API SetFarClipDistance(double distance) { s_farClipDistance = distance; -#if !UNITY_ANDROID +// #if !UNITY_ANDROID s_renderParams.farClipDistanceMeters = s_farClipDistance; -#endif +// #endif } void UNITY_INTERFACE_API SetIPD(double ipdMeters) { @@ -1919,21 +1475,6 @@ void UNITY_INTERFACE_API SetIPD(double ipdMeters) { } OSVR_ViewportDescription UNITY_INTERFACE_API GetViewport(std::uint8_t eye) { -#if UNITY_ANDROID - OSVR_RenderParams renderParams; - OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); - checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); - RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, - renderParams); - OSVR_RenderInfoOpenGL currentRenderInfo = - renderInfoCollection.getRenderInfo(eye); - OSVR_ViewportDescription viewDesc; - viewDesc.width = currentRenderInfo.viewport.width; - viewDesc.height = currentRenderInfo.viewport.height; - viewDesc.left = currentRenderInfo.viewport.left; - viewDesc.lower = currentRenderInfo.viewport.lower; - return viewDesc; -#else // non-Android platoforms OSVR_ViewportDescription viewportDescription; if (numRenderInfo > 0 && eye <= numRenderInfo - 1) { viewportDescription = s_lastRenderInfo[eye].viewport; @@ -1963,28 +1504,10 @@ OSVR_ViewportDescription UNITY_INTERFACE_API GetViewport(std::uint8_t eye) { lastGoodViewportDescription = viewportDescription; } return viewportDescription; -#endif // non-Android platforms } OSVR_ProjectionMatrix UNITY_INTERFACE_API GetProjectionMatrix(std::uint8_t eye) { -#if UNITY_ANDROID - OSVR_RenderParams renderParams; - OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); - checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); - RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, - renderParams); - OSVR_RenderInfoOpenGL currentRenderInfo = - renderInfoCollection.getRenderInfo(eye); - OSVR_ProjectionMatrix proj; - proj.left = currentRenderInfo.projection.left; - proj.right = currentRenderInfo.projection.right; - proj.top = currentRenderInfo.projection.top; - proj.bottom = currentRenderInfo.projection.bottom; - proj.nearClip = currentRenderInfo.projection.nearClip; - proj.farClip = currentRenderInfo.projection.farClip; - return proj; -#else OSVR_ProjectionMatrix pm; if (numRenderInfo > 0 && eye <= numRenderInfo - 1) { pm = s_lastRenderInfo[eye].projection; @@ -1998,20 +1521,9 @@ GetProjectionMatrix(std::uint8_t eye) { pm = lastGoodProjMatrix; } return pm; -#endif // non-Android platforms } OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { -#if UNITY_ANDROID - OSVR_RenderParams renderParams; - OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); - checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); - RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, - renderParams); - OSVR_RenderInfoOpenGL currentRenderInfo = - renderInfoCollection.getRenderInfo(eye); - return currentRenderInfo.pose; -#else OSVR_Pose3 pose; osvrPose3SetIdentity(&pose); if (numRenderInfo > 0 && eye <= numRenderInfo - 1) { @@ -2025,7 +1537,6 @@ OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { pose = lastGoodPose; } return pose; -#endif // non-Android platforms } // -------------------------------------------------------------------------- @@ -2252,9 +1763,7 @@ void UNITY_INTERFACE_API OnRenderEvent(int eventID) { case kOsvrEventID_Shutdown: break; case kOsvrEventID_Update: -#if UNITY_WIN UpdateRenderInfoCollection(); -#endif break; case kOsvrEventID_SetRoomRotationUsingHead: SetRoomRotationUsingHead(); From 92d62f38c0672f6b00e69ad8e643d67ce5838fb1 Mon Sep 17 00:00:00 2001 From: Jeremy Bell Date: Fri, 1 Sep 2017 13:05:33 -0400 Subject: [PATCH 36/43] Choreographer implementation, some build fixes --- CMakeLists.txt | 6 +- OsvrRenderingPlugin.cpp | 264 ++++++++++++++++++++++++---------------- 2 files changed, 164 insertions(+), 106 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9eca44f..a26f9cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,7 +56,7 @@ target_include_directories(osvrUnityRenderingPlugin PRIVATE ${Boost_INCLUDE_DIRS if (OPENGL_FOUND AND GLEW_FOUND) target_include_directories(osvrUnityRenderingPlugin PRIVATE ${OPENGL_INCLUDE_DIRS}) - target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} GLEW::GLEW JsonCpp::JsonCpp SDL2::SDL2 osvr::osvrClientKit osvrRenderManager::osvrRenderManager ${EXTRA_ANDROID_LINKER_FLAGS}) + target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} GLEW::GLEW JsonCpp::JsonCpp SDL2::SDL2 osvr::osvrClientKit osvrRenderManager::osvrRenderManager android ${EXTRA_ANDROID_LINKER_FLAGS}) # Handle static glew. if(GLEW_LIBRARY MATCHES ".*s.lib") target_compile_definitions(osvrUnityRenderingPlugin PRIVATE GLEW_STATIC) @@ -64,11 +64,11 @@ if (OPENGL_FOUND AND GLEW_FOUND) endif() if (OPENGL_FOUND) target_include_directories(osvrUnityRenderingPlugin PRIVATE ${OPENGL_INCLUDE_DIRS}) - target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} JsonCpp::JsonCpp osvr::osvrClientKit osvrRenderManager::osvrRenderManager ${EXTRA_ANDROID_LINKER_FLAGS}) + target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} JsonCpp::JsonCpp osvr::osvrClientKit osvrRenderManager::osvrRenderManager android ${EXTRA_ANDROID_LINKER_FLAGS}) endif() if(OPENGLES2_FOUND) target_include_directories(osvrUnityRenderingPlugin PRIVATE ${OPENGLES2_INCLUDE_DIR}) - target_link_libraries(osvrUnityRenderingPlugin PRIVATE ${OPENGLES2_LIBRARIES} JsonCpp::JsonCpp osvr::osvrClientKit osvrRenderManager::osvrRenderManager ${EXTRA_ANDROID_LINKER_FLAGS}) + target_link_libraries(osvrUnityRenderingPlugin PRIVATE ${OPENGLES2_LIBRARIES} JsonCpp::JsonCpp osvr::osvrClientKit osvrRenderManager::osvrRenderManager android ${EXTRA_ANDROID_LINKER_FLAGS}) endif() # Install docs, license, sample config diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 1d6581c..4f87c6a 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -97,16 +97,66 @@ Sensics, Inc. #include #endif // SUPPORT_OPENGL -#if OSVR_ANDROID +#if UNITY_ANDROID #include -// #include -// #include +//#include +#include #define LOG_TAG "osvrUnityRendering" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) #endif +// some choreographer code derived from this sample: +// https://github.com/googlesamples/android-ndk/blob/9c9a261426af72c1ba8fc38eb2e6d70ec7078827/teapots/choreographer-30fps/src/main/cpp/ChoreographerNativeActivity.cpp + +// Declaration for native chreographer API. +struct AChoreographer; +typedef void (*AChoreographer_frameCallback)(long frameTimeNanos, void* data); +typedef AChoreographer* (*func_AChoreographer_getInstance)(); +typedef void (*func_AChoreographer_postFrameCallback)( + AChoreographer* choreographer, AChoreographer_frameCallback callback, + void* data); + + // Function pointers for native Choreographer API. +func_AChoreographer_getInstance AChoreographer_getInstance_; +func_AChoreographer_postFrameCallback AChoreographer_postFrameCallback_; + +bool gChoreographerAPIInitialized = false; +bool gHasChoreographerAPI = true; + +static bool initChoreographerAPIDynamically() { + if(!gChoreographerAPIInitialized && gHasChoreographerAPI) { + // Retrieve function pointers from shared object. + void* lib = dlopen("libandroid.so", RTLD_NOW | RTLD_LOCAL); + if(!lib) { + gHasChoreographerAPI = false; + LOGE("[OSVR-Unity-Rendering]: Could not load libandroid.so"); + return false; + } + AChoreographer_getInstance_ = + reinterpret_cast( + dlsym(lib, "AChoreographer_getInstance")); + AChoreographer_postFrameCallback_ = + reinterpret_cast( + dlsym(lib, "AChoreographer_postFrameCallback")); + + if(!AChoreographer_getInstance_) { + LOGE("[OSVR-Unity-Rendering]: Couldn't load AChoreographer_getInstance symbol"); + gHasChoreographerAPI = false; + return false; + } + if(!AChoreographer_postFrameCallback_) { + LOGE("[OSVR-Unity-Rendering]: Couldn't load AChoreographer_postFrameCallback symbol"); + gHasChoreographerAPI = false; + return false; + } + gChoreographerAPIInitialized = true; + LOGI("[OSVR-Unity-Rendering]: Loaded Choreographer API dynamically"); + return true; + } + return false; +} // VARIABLES static IUnityInterfaces *s_UnityInterfaces = nullptr; @@ -583,77 +633,85 @@ static void checkGlError(const char *op) { } } -// #if OSVR_ANDROID -// static long gPreviousFrameTimeNanos = 0; -// static long gLastFrameTimeNanos = 0; -// static std::mutex gFrameTimeMutex; - -// /** -// * This func is called on an app frame callback by the -// * Choreographer on Android. -// * NOTE: This is offset from the real "last vsync" when the -// * Android build has offset. @todo account for this offset using JNI. -// */ -// static void frameCallbackImpl(long frameTimeNanos, void *data) { -// std::lock_guard lockGuard(gFrameTimeMutex); -// gPreviousFrameTimeNanos = gLastFrameTimeNanos; -// gLastFrameTimeNanos = frameTimeNanos; -// /// LOGI("frameTimeNanos: %d", frameTimeNanos); -// static long frameIndex = 0; -// if((frameIndex++) % 60 == 0) { -// LOGI("frame diff: %d", frameTimeNanos - gPreviousFrameTimeNanos); -// } -// AChoreographer *choreographer = AChoreographer_getInstance(); -// if (!choreographer) { -// LOGE("Couldn't get the choreographer from the frame callback"); -// } -// AChoreographer_postFrameCallback(choreographer, frameCallbackImpl, nullptr); -// } - -// /** -// * Use this function in a std::thread to keep the ALooper pumping AChoreographer -// * callbacks on a separate thread from where it's consumed. Otherwise the polling -// * here will stall the render thread. -// * @TODO - provide a way to signal graceful thread exit. -// */ -// static void choreographerThreadRun() { -// LOGI("On Choreographer thread"); -// ALooper *looper = ALooper_forThread(); -// if (!looper) { -// looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); -// if (!looper) { -// LOGE("Couldn't prepare an ALooper for the choreographer thread"); -// return; -// } -// } - -// AChoreographer *choreographer = AChoreographer_getInstance(); -// if (!choreographer) { -// LOGE("Could not get choreographer."); -// return; -// } - -// AChoreographer_postFrameCallback(choreographer, frameCallbackImpl, nullptr); - -// while (true) { -// // @TODO provide a signal for graceful thread exit? -// int fd_unused = 0; -// int outEvents_unused = 0; -// void *outData_unused = nullptr; -// int rc = ALooper_pollAll(100, &fd_unused, &outEvents_unused, -// &outData_unused); -// } -// } -// #endif +#if UNITY_ANDROID +static long gPreviousFrameTimeNanos = 0; +static long gLastFrameTimeNanos = 0; +static std::mutex gFrameTimeMutex; + +/** + * This func is called on an app frame callback by the + * Choreographer on Android. + * NOTE: This is offset from the real "last vsync" when the + * Android build has offset. @todo account for this offset using JNI. + */ +static void frameCallbackImpl(long frameTimeNanos, void *data) { + std::lock_guard lockGuard(gFrameTimeMutex); + gPreviousFrameTimeNanos = gLastFrameTimeNanos; + gLastFrameTimeNanos = frameTimeNanos; + /// LOGI("frameTimeNanos: %d", frameTimeNanos); + // static long frameIndex = 0; + // if((frameIndex++) % 60 == 0) { + // LOGI("frame diff: %d", frameTimeNanos - gPreviousFrameTimeNanos); + // } + // no need to call initChoreographerAPIDynamically because we wouldn't be + // here if it wasn't initialized + AChoreographer *choreographer = AChoreographer_getInstance_(); + if (!choreographer) { + LOGE("Couldn't get the choreographer from the frame callback"); + } + AChoreographer_postFrameCallback_(choreographer, frameCallbackImpl, nullptr); +} + +/** + * Use this function in a std::thread to keep the ALooper pumping AChoreographer + * callbacks on a separate thread from where it's consumed. Otherwise the polling + * here will stall the render thread. + * @TODO - provide a way to signal graceful thread exit. + */ +static void choreographerThreadRun() { + LOGI("On Choreographer thread"); + ALooper *looper = ALooper_forThread(); + if (!looper) { + looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); + if (!looper) { + LOGE("[OSVR-Unity-Rendering]: Couldn't prepare an ALooper for the choreographer thread"); + return; + } + } + + // this call is lazy + if(!initChoreographerAPIDynamically()) { + LOGE("[OSVR-Unity-Rendering]: Could not initialize the choreographer API dynamically."); + return; + } + + AChoreographer *choreographer = AChoreographer_getInstance_(); + if (!choreographer) { + LOGE("[OSVR-Unity-Rendering]: Could not get choreographer."); + return; + } + + AChoreographer_postFrameCallback_(choreographer, frameCallbackImpl, nullptr); + + while (true) { + // @TODO provide a signal for graceful thread exit? + int fd_unused = 0; + int outEvents_unused = 0; + void *outData_unused = nullptr; + int rc = ALooper_pollAll(100, &fd_unused, &outEvents_unused, + &outData_unused); + } +} +#endif class PassThroughOpenGLContextImpl { OSVR_OpenGLToolkitFunctions toolkit; int mWidth; int mHeight; -// #if OSVR_ANDROID -// std::thread mChoreographerThread; -// #endif +#if UNITY_ANDROID + std::thread mChoreographerThread; +#endif static void createImpl(void *data) {} static void destroyImpl(void *data) { @@ -695,11 +753,11 @@ class PassThroughOpenGLContextImpl { } public: -// #if OSVR_ANDROID -// PassThroughOpenGLContextImpl() : mChoreographerThread(choreographerThreadRun) { -// #else +#if UNITY_ANDROID + PassThroughOpenGLContextImpl() : mChoreographerThread(choreographerThreadRun) { +#else PassThroughOpenGLContextImpl() { -// #endif +#endif memset(&toolkit, 0, sizeof(toolkit)); toolkit.size = sizeof(toolkit); toolkit.data = this; @@ -746,38 +804,38 @@ class PassThroughOpenGLContextImpl { bool getRenderTimingInfo(size_t display, size_t whichEye, OSVR_RenderTimingInfo *renderTimingInfoOut) { -// #if OSVR_ANDROID -// timespec tp; -// int rv = clock_gettime(CLOCK_MONOTONIC, &tp); -// if (!rv) { -// std::lock_guard lockGuard(gFrameTimeMutex); -// // uint64_t presentationDeadline = 17683333L; // Shouldn't this bee -// // at least less than 16,666,666? (1 billion / 60) -// // that's 1,016,666 nanoseconds greater than the hardware interval -// // uint64_t hardwareDisplayIntervalNanos = 11111111L; // 90Hz hard -// // coded, TODO measure this or get it from the API? -// uint64_t hardwareDisplayIntervalNanos = gLastFrameTimeNanos - gPreviousFrameTimeNanos; -// uint64_t nowNanos = ((tp.tv_sec * 1000000000L) + tp.tv_nsec); -// uint64_t timeFromLastNanos = nowNanos >= gLastFrameTimeNanos -// ? nowNanos - gLastFrameTimeNanos -// : 0; // just being safe -// uint64_t nextNanos = gLastFrameTimeNanos + hardwareDisplayIntervalNanos; -// uint64_t timeUntilNextNanos = -// nextNanos >= nowNanos ? nextNanos - nowNanos -// : 0; // 0 here means we missed a vsync - -// nanoSecondsToTimeValue(timeFromLastNanos, -// &renderTimingInfoOut->timeSincelastVerticalRetrace); +#if UNITY_ANDROID + timespec tp; + int rv = clock_gettime(CLOCK_MONOTONIC, &tp); + if (!rv) { + std::lock_guard lockGuard(gFrameTimeMutex); + // uint64_t presentationDeadline = 17683333L; // Shouldn't this bee + // at least less than 16,666,666? (1 billion / 60) + // that's 1,016,666 nanoseconds greater than the hardware interval + // uint64_t hardwareDisplayIntervalNanos = 11111111L; // 90Hz hard + // coded, TODO measure this or get it from the API? + uint64_t hardwareDisplayIntervalNanos = gLastFrameTimeNanos - gPreviousFrameTimeNanos; + uint64_t nowNanos = ((tp.tv_sec * 1000000000L) + tp.tv_nsec); + uint64_t timeFromLastNanos = nowNanos >= gLastFrameTimeNanos + ? nowNanos - gLastFrameTimeNanos + : 0; // just being safe + uint64_t nextNanos = gLastFrameTimeNanos + hardwareDisplayIntervalNanos; + uint64_t timeUntilNextNanos = + nextNanos >= nowNanos ? nextNanos - nowNanos + : 0; // 0 here means we missed a vsync + + nanoSecondsToTimeValue(timeFromLastNanos, + &renderTimingInfoOut->timeSincelastVerticalRetrace); -// nanoSecondsToTimeValue(timeUntilNextNanos, -// &renderTimingInfoOut->timeUntilNextPresentRequired); - -// nanoSecondsToTimeValue(hardwareDisplayIntervalNanos, -// &renderTimingInfoOut->hardwareDisplayInterval); -// return true; -// } -// LOGI("clock_gettime call failed."); -// #endif + nanoSecondsToTimeValue(timeUntilNextNanos, + &renderTimingInfoOut->timeUntilNextPresentRequired); + + nanoSecondsToTimeValue(hardwareDisplayIntervalNanos, + &renderTimingInfoOut->hardwareDisplayInterval); + return true; + } + LOGI("clock_gettime call failed."); +#endif return false; } }; From 7b0013ae610943a435ab8b749994e0f0f42cf79b Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Tue, 5 Dec 2017 17:29:03 -0500 Subject: [PATCH 37/43] Creates an extra set of render buffers and swaps buffers every frame. --- OsvrRenderingPlugin.cpp | 331 ++++++++++++++++++++++++++++++++-------- OsvrRenderingPlugin.h | 2 +- 2 files changed, 270 insertions(+), 63 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index bb00f4d..bd04a15 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -186,17 +186,32 @@ static const char gFragmentShader[] = "}\n"; #else // Windows, Linux, OSX static variables + +struct FrameInfo { + // Set up the vector of textures to render to and any framebuffer + // we need to group them. + std::vector renderBuffers; + ID3D11Texture2D* depthStencilTexture; + ID3D11DepthStencilView* depthStencilView; + IDXGIKeyedMutex* keyedMutex; + + // I prefer initialization list form + FrameInfo() : renderBuffers(2) + // vertices default ctor is ok, creates empty vector + { + // use vertices.push_back(...); to fill vertices + } + +}; +static std::vector frameInfo; static OSVR_RenderParams s_renderParams; static OSVR_RenderManager s_render = nullptr; static OSVR_RenderManagerD3D11 s_renderD3D = nullptr; static OSVR_ClientContext s_clientContext = nullptr; -static std::vector s_renderBuffers; static std::vector s_renderInfo; static std::vector s_lastRenderInfo; -static OSVR_RenderInfoCount numRenderInfo; -static OSVR_RenderInfoCollection s_renderInfoCollection; static OSVR_GraphicsLibraryD3D11 s_libraryD3D; - +static OSVR_RenderInfoCount numRenderInfo; static OSVR_ProjectionMatrix lastGoodProjMatrix; static OSVR_Pose3 lastGoodPose; static OSVR_ViewportDescription lastGoodViewportDescription; @@ -209,8 +224,13 @@ static std::streambuf *s_oldCerr = nullptr; #endif // defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) #endif // end Windows, Linux, OSX +static int numBuffers = 2; +static int iterations = 0; + static void *s_leftEyeTexturePtr = nullptr; static void *s_rightEyeTexturePtr = nullptr; +static void *s_leftEyeTexturePtrBuffer2 = nullptr; +static void *s_rightEyeTexturePtrBuffer2 = nullptr; // D3D11 vars #if SUPPORT_D3D11 @@ -228,7 +248,7 @@ enum RenderEvents { kOsvrEventID_Render = 0, kOsvrEventID_Shutdown = 1, kOsvrEventID_Update = 2, - kOsvrEventID_SetRoomRotationUsingHead = 3, + kOsvrEventID_ConstructBuffers = 3, kOsvrEventID_ClearRoomToWorldTransform = 4 }; @@ -491,31 +511,37 @@ void UNITY_INTERFACE_API UnityPluginUnload() { } #if UNITY_WIN -inline void UpdateRenderInfoCollection() { - if ((OSVR_RETURN_SUCCESS != - osvrRenderManagerGetRenderInfoCollection(s_render, s_renderParams, - &s_renderInfoCollection))) { - DebugLog("[OSVR Rendering Plugin] UpdateRenderInfo Could not get " - "renderinfo collection."); - ShutdownRenderManager(); - } - osvrRenderManagerGetNumRenderInfoInCollection(s_renderInfoCollection, - &numRenderInfo); - - // update renderinfo - s_renderInfo.clear(); - for (OSVR_RenderInfoCount i = 0; i < numRenderInfo; i++) { - OSVR_RenderInfoD3D11 info; - if ((OSVR_RETURN_SUCCESS != - osvrRenderManagerGetRenderInfoFromCollectionD3D11( - s_renderInfoCollection, i, &info))) { - DebugLog("[OSVR Rendering Plugin] Could not get render info."); - } - s_renderInfo.push_back(info); - } - if (numRenderInfo > 0) { - s_lastRenderInfo = s_renderInfo; - } +inline void UpdateRenderInfo() { + // Do a call to get the information we need to construct our + // color and depth render-to-texture buffers. + + OSVR_RenderParams renderParams; + osvrRenderManagerGetDefaultRenderParams(&renderParams); + + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerGetNumRenderInfo( + s_render, renderParams, &numRenderInfo))) { + std::cerr << "Could not get context number of render infos." + << std::endl; + osvrDestroyRenderManager(s_render); + return; + } + + s_renderInfo.clear(); + for (OSVR_RenderInfoCount i = 0; i < numRenderInfo; i++) { + OSVR_RenderInfoD3D11 info; + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerGetRenderInfoD3D11( + s_renderD3D, i, renderParams, &info))) { + std::cerr << "Could not get render info " << i + << std::endl; + osvrDestroyRenderManager(s_render); + return; + } + s_renderInfo.push_back(info); + } + if (numRenderInfo > 0) + { + s_lastRenderInfo = s_renderInfo; + } } #endif // UNITY_WIN @@ -1526,7 +1552,7 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context) { // create a new set of RenderParams for passing to GetRenderInfo() osvrRenderManagerGetDefaultRenderParams(&s_renderParams); - UpdateRenderInfoCollection(); + UpdateRenderInfo(); DebugLog("[OSVR Rendering Plugin] CreateRenderManagerFromUnity Success!"); return OSVR_RETURN_SUCCESS; @@ -1571,7 +1597,7 @@ inline OSVR_ReturnCode applyRenderBufferConstructor(const int numBuffers, // Register our constructed buffers so that we can use them for // presentation. - UpdateRenderInfoCollection(); + UpdateRenderInfo(); OSVR_RenderManagerRegisterBufferState registerBufferState; if ((OSVR_RETURN_SUCCESS != @@ -1590,7 +1616,7 @@ inline OSVR_ReturnCode applyRenderBufferConstructor(const int numBuffers, } } if ((OSVR_RETURN_SUCCESS != osvrRenderManagerFinishRegisterRenderBuffers( - s_render, registerBufferState, false))) { + s_render, registerBufferState, true))) { DebugLog("[OSVR Rendering Plugin]Could not finish registering render " "buffers"); ShutdownRenderManager(); @@ -1676,12 +1702,20 @@ inline void CleanupBufferOpenGL(OSVR_RenderBufferOpenGL &rb) { #endif // SUPPORT_OPENGL #if SUPPORT_D3D11 -inline ID3D11Texture2D *GetEyeTextureD3D11(int eye) { - return reinterpret_cast(eye == 0 ? s_leftEyeTexturePtr - : s_rightEyeTexturePtr); +inline ID3D11Texture2D *GetEyeTextureD3D11(int eye, int buffer) { + if (buffer == 0) + { + return reinterpret_cast(eye == 0 ? s_leftEyeTexturePtr + : s_rightEyeTexturePtr); + } + else + { + return reinterpret_cast(eye == 0 ? s_leftEyeTexturePtrBuffer2 + : s_rightEyeTexturePtrBuffer2); + } } -inline OSVR_ReturnCode ConstructBuffersD3D11(int eye) { +inline OSVR_ReturnCode ConstructBuffersD3D11(int eye, int buffer, FrameInfo* fInfo) { DebugLog("[OSVR Rendering Plugin] ConstructBuffersD3D11"); HRESULT hr; // The color buffer for this eye. We need to put this into @@ -1689,7 +1723,7 @@ inline OSVR_ReturnCode ConstructBuffersD3D11(int eye) { // to fill in the Direct3D portion. // Note that this texture format must be RGBA and unsigned byte, // so that we can present it to Direct3D for DirectMode. - ID3D11Texture2D *D3DTexture = GetEyeTextureD3D11(eye); + ID3D11Texture2D *D3DTexture = GetEyeTextureD3D11(eye, buffer); unsigned width = static_cast(s_renderInfo[eye].viewport.width); unsigned height = static_cast(s_renderInfo[eye].viewport.height); @@ -1722,7 +1756,64 @@ inline OSVR_ReturnCode ConstructBuffersD3D11(int eye) { OSVR_RenderBufferD3D11 rbD3D; rbD3D.colorBuffer = D3DTexture; rbD3D.colorBufferView = renderTargetView; - s_renderBuffers.push_back(rbD3D); + fInfo->renderBuffers.push_back(rbD3D); + //s_renderBuffers.push_back(rbD3D); + + IDXGIKeyedMutex* keyedMutex = nullptr; + hr = D3DTexture->QueryInterface( + __uuidof(IDXGIKeyedMutex), (LPVOID*)&keyedMutex); + if (FAILED(hr) || keyedMutex == nullptr) { + std::cerr << "Could not get mutex pointer" << std::endl; + return -2; + } + fInfo->keyedMutex = keyedMutex; + + //================================================================== + // Create a depth buffer + + // Make the depth/stencil texture. + D3D11_TEXTURE2D_DESC textureDescription = { 0 }; + textureDescription.SampleDesc.Count = 1; + textureDescription.SampleDesc.Quality = 0; + textureDescription.Usage = D3D11_USAGE_DEFAULT; + textureDescription.BindFlags = D3D11_BIND_DEPTH_STENCIL; + textureDescription.Width = width; + textureDescription.Height = height; + textureDescription.MipLevels = 1; + textureDescription.ArraySize = 1; + textureDescription.CPUAccessFlags = 0; + textureDescription.MiscFlags = 0; + /// @todo Make this a parameter + textureDescription.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + ID3D11Texture2D* depthStencilBuffer; + hr = s_libraryD3D.device->CreateTexture2D( + &textureDescription, NULL, &depthStencilBuffer); + if (FAILED(hr)) { + std::cerr << "Could not create depth/stencil texture" + << std::endl; + return -4; + } + fInfo->depthStencilTexture = depthStencilBuffer; + + // Create the depth/stencil view description + D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDescription; + memset(&depthStencilViewDescription, 0, sizeof(depthStencilViewDescription)); + depthStencilViewDescription.Format = textureDescription.Format; + depthStencilViewDescription.ViewDimension = + D3D11_DSV_DIMENSION_TEXTURE2D; + depthStencilViewDescription.Texture2D.MipSlice = 0; + + ID3D11DepthStencilView* depthStencilView; + hr = s_libraryD3D.device->CreateDepthStencilView( + depthStencilBuffer, + &depthStencilViewDescription, + &depthStencilView); + if (FAILED(hr)) { + std::cerr << "Could not create depth/stencil view" + << std::endl; + return -5; + } + fInfo->depthStencilView = depthStencilView; return OSVR_RETURN_SUCCESS; } @@ -1741,21 +1832,59 @@ OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { DebugLog("[OSVR Rendering Plugin] Device type not supported."); return OSVR_RETURN_FAILURE; } - UpdateRenderInfoCollection(); + UpdateRenderInfo(); // construct buffers - const int n = static_cast(numRenderInfo); + //const int n = static_cast(numRenderInfo); switch (s_deviceType.getDeviceTypeEnum()) { #if SUPPORT_D3D11 case OSVRSupportedRenderers::D3D11: - return applyRenderBufferConstructor(n, ConstructBuffersD3D11, - CleanupBufferD3D11); + for (int i = 0; i < numBuffers; i++) + { + FrameInfo* f = new FrameInfo(); + f->renderBuffers.clear(); + for (int j = 0; j < numRenderInfo; j++) + { + ConstructBuffersD3D11(i, j, f); + } + frameInfo.push_back(f); + } + + // Register our constructed buffers so that we can use them for + // presentation. + OSVR_RenderManagerRegisterBufferState registerBufferState; + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerStartRegisterRenderBuffers( + ®isterBufferState))) { + std::cerr << "Could not start registering render buffers" << std::endl; + osvrDestroyRenderManager(s_render); + return -4; + } + for (size_t i = 0; i < frameInfo.size(); i++) { + for (int j = 0; j < numRenderInfo; j++) + { + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerRegisterRenderBufferD3D11( + registerBufferState, frameInfo[i]->renderBuffers[j]))) { + std::cerr << "Could not register render buffer " << i << std::endl; + osvrDestroyRenderManager(s_render); + return -5; + } + } + + } + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerFinishRegisterRenderBuffers( + s_render, registerBufferState, false))) { + std::cerr << "Could not finish registering render buffers" << std::endl; + osvrDestroyRenderManager(s_render); + return -6; + } + //return applyRenderBufferConstructor(n, ConstructBuffersD3D11, + // CleanupBufferD3D11); break; #endif #if SUPPORT_OPENGL case OSVRSupportedRenderers::OpenGL: - return applyRenderBufferConstructor(n, ConstructBuffersOpenGL, - CleanupBufferOpenGL); + // return applyRenderBufferConstructor(n, ConstructBuffersOpenGL, + // CleanupBufferOpenGL); break; #endif case OSVRSupportedRenderers::EmptyRenderer: @@ -1909,7 +2038,7 @@ OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { // For more reference, see: // http://docs.unity3d.com/ScriptReference/Texture.GetNativeTexturePtr.html int UNITY_INTERFACE_API SetColorBufferFromUnity(void *texturePtr, - std::uint8_t eye) { + std::uint8_t eye, std::uint8_t buffer) { if (!s_deviceType) { return OSVR_RETURN_FAILURE; } @@ -1925,10 +2054,32 @@ int UNITY_INTERFACE_API SetColorBufferFromUnity(void *texturePtr, return OSVR_RETURN_SUCCESS; #else if (eye == 0) { - s_leftEyeTexturePtr = texturePtr; + if (buffer == 0) + { + DebugLog("[OSVR Rendering Plugin] SetColorBufferFromUnity eye 0 buffer 0"); + + s_leftEyeTexturePtr = texturePtr; + } + else + { + DebugLog("[OSVR Rendering Plugin] SetColorBufferFromUnity eye 1 buffer 0"); + + s_leftEyeTexturePtrBuffer2 = texturePtr; + } } else { - s_rightEyeTexturePtr = texturePtr; - } + if (buffer == 0) + { + DebugLog("[OSVR Rendering Plugin] SetColorBufferFromUnity eye 0 buffer 1"); + + s_rightEyeTexturePtr = texturePtr; + } + else + { + DebugLog("[OSVR Rendering Plugin] SetColorBufferFromUnity eye 1 buffer 1"); + + s_rightEyeTexturePtrBuffer2 = texturePtr; + } + } return OSVR_RETURN_SUCCESS; #endif @@ -1937,13 +2088,13 @@ int UNITY_INTERFACE_API SetColorBufferFromUnity(void *texturePtr, // Renders the view from our Unity cameras by copying data at // Unity.RenderTexture.GetNativeTexturePtr() to RenderManager colorBuffers void RenderViewD3D11(const OSVR_RenderInfoD3D11 &ri, - ID3D11RenderTargetView *renderTargetView, int eyeIndex) { + ID3D11RenderTargetView *renderTargetView, int eyeIndex, int frame) { auto context = ri.library.context; // Set up to render to the textures for this eye context->OMSetRenderTargets(1, &renderTargetView, NULL); // copy the updated RenderTexture from Unity to RenderManager colorBuffer - s_renderBuffers[eyeIndex].colorBuffer = GetEyeTextureD3D11(eyeIndex); + frameInfo[frame]->renderBuffers[eyeIndex].colorBuffer = GetEyeTextureD3D11(eyeIndex, frame); } #endif // SUPPORT_D3D11 @@ -2030,13 +2181,54 @@ inline void DoRender() { switch (s_deviceType.getDeviceTypeEnum()) { #if SUPPORT_D3D11 case OSVRSupportedRenderers::D3D11: { + + + int frame = iterations % numBuffers; + + // Grab and lock the mutex, so that we will be able to render + // to it whether or not RenderManager locks it on our behalf. + // it will not be auto-locked when we're in the non-ATW case. + //std::cout << "RenderThread: locking buffer for frame " << frame << " using key " << 0 << std::endl; + /*auto hr = frameInfo[frame]->keyedMutex->AcquireSync(0, 500); + if (FAILED(hr) || hr == E_FAIL || hr == WAIT_ABANDONED || hr == WAIT_TIMEOUT) { + std::cerr << "RenderThread: could not lock buffer for frame " << frame << std::endl; + switch (hr) { + case E_FAIL: + std::cerr << "RenderThread: error == E_FAIL" << std::endl; + break; + case WAIT_ABANDONED: + std::cerr << "RenderThread: error == WAIT_ABANDONED" << std::endl; + break; + case WAIT_TIMEOUT: + std::cerr << "RenderThread: error == WAIT_TIMEOUT" << std::endl; + break; + default: + std::cerr << "RenderThread: error == (unknown error type: " << hr << ")" << std::endl; + break; + } + osvrDestroyRenderManager(s_render); + return; + }*/ + + const auto n = static_cast(numRenderInfo); // Render into each buffer using the specified information. for (int i = 0; i < n; ++i) { - RenderViewD3D11(s_renderInfo[i], s_renderBuffers[i].colorBufferView, - i); + RenderViewD3D11(s_renderInfo[i], frameInfo[frame]->renderBuffers[i].colorBufferView, + i, frame); } + // Grab and lock the mutex, so that we will be able to render + // to it whether or not RenderManager locks it on our behalf. + // it will not be auto-locked when we're in the non-ATW case. + //std::cout << "RenderThread: Unlocking buffer for frame " << frame << " using key " << 1 << std::endl; + /*hr = frameInfo[frame]->keyedMutex->ReleaseSync(0); + if (FAILED(hr)) { + std::cerr << "RenderThread: could not unlock buffer for frame " << frame << std::endl; + osvrDestroyRenderManager(s_render); + return; + }*/ + // Send the rendered results to the screen OSVR_RenderManagerPresentState presentState; if ((OSVR_RETURN_SUCCESS != @@ -2045,14 +2237,25 @@ inline void DoRender() { "render buffers"); ShutdownRenderManager(); } - OSVR_ViewportDescription fullView; - fullView.left = fullView.lower = 0; - fullView.width = fullView.height = 1; + // create normalized cropping viewports for side-by-side rendering to a single render target + std::vector NVCPs; + double fraction = 1.0 / s_renderInfo.size(); + for (size_t i = 0; i < s_renderInfo.size(); i++) { + OSVR_ViewportDescription v; + v.left = fraction * i; + v.lower = 0.0; + v.width = fraction; + v.height = 1; + NVCPs.push_back(v); + } + OSVR_ViewportDescription fullView; + fullView.left = fullView.lower = 0; + fullView.width = fullView.height = 1; for (size_t i = 0; i < numRenderInfo; i++) { if ((OSVR_RETURN_SUCCESS != osvrRenderManagerPresentRenderBufferD3D11( - presentState, s_renderBuffers[i], s_renderInfo[i], - fullView))) { + presentState, frameInfo[frame]->renderBuffers[i], s_renderInfo[i], + fullView))) { DebugLog( "[OSVR Rendering Plugin] Could not present render buffer "); ShutdownRenderManager(); @@ -2066,6 +2269,9 @@ inline void DoRender() { "render buffers"); ShutdownRenderManager(); } + + iterations++; + break; } #endif // SUPPORT_D3D11 @@ -2120,14 +2326,15 @@ void UNITY_INTERFACE_API OnRenderEvent(int eventID) { break; case kOsvrEventID_Update: #if UNITY_WIN - UpdateRenderInfoCollection(); + UpdateRenderInfo(); #endif break; - case kOsvrEventID_SetRoomRotationUsingHead: - SetRoomRotationUsingHead(); + case kOsvrEventID_ConstructBuffers: + ConstructRenderBuffers(); + // SetRoomRotationUsingHead(); break; case kOsvrEventID_ClearRoomToWorldTransform: - ClearRoomToWorldTransform(); + // ClearRoomToWorldTransform(); break; default: break; diff --git a/OsvrRenderingPlugin.h b/OsvrRenderingPlugin.h index aed78ec..6566772 100644 --- a/OsvrRenderingPlugin.h +++ b/OsvrRenderingPlugin.h @@ -66,7 +66,7 @@ UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API OnRenderEvent(int eventID); /// @todo should return OSVR_ReturnCode UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API -SetColorBufferFromUnity(void *texturePtr, std::uint8_t eye); +SetColorBufferFromUnity(void *texturePtr, std::uint8_t eye, std::uint8_t buffer); UNITY_INTERFACE_EXPORT void UNITY_INTERFACE_API SetFarClipDistance(double distance); From 25563a545dc925307f60a50fe02e8b17f8af50f2 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Wed, 6 Dec 2017 21:07:14 -0500 Subject: [PATCH 38/43] Comments out DebugLog from Shutdown Event to avoid crash --- OsvrRenderingPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index bd04a15..db002e3 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -446,7 +446,7 @@ OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) { } case kUnityGfxDeviceEventShutdown: { - DebugLog("[OSVR Rendering Plugin] OnGraphicsDeviceEvent(Shutdown).\n"); + // DebugLog("[OSVR Rendering Plugin] OnGraphicsDeviceEvent(Shutdown).\n"); /// Here, we want to dispatch before we reset the device type, so the /// right device type gets shut down. Thus we return instead of break. dispatchEventToRenderer(s_deviceType, eventType); From 376a6ee4e5cb40a5aec7f836e8c32140393aea1b Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Wed, 6 Dec 2017 21:18:00 -0500 Subject: [PATCH 39/43] Cleaned up shutdown process --- OsvrRenderingPlugin.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index db002e3..a7d6fef 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -520,9 +520,8 @@ inline void UpdateRenderInfo() { if ((OSVR_RETURN_SUCCESS != osvrRenderManagerGetNumRenderInfo( s_render, renderParams, &numRenderInfo))) { - std::cerr << "Could not get context number of render infos." - << std::endl; - osvrDestroyRenderManager(s_render); + DebugLog("[OSVR Rendering Plugin] Could not get context number of render infos."); + ShutdownRenderManager(); return; } @@ -531,9 +530,8 @@ inline void UpdateRenderInfo() { OSVR_RenderInfoD3D11 info; if ((OSVR_RETURN_SUCCESS != osvrRenderManagerGetRenderInfoD3D11( s_renderD3D, i, renderParams, &info))) { - std::cerr << "Could not get render info " << i - << std::endl; - osvrDestroyRenderManager(s_render); + DebugLog("[OSVR Rendering Plugin] Could not get render info " + i); + ShutdownRenderManager(); return; } s_renderInfo.push_back(info); @@ -1448,8 +1446,10 @@ void UNITY_INTERFACE_API ShutdownRenderManager() { if (s_render != nullptr) { osvrDestroyRenderManager(s_render); s_render = nullptr; - s_rightEyeTexturePtr = nullptr; s_leftEyeTexturePtr = nullptr; + s_leftEyeTexturePtrBuffer2 = nullptr; + s_rightEyeTexturePtr = nullptr; + s_rightEyeTexturePtrBuffer2 = nullptr; } s_clientContext = nullptr; #endif @@ -1856,26 +1856,26 @@ OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { if ((OSVR_RETURN_SUCCESS != osvrRenderManagerStartRegisterRenderBuffers( ®isterBufferState))) { std::cerr << "Could not start registering render buffers" << std::endl; - osvrDestroyRenderManager(s_render); - return -4; + ShutdownRenderManager(); + return OSVR_RETURN_FAILURE; } for (size_t i = 0; i < frameInfo.size(); i++) { for (int j = 0; j < numRenderInfo; j++) { if ((OSVR_RETURN_SUCCESS != osvrRenderManagerRegisterRenderBufferD3D11( registerBufferState, frameInfo[i]->renderBuffers[j]))) { - std::cerr << "Could not register render buffer " << i << std::endl; - osvrDestroyRenderManager(s_render); - return -5; + DebugLog("[OSVR Rendering Plugin] Could not register render buffer "); + ShutdownRenderManager(); + return OSVR_RETURN_FAILURE; } } } if ((OSVR_RETURN_SUCCESS != osvrRenderManagerFinishRegisterRenderBuffers( s_render, registerBufferState, false))) { - std::cerr << "Could not finish registering render buffers" << std::endl; - osvrDestroyRenderManager(s_render); - return -6; + DebugLog("[OSVR Rendering Plugin] Could not finish registering render buffers"); + ShutdownRenderManager(); + return OSVR_RETURN_FAILURE; } //return applyRenderBufferConstructor(n, ConstructBuffersD3D11, // CleanupBufferD3D11); From 27a0d449710c3984b45b5529e905dff747d8ff66 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Tue, 12 Dec 2017 00:01:52 -0500 Subject: [PATCH 40/43] Fixes crash when switching scenes. --- OsvrRenderingPlugin.cpp | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index a7d6fef..e3d8708 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -323,7 +323,7 @@ inline void DoEventGraphicsDeviceD3D11(UnityGfxDeviceEventType eventType) { case kUnityGfxDeviceEventShutdown: { // Close the Renderer interface cleanly. // This should be handled in ShutdownRenderManager - /// @todo delete library.D3D11; library.D3D11 = nullptr; ? + /// @todo delete library.D3D11; library.D3D11 = nullptr; break; } } @@ -450,7 +450,7 @@ OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) { /// Here, we want to dispatch before we reset the device type, so the /// right device type gets shut down. Thus we return instead of break. dispatchEventToRenderer(s_deviceType, eventType); - s_deviceType.reset(); + // s_deviceType.reset(); return; } @@ -512,9 +512,13 @@ void UNITY_INTERFACE_API UnityPluginUnload() { #if UNITY_WIN inline void UpdateRenderInfo() { + + if (s_render == nullptr) + { + return; + } // Do a call to get the information we need to construct our // color and depth render-to-texture buffers. - OSVR_RenderParams renderParams; osvrRenderManagerGetDefaultRenderParams(&renderParams); @@ -1450,6 +1454,17 @@ void UNITY_INTERFACE_API ShutdownRenderManager() { s_leftEyeTexturePtrBuffer2 = nullptr; s_rightEyeTexturePtr = nullptr; s_rightEyeTexturePtrBuffer2 = nullptr; + //s_renderInfo.clear(); + //s_lastRenderInfo.clear(); + /*for (int i = 0; i < frameInfo.size(); i++) + { + for (int j = 0; j < frameInfo[i]->renderBuffers.size(); j++) + { + frameInfo[i]->renderBuffers[j] = nullptr; + } + + }*/ + frameInfo.clear(); } s_clientContext = nullptr; #endif @@ -1471,7 +1486,8 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context) { DebugLog("[OSVR Rendering Plugin] RenderManager already created, " "but not doing OK. Will shut down before creating again."); - ShutdownRenderManager(); + // ShutdownRenderManager(); + return OSVR_RETURN_SUCCESS; } if (s_clientContext != nullptr) { DebugLog( @@ -1855,7 +1871,7 @@ OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { OSVR_RenderManagerRegisterBufferState registerBufferState; if ((OSVR_RETURN_SUCCESS != osvrRenderManagerStartRegisterRenderBuffers( ®isterBufferState))) { - std::cerr << "Could not start registering render buffers" << std::endl; + DebugLog("[OSVR Rendering Plugin] Could not start registering render buffers"); ShutdownRenderManager(); return OSVR_RETURN_FAILURE; } @@ -2010,7 +2026,7 @@ OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { #else OSVR_Pose3 pose; osvrPose3SetIdentity(&pose); - if (numRenderInfo > 0 && eye <= numRenderInfo - 1) { + if (numRenderInfo > 0 && eye <= numRenderInfo - 1 && s_render != nullptr) { pose = s_lastRenderInfo[eye].pose; lastGoodPose = pose; } else { From 10dfe9e5c14db054fa4d26ea0752d5354c3dff10 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Fri, 22 Dec 2017 12:05:46 -0500 Subject: [PATCH 41/43] Updates to double buffering on Android path --- OsvrRenderingPlugin.cpp | 3275 ++++++++++++++++++++------------------- 1 file changed, 1672 insertions(+), 1603 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index e3d8708..4135056 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -131,18 +131,20 @@ static GLuint gvModelUniformId; static GLuint gFrameBuffer; static GLuint gTextureID; static GLuint gLeftEyeTextureID; +static GLuint gLeftEyeTextureIDBuffer2; static GLuint gRightEyeTextureID; +static GLuint gRightEyeTextureIDBuffer2; static bool gGraphicsInitializedOnce = - false; // if setupGraphics has been called at least once +false; // if setupGraphics has been called at least once static bool gOSVRInitialized = false; static bool gRenderManagerInitialized = false; -typedef struct OSVR_RenderTargetInfo { - GLuint colorBufferName; - GLuint depthBufferName; - GLuint frameBufferName; - GLuint renderBufferName; // @todo - do we need this? -} OSVR_RenderTargetInfo; +typedef struct OSVR_RenderTargetInfoOpenGL { + GLuint colorBufferName; + GLuint depthBufferName; + GLuint frameBufferName; + GLuint renderBufferName; // @todo - do we need this? +} OSVR_RenderTargetInfoOpenGL; static OSVR_ClientContext gClientContext = NULL; static OSVR_ClientInterface gCamera = NULL; static OSVR_ClientInterface gHead = NULL; @@ -151,59 +153,66 @@ static OSVR_ImageBufferElement *gLastFrame = nullptr; static GLuint gLastFrameWidth = 0; static GLuint gLastFrameHeight = 0; static GLubyte *gTextureBuffer = nullptr; -static OSVR_GraphicsLibraryOpenGL gGraphicsLibrary = {0}; +static OSVR_GraphicsLibraryOpenGL gGraphicsLibrary = { 0 }; static OSVR_RenderManager gRenderManager = nullptr; static OSVR_RenderManagerOpenGL gRenderManagerOGL = nullptr; -static OSVR_RenderParams gRenderParams = {0}; -static std::vector buffers; -static std::vector gRenderTargets; +static OSVR_RenderParams gRenderParams = { 0 }; +//static std::vector buffers; +//static std::vector gRenderTargets; static bool contextSet = false; +static jmethodID logmid = nullptr; +struct FrameInfoOpenGL { + // Set up the vector of textures to render to and any framebuffer + // we need to group them. + std::vector renderBuffers; + FrameInfoOpenGL() : renderBuffers(2) + { + } + +}; +static std::vector frameInfoOGL; static const char gVertexShader[] = - "uniform mat4 model;\n" - "uniform mat4 view;\n" - "uniform mat4 projection;\n" - "attribute vec4 vPosition;\n" - "attribute vec4 vColor;\n" - "attribute vec2 vTexCoordinate;\n" - "varying vec2 texCoordinate;\n" - "varying vec4 fragmentColor;\n" - "void main() {\n" - " gl_Position = projection * view * model * vPosition;\n" - " fragmentColor = vColor;\n" - " texCoordinate = vTexCoordinate;\n" - "}\n"; +"uniform mat4 model;\n" +"uniform mat4 view;\n" +"uniform mat4 projection;\n" +"attribute vec4 vPosition;\n" +"attribute vec4 vColor;\n" +"attribute vec2 vTexCoordinate;\n" +"varying vec2 texCoordinate;\n" +"varying vec4 fragmentColor;\n" +"void main() {\n" +" gl_Position = projection * view * model * vPosition;\n" +" fragmentColor = vColor;\n" +" texCoordinate = vTexCoordinate;\n" +"}\n"; static const char gFragmentShader[] = - "precision mediump float;\n" - "uniform sampler2D uTexture;\n" - "varying vec2 texCoordinate;\n" - "varying vec4 fragmentColor;\n" - "void main()\n" - "{\n" - " gl_FragColor = fragmentColor * texture2D(uTexture, texCoordinate);\n" - //" gl_FragColor = texture2D(uTexture, texCoordinate);\n" - "}\n"; +"precision mediump float;\n" +"uniform sampler2D uTexture;\n" +"varying vec2 texCoordinate;\n" +"varying vec4 fragmentColor;\n" +"void main()\n" +"{\n" +" gl_FragColor = fragmentColor * texture2D(uTexture, texCoordinate);\n" +//" gl_FragColor = texture2D(uTexture, texCoordinate);\n" +"}\n"; #else // Windows, Linux, OSX static variables -struct FrameInfo { +struct FrameInfoD3D11 { // Set up the vector of textures to render to and any framebuffer // we need to group them. std::vector renderBuffers; ID3D11Texture2D* depthStencilTexture; ID3D11DepthStencilView* depthStencilView; IDXGIKeyedMutex* keyedMutex; - - // I prefer initialization list form - FrameInfo() : renderBuffers(2) - // vertices default ctor is ok, creates empty vector + FrameInfoD3D11() : renderBuffers(2) { - // use vertices.push_back(...); to fill vertices } }; -static std::vector frameInfo; +static std::vector frameInfo; static OSVR_RenderParams s_renderParams; static OSVR_RenderManager s_render = nullptr; static OSVR_RenderManagerD3D11 s_renderD3D = nullptr; @@ -224,7 +233,7 @@ static std::streambuf *s_oldCerr = nullptr; #endif // defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) #endif // end Windows, Linux, OSX -static int numBuffers = 2; +static int numBuffers = 2; static int iterations = 0; static void *s_leftEyeTexturePtr = nullptr; @@ -245,11 +254,11 @@ GLuint s_frameBuffer; // RenderEvents // Called from Unity with GL.IssuePluginEvent enum RenderEvents { - kOsvrEventID_Render = 0, - kOsvrEventID_Shutdown = 1, - kOsvrEventID_Update = 2, - kOsvrEventID_ConstructBuffers = 3, - kOsvrEventID_ClearRoomToWorldTransform = 4 + kOsvrEventID_Render = 0, + kOsvrEventID_Shutdown = 1, + kOsvrEventID_Update = 2, + kOsvrEventID_ConstructBuffers = 3, + kOsvrEventID_ClearRoomToWorldTransform = 4 }; // -------------------------------------------------------------------------- @@ -261,21 +270,27 @@ void UNITY_INTERFACE_API LinkDebug(DebugFnPtr d) { s_debugLog = d; } // Only for debugging purposes, as this causes some errors at shutdown inline void DebugLog(const char *str) { -//@todo complete logMsg implementation in JNI plugin -// for now just return on Android + //@todo complete logMsg implementation in JNI plugin + // for now just return on Android #if UNITY_ANDROID - return; + if (logmid != nullptr) + { + jstring jstr2 = jniEnvironment->NewStringUTF(str); + jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, + logmid, jstr2); + } + return; #else // all platforms besides Android #if !defined(NDEBUG) || defined(ENABLE_LOGGING) - if (s_debugLog != nullptr) { - s_debugLog(str); - } + if (s_debugLog != nullptr) { + s_debugLog(str); + } #endif // !defined(NDEBUG) || defined(ENABLE_LOGGING) #if defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) - if (s_debugLogFile) { - s_debugLogFile << str << std::endl; - } + if (s_debugLogFile) { + s_debugLogFile << str << std::endl; + } #endif // defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) #endif // all platforms besides Android } @@ -285,9 +300,9 @@ inline void DebugLog(const char *str) { #if UNITY_ANDROID // this OnLoad gets called automatically jint JNI_OnLoad(JavaVM *vm, void *reserved) { - jniEnvironment = 0; - vm->AttachCurrentThread(&jniEnvironment, 0); - return JNI_VERSION_1_6; + jniEnvironment = 0; + vm->AttachCurrentThread(&jniEnvironment, 0); + return JNI_VERSION_1_6; } #endif @@ -298,35 +313,35 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) { // ------------------------------------------------------------------- /// Direct3D 11 setup/teardown code inline void DoEventGraphicsDeviceD3D11(UnityGfxDeviceEventType eventType) { - BOOST_ASSERT_MSG( - s_deviceType, - "Should only be able to get in here with a valid device type."); - BOOST_ASSERT_MSG( - s_deviceType.getDeviceTypeEnum() == OSVRSupportedRenderers::D3D11, - "Should only be able to get in here if using D3D11 device type."); - - switch (eventType) { - case kUnityGfxDeviceEventInitialize: { - IUnityGraphicsD3D11 *d3d11 = - s_UnityInterfaces->Get(); - - // Put the device and context into a structure to let RenderManager - // know to use this one rather than creating its own. - s_libraryD3D.device = d3d11->GetDevice(); - ID3D11DeviceContext *ctx = nullptr; - s_libraryD3D.device->GetImmediateContext(&ctx); - s_libraryD3D.context = ctx; - DebugLog("[OSVR Rendering Plugin] Passed Unity device/context to " - "RenderManager library."); - break; - } - case kUnityGfxDeviceEventShutdown: { - // Close the Renderer interface cleanly. - // This should be handled in ShutdownRenderManager - /// @todo delete library.D3D11; library.D3D11 = nullptr; - break; - } - } + BOOST_ASSERT_MSG( + s_deviceType, + "Should only be able to get in here with a valid device type."); + BOOST_ASSERT_MSG( + s_deviceType.getDeviceTypeEnum() == OSVRSupportedRenderers::D3D11, + "Should only be able to get in here if using D3D11 device type."); + + switch (eventType) { + case kUnityGfxDeviceEventInitialize: { + IUnityGraphicsD3D11 *d3d11 = + s_UnityInterfaces->Get(); + + // Put the device and context into a structure to let RenderManager + // know to use this one rather than creating its own. + s_libraryD3D.device = d3d11->GetDevice(); + ID3D11DeviceContext *ctx = nullptr; + s_libraryD3D.device->GetImmediateContext(&ctx); + s_libraryD3D.context = ctx; + DebugLog("[OSVR Rendering Plugin] Passed Unity device/context to " + "RenderManager library."); + break; + } + case kUnityGfxDeviceEventShutdown: { + // Close the Renderer interface cleanly. + // This should be handled in ShutdownRenderManager + /// @todo delete library.D3D11; library.D3D11 = nullptr; + break; + } + } } #endif // SUPPORT_D3D11 @@ -335,47 +350,47 @@ inline void DoEventGraphicsDeviceD3D11(UnityGfxDeviceEventType eventType) { /// OpenGL setup/teardown code /// @todo OpenGL path not implemented yet inline void DoEventGraphicsDeviceOpenGL(UnityGfxDeviceEventType eventType) { - BOOST_ASSERT_MSG( - s_deviceType, - "Should only be able to get in here with a valid device type."); - BOOST_ASSERT_MSG( - s_deviceType.getDeviceTypeEnum() == OSVRSupportedRenderers::OpenGL, - "Should only be able to get in here if using OpenGL device type."); - - switch (eventType) { - case kUnityGfxDeviceEventInitialize: - DebugLog("OpenGL Initialize Event"); - break; - case kUnityGfxDeviceEventShutdown: - DebugLog("OpenGL Shutdown Event"); - break; - default: - break; - } + BOOST_ASSERT_MSG( + s_deviceType, + "Should only be able to get in here with a valid device type."); + BOOST_ASSERT_MSG( + s_deviceType.getDeviceTypeEnum() == OSVRSupportedRenderers::OpenGL, + "Should only be able to get in here if using OpenGL device type."); + + switch (eventType) { + case kUnityGfxDeviceEventInitialize: + DebugLog("OpenGL Initialize Event"); + break; + case kUnityGfxDeviceEventShutdown: + DebugLog("OpenGL Shutdown Event"); + break; + default: + break; + } } #endif // SUPPORT_OPENGL inline void dispatchEventToRenderer(UnityRendererType renderer, - UnityGfxDeviceEventType eventType) { - if (!renderer) { - DebugLog("[OSVR Rendering Plugin] Current device type not supported"); - return; - } - switch (renderer.getDeviceTypeEnum()) { + UnityGfxDeviceEventType eventType) { + if (!renderer) { + DebugLog("[OSVR Rendering Plugin] Current device type not supported"); + return; + } + switch (renderer.getDeviceTypeEnum()) { #if SUPPORT_D3D11 - case OSVRSupportedRenderers::D3D11: - DoEventGraphicsDeviceD3D11(eventType); - break; + case OSVRSupportedRenderers::D3D11: + DoEventGraphicsDeviceD3D11(eventType); + break; #endif #if SUPPORT_OPENGL - case OSVRSupportedRenderers::OpenGL: - DoEventGraphicsDeviceOpenGL(eventType); - break; + case OSVRSupportedRenderers::OpenGL: + DoEventGraphicsDeviceOpenGL(eventType); + break; #endif - case OSVRSupportedRenderers::EmptyRenderer: - default: - break; - } + case OSVRSupportedRenderers::EmptyRenderer: + default: + break; + } } //@TODO InitSDLGL, ShareContext on OpenGL path @@ -384,90 +399,90 @@ inline void dispatchEventToRenderer(UnityRendererType renderer, /// because it's registered as a callback on plugin load. static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) { - switch (eventType) { - case kUnityGfxDeviceEventInitialize: { + switch (eventType) { + case kUnityGfxDeviceEventInitialize: { #if UNITY_ANDROID - osvrJniWrapperClass = jniEnvironment->FindClass( - "org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class - if (osvrJniWrapperClass == nullptr) { - return; - } else { // if osvrJniWrapperClass found, continue - - // get the Android logger method ID - jmethodID logmid = jniEnvironment->GetStaticMethodID( - osvrJniWrapperClass, "logMsg", - "(Ljava/lang/String;)V"); // find method - // get the method ID for setting the GL context - jmethodID setGlContextId = jniEnvironment->GetStaticMethodID( - osvrJniWrapperClass, "setUnityMainContext", - "()J"); // find method - if (setGlContextId == nullptr) - return; - else { - jlong currentEglContextHandle = - jniEnvironment->CallStaticLongMethod( - osvrJniWrapperClass, setGlContextId); // call mathod - // example code for logging the context ID - /*long myLongValue = (long)currentEglContextHandle; - std::string stringy = "[OSVR-Unity-Android] setCurrentContext - with handle: " + std::to_string(myLongValue); - jstring jstr2 = jniEnvironment->NewStringUTF(stringy.c_str()); - jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, - logmid, jstr2);*/ - contextSet = true; - } - // get the display width and height via JNI - jmethodID getWidthMID = jniEnvironment->GetStaticMethodID( - osvrJniWrapperClass, "getDisplayWidth", "()I"); // find method - jmethodID getHeightMID = jniEnvironment->GetStaticMethodID( - osvrJniWrapperClass, "getDisplayHeight", "()I"); // find method - if (getWidthMID == nullptr || getHeightMID == nullptr) - return; - else { - jint displayWidth = jniEnvironment->CallStaticIntMethod( - osvrJniWrapperClass, getWidthMID); // call method - jint displayHeight = jniEnvironment->CallStaticIntMethod( - osvrJniWrapperClass, getHeightMID); // call method - gWidth = (int)displayWidth; - gHeight = (int)displayHeight; - } - } + osvrJniWrapperClass = jniEnvironment->FindClass( + "org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class + if (osvrJniWrapperClass == nullptr) { + return; + } + else { // if osvrJniWrapperClass found, continue + + // get the Android logger method ID + logmid = jniEnvironment->GetStaticMethodID( + osvrJniWrapperClass, "logMsg", + "(Ljava/lang/String;)V"); // find method + // get the method ID for setting the GL context + jmethodID setGlContextId = jniEnvironment->GetStaticMethodID( + osvrJniWrapperClass, "setUnityMainContext", + "()J"); // find method + if (setGlContextId == nullptr) + return; + else { + jlong currentEglContextHandle = + jniEnvironment->CallStaticLongMethod( + osvrJniWrapperClass, setGlContextId); // call mathod + // example code for logging the context ID + /*long myLongValue = (long)currentEglContextHandle; + std::string stringy = "[OSVR-Unity-Android] setCurrentContext with handle : " + std::to_string(myLongValue); + jstring jstr2 = jniEnvironment->NewStringUTF(stringy.c_str()); + jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, + logmid, jstr2);*/ + contextSet = true; + } + // get the display width and height via JNI + jmethodID getWidthMID = jniEnvironment->GetStaticMethodID( + osvrJniWrapperClass, "getDisplayWidth", "()I"); // find method + jmethodID getHeightMID = jniEnvironment->GetStaticMethodID( + osvrJniWrapperClass, "getDisplayHeight", "()I"); // find method + if (getWidthMID == nullptr || getHeightMID == nullptr) + return; + else { + jint displayWidth = jniEnvironment->CallStaticIntMethod( + osvrJniWrapperClass, getWidthMID); // call method + jint displayHeight = jniEnvironment->CallStaticIntMethod( + osvrJniWrapperClass, getHeightMID); // call method + gWidth = (int)displayWidth; + gHeight = (int)displayHeight; + } + } #endif - //@todo windows, osx context sharing - DebugLog( - "[OSVR Rendering Plugin] OnGraphicsDeviceEvent(Initialize).\n"); - s_deviceType = s_Graphics->GetRenderer(); - if (!s_deviceType) { - DebugLog("[OSVR Rendering Plugin] " - "OnGraphicsDeviceEvent(Initialize): New device type is " - "not supported!\n"); - } - break; - } - - case kUnityGfxDeviceEventShutdown: { - // DebugLog("[OSVR Rendering Plugin] OnGraphicsDeviceEvent(Shutdown).\n"); - /// Here, we want to dispatch before we reset the device type, so the - /// right device type gets shut down. Thus we return instead of break. - dispatchEventToRenderer(s_deviceType, eventType); - // s_deviceType.reset(); - return; - } - - case kUnityGfxDeviceEventBeforeReset: { - DebugLog( - "[OSVR Rendering Plugin] OnGraphicsDeviceEvent(BeforeReset).\n"); - break; - } - - case kUnityGfxDeviceEventAfterReset: { - DebugLog( - "[OSVR Rendering Plugin] OnGraphicsDeviceEvent(AfterReset).\n"); - break; - } - } - - dispatchEventToRenderer(s_deviceType, eventType); + //@todo windows, osx context sharing + DebugLog( + "[OSVR Rendering Plugin] OnGraphicsDeviceEvent(Initialize).\n"); + s_deviceType = s_Graphics->GetRenderer(); + if (!s_deviceType) { + DebugLog("[OSVR Rendering Plugin] " + "OnGraphicsDeviceEvent(Initialize): New device type is " + "not supported!\n"); + } + break; + } + + case kUnityGfxDeviceEventShutdown: { + // DebugLog("[OSVR Rendering Plugin] OnGraphicsDeviceEvent(Shutdown).\n"); + /// Here, we want to dispatch before we reset the device type, so the + /// right device type gets shut down. Thus we return instead of break. + dispatchEventToRenderer(s_deviceType, eventType); + // s_deviceType.reset(); + return; + } + + case kUnityGfxDeviceEventBeforeReset: { + DebugLog( + "[OSVR Rendering Plugin] OnGraphicsDeviceEvent(BeforeReset).\n"); + break; + } + + case kUnityGfxDeviceEventAfterReset: { + DebugLog( + "[OSVR Rendering Plugin] OnGraphicsDeviceEvent(AfterReset).\n"); + break; + } + } + + dispatchEventToRenderer(s_deviceType, eventType); } // -------------------------------------------------------------------------- @@ -475,44 +490,44 @@ OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) { void UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces *unityInterfaces) { #if UNITY_WIN #if defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) - s_debugLogFile.open("RenderPluginLog.txt"); + s_debugLogFile.open("RenderPluginLog.txt"); - // Capture std::cout and std::cerr from RenderManager. - if (s_debugLogFile) { - s_oldCout = std::cout.rdbuf(); - std::cout.rdbuf(s_debugLogFile.rdbuf()); + // Capture std::cout and std::cerr from RenderManager. + if (s_debugLogFile) { + s_oldCout = std::cout.rdbuf(); + std::cout.rdbuf(s_debugLogFile.rdbuf()); - s_oldCerr = std::cerr.rdbuf(); - std::cerr.rdbuf(s_debugLogFile.rdbuf()); - } + s_oldCerr = std::cerr.rdbuf(); + std::cerr.rdbuf(s_debugLogFile.rdbuf()); + } #endif // defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) #endif // UNITY_WIN - s_UnityInterfaces = unityInterfaces; - s_Graphics = s_UnityInterfaces->Get(); - s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent); + s_UnityInterfaces = unityInterfaces; + s_Graphics = s_UnityInterfaces->Get(); + s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent); - // Run OnGraphicsDeviceEvent(initialize) manually on plugin load - OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize); + // Run OnGraphicsDeviceEvent(initialize) manually on plugin load + OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize); } void UNITY_INTERFACE_API UnityPluginUnload() { - s_Graphics->UnregisterDeviceEventCallback(OnGraphicsDeviceEvent); - OnGraphicsDeviceEvent(kUnityGfxDeviceEventShutdown); + s_Graphics->UnregisterDeviceEventCallback(OnGraphicsDeviceEvent); + OnGraphicsDeviceEvent(kUnityGfxDeviceEventShutdown); #if UNITY_WIN #if defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) - if (s_debugLogFile) { - // Restore the buffers - std::cout.rdbuf(s_oldCout); - std::cerr.rdbuf(s_oldCerr); - s_debugLogFile.close(); - } + if (s_debugLogFile) { + // Restore the buffers + std::cout.rdbuf(s_oldCout); + std::cerr.rdbuf(s_oldCerr); + s_debugLogFile.close(); + } #endif // defined(ENABLE_LOGGING) && defined(ENABLE_LOGFILE) #endif // UNITY_WIN } #if UNITY_WIN inline void UpdateRenderInfo() { - + if (s_render == nullptr) { return; @@ -556,7 +571,7 @@ inline void UpdateRenderInfo() { // so your callbacks may be called during its execution! /// @todo does this actually get called from anywhere or is it dead code? void SetRoomRotationUsingHead() { /* s_renderD3D-> SetRoomRotationUsingHead(); - */ + */ } // Clears/resets the internal "room to world" transformation back to an @@ -570,887 +585,912 @@ void ClearRoomToWorldTransform() { /*s_render->ClearRoomToWorldTransform(); */ #if UNITY_ANDROID inline osvr::renderkit::OSVR_ProjectionMatrix ConvertProjectionMatrix(::OSVR_ProjectionMatrix matrix) { - osvr::renderkit::OSVR_ProjectionMatrix ret = {0}; - ret.bottom = matrix.bottom; - ret.top = matrix.top; - ret.left = matrix.left; - ret.right = matrix.right; - ret.nearClip = matrix.nearClip; - ret.farClip = matrix.farClip; - return ret; + osvr::renderkit::OSVR_ProjectionMatrix ret = { 0 }; + ret.bottom = matrix.bottom; + ret.top = matrix.top; + ret.left = matrix.left; + ret.right = matrix.right; + ret.nearClip = matrix.nearClip; + ret.farClip = matrix.farClip; + return ret; } static void checkReturnCode(OSVR_ReturnCode returnCode, const char *msg) { - if (returnCode != OSVR_RETURN_SUCCESS) { - // LOGI("[OSVR] OSVR method returned a failure: %s", msg); - throw std::runtime_error(msg); - } + if (returnCode != OSVR_RETURN_SUCCESS) { + // LOGI("[OSVR] OSVR method returned a failure: %s", msg); + throw std::runtime_error(msg); + } } // RAII wrapper around the RenderManager collection APIs for OpenGL class RenderInfoCollectionOpenGL { - private: - OSVR_RenderManager mRenderManager = nullptr; - OSVR_RenderInfoCollection mRenderInfoCollection = nullptr; - OSVR_RenderParams mRenderParams = {0}; - - public: - RenderInfoCollectionOpenGL(OSVR_RenderManager renderManager, - OSVR_RenderParams renderParams) - : mRenderManager(renderManager), mRenderParams(renderParams) { - OSVR_ReturnCode rc; - rc = osvrRenderManagerGetRenderInfoCollection( - mRenderManager, mRenderParams, &mRenderInfoCollection); - checkReturnCode( - rc, "osvrRenderManagerGetRenderInfoCollection call failed."); - } - - OSVR_RenderInfoCount getNumRenderInfo() { - OSVR_RenderInfoCount ret; - OSVR_ReturnCode rc; - rc = osvrRenderManagerGetNumRenderInfoInCollection( - mRenderInfoCollection, &ret); - checkReturnCode( - rc, "osvrRenderManagerGetNumRenderInfoInCollection call failed."); - return ret; - } - - OSVR_RenderInfoOpenGL getRenderInfo(OSVR_RenderInfoCount index) { - if (index < 0 || index >= getNumRenderInfo()) { - const static char *err = "getRenderInfo called with invalid index"; - // LOGE(err); - throw std::runtime_error(err); - } - OSVR_RenderInfoOpenGL ret; - OSVR_ReturnCode rc; - rc = osvrRenderManagerGetRenderInfoFromCollectionOpenGL( - mRenderInfoCollection, index, &ret); - checkReturnCode( - rc, - "osvrRenderManagerGetRenderInfoFromCollectionOpenGL call failed."); - return ret; - } - - ~RenderInfoCollectionOpenGL() { - if (mRenderInfoCollection) { - osvrRenderManagerReleaseRenderInfoCollection(mRenderInfoCollection); - } - } +private: + OSVR_RenderManager mRenderManager = nullptr; + OSVR_RenderInfoCollection mRenderInfoCollection = nullptr; + OSVR_RenderParams mRenderParams = { 0 }; + +public: + RenderInfoCollectionOpenGL(OSVR_RenderManager renderManager, + OSVR_RenderParams renderParams) + : mRenderManager(renderManager), mRenderParams(renderParams) { + OSVR_ReturnCode rc; + rc = osvrRenderManagerGetRenderInfoCollection( + mRenderManager, mRenderParams, &mRenderInfoCollection); + checkReturnCode( + rc, "osvrRenderManagerGetRenderInfoCollection call failed."); + } + + OSVR_RenderInfoCount getNumRenderInfo() { + OSVR_RenderInfoCount ret; + OSVR_ReturnCode rc; + rc = osvrRenderManagerGetNumRenderInfoInCollection( + mRenderInfoCollection, &ret); + checkReturnCode( + rc, "osvrRenderManagerGetNumRenderInfoInCollection call failed."); + return ret; + } + + OSVR_RenderInfoOpenGL getRenderInfo(OSVR_RenderInfoCount index) { + if (index < 0 || index >= getNumRenderInfo()) { + const static char *err = "getRenderInfo called with invalid index"; + // LOGE(err); + throw std::runtime_error(err); + } + OSVR_RenderInfoOpenGL ret; + OSVR_ReturnCode rc; + rc = osvrRenderManagerGetRenderInfoFromCollectionOpenGL( + mRenderInfoCollection, index, &ret); + checkReturnCode( + rc, + "osvrRenderManagerGetRenderInfoFromCollectionOpenGL call failed."); + return ret; + } + + ~RenderInfoCollectionOpenGL() { + if (mRenderInfoCollection) { + osvrRenderManagerReleaseRenderInfoCollection(mRenderInfoCollection); + } + } }; static void checkGlError(const char *op) { - std::stringstream ss; - for (GLint error = glGetError(); error; error = glGetError()) { - // gluErrorString without glu - std::string errorString; - switch (error) { - case GL_NO_ERROR: - errorString = "GL_NO_ERROR"; - break; - case GL_INVALID_ENUM: - errorString = "GL_INVALID_ENUM"; - break; - case GL_INVALID_VALUE: - errorString = "GL_INVALID_VALUE"; - break; - case GL_INVALID_OPERATION: - errorString = "GL_INVALID_OPERATION"; - break; - case GL_INVALID_FRAMEBUFFER_OPERATION: - errorString = "GL_INVALID_FRAMEBUFFER_OPERATION"; - break; - case GL_OUT_OF_MEMORY: - errorString = "GL_OUT_OF_MEMORY"; - break; - default: - errorString = "(unknown error)"; - break; - } - // LOGI("after %s() glError (%s)\n", op, errorString.c_str()); - } + std::stringstream ss; + for (GLint error = glGetError(); error; error = glGetError()) { + // gluErrorString without glu + std::string errorString; + switch (error) { + case GL_NO_ERROR: + errorString = "GL_NO_ERROR"; + break; + case GL_INVALID_ENUM: + errorString = "GL_INVALID_ENUM"; + break; + case GL_INVALID_VALUE: + errorString = "GL_INVALID_VALUE"; + break; + case GL_INVALID_OPERATION: + errorString = "GL_INVALID_OPERATION"; + break; + case GL_INVALID_FRAMEBUFFER_OPERATION: + errorString = "GL_INVALID_FRAMEBUFFER_OPERATION"; + break; + case GL_OUT_OF_MEMORY: + errorString = "GL_OUT_OF_MEMORY"; + break; + default: + errorString = "(unknown error)"; + break; + } + // LOGI("after %s() glError (%s)\n", op, errorString.c_str()); + } } class PassThroughOpenGLContextImpl { - OSVR_OpenGLToolkitFunctions toolkit; - int mWidth; - int mHeight; - - static void createImpl(void *data) {} - static void destroyImpl(void *data) { - delete ((PassThroughOpenGLContextImpl *)data); - } - static OSVR_CBool addOpenGLContextImpl(void *data, - const OSVR_OpenGLContextParams *p) { - return ((PassThroughOpenGLContextImpl *)data)->addOpenGLContext(p); - } - static OSVR_CBool removeOpenGLContextsImpl(void *data) { - return ((PassThroughOpenGLContextImpl *)data)->removeOpenGLContexts(); - } - static OSVR_CBool makeCurrentImpl(void *data, size_t display) { - return ((PassThroughOpenGLContextImpl *)data)->makeCurrent(display); - } - static OSVR_CBool swapBuffersImpl(void *data, size_t display) { - return ((PassThroughOpenGLContextImpl *)data)->swapBuffers(display); - } - static OSVR_CBool setVerticalSyncImpl(void *data, OSVR_CBool verticalSync) { - return ((PassThroughOpenGLContextImpl *)data) - ->setVerticalSync(verticalSync); - } - static OSVR_CBool handleEventsImpl(void *data) { - return ((PassThroughOpenGLContextImpl *)data)->handleEvents(); - } - static OSVR_CBool getDisplayFrameBufferImpl(void *data, size_t display, - GLuint *displayFrameBufferOut) { - return ((PassThroughOpenGLContextImpl *)data) - ->getDisplayFrameBuffer(display, displayFrameBufferOut); - } - static OSVR_CBool getDisplaySizeOverrideImpl(void *data, size_t display, - int *width, int *height) { - return ((PassThroughOpenGLContextImpl *)data) - ->getDisplaySizeOverride(display, width, height); - } - - public: - PassThroughOpenGLContextImpl() { - memset(&toolkit, 0, sizeof(toolkit)); - toolkit.size = sizeof(toolkit); - toolkit.data = this; - - toolkit.create = createImpl; - toolkit.destroy = destroyImpl; - toolkit.addOpenGLContext = addOpenGLContextImpl; - toolkit.removeOpenGLContexts = removeOpenGLContextsImpl; - toolkit.makeCurrent = makeCurrentImpl; - toolkit.swapBuffers = swapBuffersImpl; - toolkit.setVerticalSync = setVerticalSyncImpl; - toolkit.handleEvents = handleEventsImpl; - toolkit.getDisplaySizeOverride = getDisplaySizeOverrideImpl; - toolkit.getDisplayFrameBuffer = getDisplayFrameBufferImpl; - } - - ~PassThroughOpenGLContextImpl() {} - - const OSVR_OpenGLToolkitFunctions *getToolkit() const { return &toolkit; } - - bool addOpenGLContext(const OSVR_OpenGLContextParams *p) { return true; } - - bool removeOpenGLContexts() { return true; } - - bool makeCurrent(size_t display) { return true; } - - bool swapBuffers(size_t display) { return true; } - - bool setVerticalSync(bool verticalSync) { return true; } - - bool handleEvents() { return true; } - bool getDisplayFrameBuffer(size_t display, GLuint *displayFrameBufferOut) { - *displayFrameBufferOut = gFrameBuffer; - return true; - } - - bool getDisplaySizeOverride(size_t display, int *width, int *height) { - *width = gWidth; - *height = gHeight; - return false; - } + OSVR_OpenGLToolkitFunctions toolkit; + int mWidth; + int mHeight; + + static void createImpl(void *data) {} + static void destroyImpl(void *data) { + delete ((PassThroughOpenGLContextImpl *)data); + } + static OSVR_CBool addOpenGLContextImpl(void *data, + const OSVR_OpenGLContextParams *p) { + return ((PassThroughOpenGLContextImpl *)data)->addOpenGLContext(p); + } + static OSVR_CBool removeOpenGLContextsImpl(void *data) { + return ((PassThroughOpenGLContextImpl *)data)->removeOpenGLContexts(); + } + static OSVR_CBool makeCurrentImpl(void *data, size_t display) { + return ((PassThroughOpenGLContextImpl *)data)->makeCurrent(display); + } + static OSVR_CBool swapBuffersImpl(void *data, size_t display) { + return ((PassThroughOpenGLContextImpl *)data)->swapBuffers(display); + } + static OSVR_CBool setVerticalSyncImpl(void *data, OSVR_CBool verticalSync) { + return ((PassThroughOpenGLContextImpl *)data) + ->setVerticalSync(verticalSync); + } + static OSVR_CBool handleEventsImpl(void *data) { + return ((PassThroughOpenGLContextImpl *)data)->handleEvents(); + } + static OSVR_CBool getDisplayFrameBufferImpl(void *data, size_t display, + GLuint *displayFrameBufferOut) { + return ((PassThroughOpenGLContextImpl *)data) + ->getDisplayFrameBuffer(display, displayFrameBufferOut); + } + static OSVR_CBool getDisplaySizeOverrideImpl(void *data, size_t display, + int *width, int *height) { + return ((PassThroughOpenGLContextImpl *)data) + ->getDisplaySizeOverride(display, width, height); + } + +public: + PassThroughOpenGLContextImpl() { + memset(&toolkit, 0, sizeof(toolkit)); + toolkit.size = sizeof(toolkit); + toolkit.data = this; + + toolkit.create = createImpl; + toolkit.destroy = destroyImpl; + toolkit.addOpenGLContext = addOpenGLContextImpl; + toolkit.removeOpenGLContexts = removeOpenGLContextsImpl; + toolkit.makeCurrent = makeCurrentImpl; + toolkit.swapBuffers = swapBuffersImpl; + toolkit.setVerticalSync = setVerticalSyncImpl; + toolkit.handleEvents = handleEventsImpl; + toolkit.getDisplaySizeOverride = getDisplaySizeOverrideImpl; + toolkit.getDisplayFrameBuffer = getDisplayFrameBufferImpl; + } + + ~PassThroughOpenGLContextImpl() {} + + const OSVR_OpenGLToolkitFunctions *getToolkit() const { return &toolkit; } + + bool addOpenGLContext(const OSVR_OpenGLContextParams *p) { return true; } + + bool removeOpenGLContexts() { return true; } + + bool makeCurrent(size_t display) { return true; } + + bool swapBuffers(size_t display) { return true; } + + bool setVerticalSync(bool verticalSync) { return true; } + + bool handleEvents() { return true; } + bool getDisplayFrameBuffer(size_t display, GLuint *displayFrameBufferOut) { + *displayFrameBufferOut = gFrameBuffer; + return true; + } + + bool getDisplaySizeOverride(size_t display, int *width, int *height) { + *width = gWidth; + *height = gHeight; + return false; + } }; static GLuint loadShader(GLenum shaderType, const char *pSource) { - GLuint shader = glCreateShader(shaderType); - if (shader) { - glShaderSource(shader, 1, &pSource, NULL); - glCompileShader(shader); - GLint compiled = 0; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); - if (!compiled) { - GLint infoLen = 0; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); - if (infoLen) { - char *buf = (char *)malloc(infoLen); - if (buf) { - glGetShaderInfoLog(shader, infoLen, NULL, buf); - // LOGE("Could not compile shader %d:\n%s\n", - // shaderType, buf); - free(buf); - } - glDeleteShader(shader); - shader = 0; - } - } - } - return shader; + GLuint shader = glCreateShader(shaderType); + if (shader) { + glShaderSource(shader, 1, &pSource, NULL); + glCompileShader(shader); + GLint compiled = 0; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (!compiled) { + GLint infoLen = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen) { + char *buf = (char *)malloc(infoLen); + if (buf) { + glGetShaderInfoLog(shader, infoLen, NULL, buf); + // LOGE("Could not compile shader %d:\n%s\n", + // shaderType, buf); + free(buf); + } + glDeleteShader(shader); + shader = 0; + } + } + } + return shader; } static GLuint createProgram(const char *pVertexSource, - const char *pFragmentSource) { - GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); - if (!vertexShader) { - return 0; - } - - GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); - if (!pixelShader) { - return 0; - } - - GLuint program = glCreateProgram(); - if (program) { - glAttachShader(program, vertexShader); - checkGlError("glAttachShader"); - - glAttachShader(program, pixelShader); - checkGlError("glAttachShader"); - - glBindAttribLocation(program, 0, "vPosition"); - glBindAttribLocation(program, 1, "vColor"); - glBindAttribLocation(program, 2, "vTexCoordinate"); - - glLinkProgram(program); - GLint linkStatus = GL_FALSE; - glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); - if (linkStatus != GL_TRUE) { - GLint bufLength = 0; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); - if (bufLength) { - char *buf = (char *)malloc(bufLength); - if (buf) { - glGetProgramInfoLog(program, bufLength, NULL, buf); - // LOGE("Could not link program:\n%s\n", buf); - free(buf); - } - } - glDeleteProgram(program); - program = 0; - } - } - return program; + const char *pFragmentSource) { + GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource); + if (!vertexShader) { + return 0; + } + + GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource); + if (!pixelShader) { + return 0; + } + + GLuint program = glCreateProgram(); + if (program) { + glAttachShader(program, vertexShader); + checkGlError("glAttachShader"); + + glAttachShader(program, pixelShader); + checkGlError("glAttachShader"); + + glBindAttribLocation(program, 0, "vPosition"); + glBindAttribLocation(program, 1, "vColor"); + glBindAttribLocation(program, 2, "vTexCoordinate"); + + glLinkProgram(program); + GLint linkStatus = GL_FALSE; + glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); + if (linkStatus != GL_TRUE) { + GLint bufLength = 0; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); + if (bufLength) { + char *buf = (char *)malloc(bufLength); + if (buf) { + glGetProgramInfoLog(program, bufLength, NULL, buf); + // LOGE("Could not link program:\n%s\n", buf); + free(buf); + } + } + glDeleteProgram(program); + program = 0; + } + } + return program; } static GLuint createTexture(GLuint width, GLuint height) { - GLuint ret; - glGenTextures(1, &ret); - checkGlError("glGenTextures"); - - glBindTexture(GL_TEXTURE_2D, ret); - checkGlError("glBindTexture"); - - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - // // DEBUG CODE - should be passing null here, but then texture is - // always black. - GLubyte *dummyBuffer = new GLubyte[width * height * 4]; - for (GLuint i = 0; i < width * height * 4; i++) { - dummyBuffer[i] = (i % 4 ? 100 : 255); - } - - // This dummy texture successfully makes it into the texture and renders, - // but subsequent - // calls to glTexSubImage2D don't appear to do anything. - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, - GL_UNSIGNED_BYTE, dummyBuffer); - checkGlError("glTexImage2D"); - delete[] dummyBuffer; - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - checkGlError("glTexParameteri"); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - checkGlError("glTexParameteri"); - return ret; + GLuint ret; + glGenTextures(1, &ret); + checkGlError("glGenTextures"); + + glBindTexture(GL_TEXTURE_2D, ret); + checkGlError("glBindTexture"); + + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + // // DEBUG CODE - should be passing null here, but then texture is + // always black. + GLubyte *dummyBuffer = new GLubyte[width * height * 4]; + for (GLuint i = 0; i < width * height * 4; i++) { + dummyBuffer[i] = (i % 4 ? 100 : 255); + } + + // This dummy texture successfully makes it into the texture and renders, + // but subsequent + // calls to glTexSubImage2D don't appear to do anything. + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, dummyBuffer); + checkGlError("glTexImage2D"); + delete[] dummyBuffer; + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + checkGlError("glTexParameteri"); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + checkGlError("glTexParameteri"); + return ret; } static void updateTexture(GLuint width, GLuint height, GLubyte *data) { - glBindTexture(GL_TEXTURE_2D, gTextureID); - checkGlError("glBindTexture"); + glBindTexture(GL_TEXTURE_2D, gTextureID); + checkGlError("glBindTexture"); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_PACK_ALIGNMENT, 1); - // @todo use glTexSubImage2D to be faster here, but add check to make sure - // height/width are the same. - // glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, - // GL_UNSIGNED_BYTE, data); - // checkGlError("glTexSubImage2D"); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, - GL_UNSIGNED_BYTE, data); - checkGlError("glTexImage2D"); + // @todo use glTexSubImage2D to be faster here, but add check to make sure + // height/width are the same. + // glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, + // GL_UNSIGNED_BYTE, data); + // checkGlError("glTexSubImage2D"); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, data); + checkGlError("glTexImage2D"); } static void imagingCallback(void *userdata, const OSVR_TimeValue *timestamp, - const OSVR_ImagingReport *report) { + const OSVR_ImagingReport *report) { - OSVR_ClientContext *ctx = (OSVR_ClientContext *)userdata; + OSVR_ClientContext *ctx = (OSVR_ClientContext *)userdata; - gReportNumber++; - GLuint width = report->state.metadata.width; - GLuint height = report->state.metadata.height; - gLastFrameWidth = width; - gLastFrameHeight = height; - GLuint size = width * height * 4; + gReportNumber++; + GLuint width = report->state.metadata.width; + GLuint height = report->state.metadata.height; + gLastFrameWidth = width; + gLastFrameHeight = height; + GLuint size = width * height * 4; - gLastFrame = report->state.data; + gLastFrame = report->state.data; } #if SUPPORT_OPENGL -inline GLuint GetEyeTextureOpenGL(int eye) { - return (eye == 0) ? gLeftEyeTextureID : gRightEyeTextureID; +inline GLuint GetEyeTextureOpenGL(int eye, int buffer = 0) { + if (buffer == 0) + { + return (eye == 0) ? gLeftEyeTextureID : gRightEyeTextureID; + + } + else + { + return (eye == 0) ? gLeftEyeTextureIDBuffer2 : gRightEyeTextureIDBuffer2; + + } } #endif static bool setupRenderTextures(OSVR_RenderManager renderManager) { - try { - OSVR_ReturnCode rc; - rc = osvrRenderManagerGetDefaultRenderParams(&gRenderParams); - checkReturnCode(rc, - "osvrRenderManagerGetDefaultRenderParams call failed."); - - gRenderParams.farClipDistanceMeters = 1000000.0f; - gRenderParams.nearClipDistanceMeters = 0.0000001f; - RenderInfoCollectionOpenGL renderInfo(renderManager, gRenderParams); - - OSVR_RenderManagerRegisterBufferState state; - rc = osvrRenderManagerStartRegisterRenderBuffers(&state); - checkReturnCode( - rc, "osvrRenderManagerStartRegisterRenderBuffers call failed."); - - for (OSVR_RenderInfoCount i = 0; i < renderInfo.getNumRenderInfo(); - i++) { - OSVR_RenderInfoOpenGL currentRenderInfo = - renderInfo.getRenderInfo(i); - - // Determine the appropriate size for the frame buffer to be used - // for - // all eyes when placed horizontally size by side. - int width = static_cast(currentRenderInfo.viewport.width); - int height = static_cast(currentRenderInfo.viewport.height); - - GLuint frameBufferName = 0; - glGenFramebuffers(1, &frameBufferName); - glBindFramebuffer(GL_FRAMEBUFFER, frameBufferName); - - GLuint renderBufferName = 0; - glGenRenderbuffers(1, &renderBufferName); - - GLuint colorBufferName = GetEyeTextureOpenGL(i); - rc = osvrRenderManagerCreateColorBufferOpenGL( - width, height, GL_RGBA, &colorBufferName); - checkReturnCode( - rc, "osvrRenderManagerCreateColorBufferOpenGL call failed."); - - // bind it to our framebuffer - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, colorBufferName, 0); - - // The depth buffer - GLuint depthBuffer; - rc = osvrRenderManagerCreateDepthBufferOpenGL(width, height, - &depthBuffer); - checkReturnCode( - rc, "osvrRenderManagerCreateDepthBufferOpenGL call failed."); - - glGenRenderbuffers(1, &depthBuffer); - glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, - height); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, depthBuffer); - - glBindRenderbuffer(GL_RENDERBUFFER, renderBufferName); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, - height); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, colorBufferName, 0); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, renderBufferName); - - // unbind the framebuffer - glBindTexture(GL_TEXTURE_2D, 0); - glBindRenderbuffer(GL_RENDERBUFFER, 0); - glBindFramebuffer(GL_FRAMEBUFFER, gFrameBuffer); - - OSVR_RenderBufferOpenGL buffer = {0}; - buffer.colorBufferName = colorBufferName; - buffer.depthStencilBufferName = depthBuffer; - rc = osvrRenderManagerRegisterRenderBufferOpenGL(state, buffer); - checkReturnCode( - rc, "osvrRenderManagerRegisterRenderBufferOpenGL call failed."); - - OSVR_RenderTargetInfo renderTarget = {0}; - renderTarget.frameBufferName = frameBufferName; - renderTarget.renderBufferName = renderBufferName; - renderTarget.colorBufferName = colorBufferName; - renderTarget.depthBufferName = depthBuffer; - gRenderTargets.push_back(renderTarget); - } - - rc = osvrRenderManagerFinishRegisterRenderBuffers(renderManager, state, - true); - checkReturnCode( - rc, "osvrRenderManagerFinishRegisterRenderBuffers call failed."); - } catch (...) { - // LOGE("Error durring render target creation."); - return false; - } - return true; + try { + OSVR_ReturnCode rc; + rc = osvrRenderManagerGetDefaultRenderParams(&gRenderParams); + checkReturnCode(rc, + "osvrRenderManagerGetDefaultRenderParams call failed."); + + gRenderParams.farClipDistanceMeters = 1000000.0f; + gRenderParams.nearClipDistanceMeters = 0.0000001f; + RenderInfoCollectionOpenGL renderInfo(renderManager, gRenderParams); + + OSVR_RenderManagerRegisterBufferState state; + rc = osvrRenderManagerStartRegisterRenderBuffers(&state); + checkReturnCode( + rc, "osvrRenderManagerStartRegisterRenderBuffers call failed."); + + for (int j = 0; j < numBuffers; j++){ + FrameInfoOpenGL* f = new FrameInfoOpenGL(); + f->renderBuffers.clear(); + for (OSVR_RenderInfoCount i = 0; i < renderInfo.getNumRenderInfo(); + i++) { + OSVR_RenderInfoOpenGL currentRenderInfo = + renderInfo.getRenderInfo(i); + + // Determine the appropriate size for the frame buffer to be used + // for + // all eyes when placed horizontally size by side. + int width = static_cast(currentRenderInfo.viewport.width); + int height = static_cast(currentRenderInfo.viewport.height); + + GLuint frameBufferName = 0; + glGenFramebuffers(1, &frameBufferName); + glBindFramebuffer(GL_FRAMEBUFFER, frameBufferName); + + GLuint renderBufferName = 0; + glGenRenderbuffers(1, &renderBufferName); + + GLuint colorBufferName = GetEyeTextureOpenGL(i, j); + rc = osvrRenderManagerCreateColorBufferOpenGL( + width, height, GL_RGBA, &colorBufferName); + checkReturnCode( + rc, "osvrRenderManagerCreateColorBufferOpenGL call failed."); + + // bind it to our framebuffer + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, colorBufferName, 0); + + // The depth buffer + GLuint depthBuffer; + rc = osvrRenderManagerCreateDepthBufferOpenGL(width, height, + &depthBuffer); + checkReturnCode( + rc, "osvrRenderManagerCreateDepthBufferOpenGL call failed."); + + glGenRenderbuffers(1, &depthBuffer); + glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, + height); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, depthBuffer); + + glBindRenderbuffer(GL_RENDERBUFFER, renderBufferName); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, + height); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, colorBufferName, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, renderBufferName); + + // unbind the framebuffer + glBindTexture(GL_TEXTURE_2D, 0); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, gFrameBuffer); + + OSVR_RenderBufferOpenGL buffer = { 0 }; + buffer.colorBufferName = colorBufferName; + buffer.depthStencilBufferName = depthBuffer; + rc = osvrRenderManagerRegisterRenderBufferOpenGL(state, buffer); + checkReturnCode( + rc, "osvrRenderManagerRegisterRenderBufferOpenGL call failed."); + + OSVR_RenderTargetInfoOpenGL renderTarget = { 0 }; + renderTarget.frameBufferName = frameBufferName; + renderTarget.renderBufferName = renderBufferName; + renderTarget.colorBufferName = colorBufferName; + renderTarget.depthBufferName = depthBuffer; + f->renderBuffers.push_back(renderTarget); + //gRenderTargets.push_back(renderTarget); + } + frameInfoOGL.push_back(f); + } + rc = osvrRenderManagerFinishRegisterRenderBuffers(renderManager, state, + true); + checkReturnCode( + rc, "osvrRenderManagerFinishRegisterRenderBuffers call failed."); + } + catch (...) { + // LOGE("Error durring render target creation."); + return false; + } + return true; } static bool setupOSVR() { - if (gOSVRInitialized) { - return true; - } - OSVR_ReturnCode rc = 0; - try { - // On Android, the current working directory is added to the default - // plugin search path. - // it also helps the server find its configuration and display files. - // boost::filesystem::current_path("/data/data/com.osvr.android.gles2sample/files"); - // auto workingDirectory = boost::filesystem::current_path(); - // //LOGI("[OSVR] Current working directory: %s", - // workingDirectory.string().c_str()); - - // auto-start the server - osvrClientAttemptServerAutoStart(); - - if (!gClientContext) { - // LOGI("[OSVR] Creating ClientContext..."); - gClientContext = - osvrClientInit("com.osvr.android.examples.OSVROpenGL", 0); - if (!gClientContext) { - // LOGI("[OSVR] could not create client context"); - return false; - } - - // temporary workaround to DisplayConfig issue, - // display sometimes fails waiting for the tree from the server. - // LOGI("[OSVR] Calling update a few times..."); - for (int i = 0; i < 10000; i++) { - rc = osvrClientUpdate(gClientContext); - if (rc != OSVR_RETURN_SUCCESS) { - // LOGI("[OSVR] Error while updating client context."); - return false; - } - } - - rc = osvrClientCheckStatus(gClientContext); - if (rc != OSVR_RETURN_SUCCESS) { - // LOGI("[OSVR] Client context reported bad status."); - return false; - } else { - // LOGI("[OSVR] Client context reported good status."); - } - - // if (OSVR_RETURN_SUCCESS != - // osvrClientGetInterface(gClientContext, - // "/camera", &gCamera)) { - // //LOGI("Error, could not get the camera - // interface at /camera."); - // return false; - // } - // - // // Register the imaging callback. - // if (OSVR_RETURN_SUCCESS != - // osvrRegisterImagingCallback(gCamera, - // &imagingCallback, &gClientContext)) { - // //LOGI("Error, could not register image - // callback."); - // return false; - // } - } - - gOSVRInitialized = true; - return true; - } catch (const std::runtime_error &ex) { - // LOGI("[OSVR] OSVR initialization failed: %s", ex.what()); - return false; - } + if (gOSVRInitialized) { + return true; + } + OSVR_ReturnCode rc = 0; + try { + // On Android, the current working directory is added to the default + // plugin search path. + // it also helps the server find its configuration and display files. + // boost::filesystem::current_path("/data/data/com.osvr.android.gles2sample/files"); + // auto workingDirectory = boost::filesystem::current_path(); + // //LOGI("[OSVR] Current working directory: %s", + // workingDirectory.string().c_str()); + + // auto-start the server + osvrClientAttemptServerAutoStart(); + + if (!gClientContext) { + // LOGI("[OSVR] Creating ClientContext..."); + gClientContext = + osvrClientInit("com.osvr.android.examples.OSVROpenGL", 0); + if (!gClientContext) { + // LOGI("[OSVR] could not create client context"); + return false; + } + + // temporary workaround to DisplayConfig issue, + // display sometimes fails waiting for the tree from the server. + // LOGI("[OSVR] Calling update a few times..."); + for (int i = 0; i < 10000; i++) { + rc = osvrClientUpdate(gClientContext); + if (rc != OSVR_RETURN_SUCCESS) { + // LOGI("[OSVR] Error while updating client context."); + return false; + } + } + + rc = osvrClientCheckStatus(gClientContext); + if (rc != OSVR_RETURN_SUCCESS) { + // LOGI("[OSVR] Client context reported bad status."); + return false; + } + else { + // LOGI("[OSVR] Client context reported good status."); + } + + // if (OSVR_RETURN_SUCCESS != + // osvrClientGetInterface(gClientContext, + // "/camera", &gCamera)) { + // //LOGI("Error, could not get the camera + // interface at /camera."); + // return false; + // } + // + // // Register the imaging callback. + // if (OSVR_RETURN_SUCCESS != + // osvrRegisterImagingCallback(gCamera, + // &imagingCallback, &gClientContext)) { + // //LOGI("Error, could not register image + // callback."); + // return false; + // } + } + + gOSVRInitialized = true; + return true; + } + catch (const std::runtime_error &ex) { + // LOGI("[OSVR] OSVR initialization failed: %s", ex.what()); + return false; + } } // Idempotent call to setup render manager static bool setupRenderManager() { - if (!gOSVRInitialized || !gGraphicsInitializedOnce) { - return false; - } - if (gRenderManagerInitialized) { - return true; - } - try { - PassThroughOpenGLContextImpl *glContextImpl = - new PassThroughOpenGLContextImpl(); - gGraphicsLibrary.toolkit = glContextImpl->getToolkit(); - - if (OSVR_RETURN_SUCCESS != - osvrCreateRenderManagerOpenGL(gClientContext, "OpenGL", - gGraphicsLibrary, &gRenderManager, - &gRenderManagerOGL)) { - std::cerr << "Could not create the RenderManager" << std::endl; - return false; - } - - // Open the display and make sure this worked - OSVR_OpenResultsOpenGL openResults; - if (OSVR_RETURN_SUCCESS != osvrRenderManagerOpenDisplayOpenGL( - gRenderManagerOGL, &openResults) || - (openResults.status == OSVR_OPEN_STATUS_FAILURE)) { - std::cerr << "Could not open display" << std::endl; - osvrDestroyRenderManager(gRenderManager); - gRenderManager = gRenderManagerOGL = nullptr; - return false; - } - - gRenderManagerInitialized = true; - return true; - } catch (const std::runtime_error &ex) { - // LOGI("[OSVR] RenderManager initialization failed: %s", ex.what()); - return false; - } + if (!gOSVRInitialized || !gGraphicsInitializedOnce) { + return false; + } + if (gRenderManagerInitialized) { + return true; + } + try { + PassThroughOpenGLContextImpl *glContextImpl = + new PassThroughOpenGLContextImpl(); + gGraphicsLibrary.toolkit = glContextImpl->getToolkit(); + + if (OSVR_RETURN_SUCCESS != + osvrCreateRenderManagerOpenGL(gClientContext, "OpenGL", + gGraphicsLibrary, &gRenderManager, + &gRenderManagerOGL)) { + std::cerr << "Could not create the RenderManager" << std::endl; + return false; + } + + // Open the display and make sure this worked + OSVR_OpenResultsOpenGL openResults; + if (OSVR_RETURN_SUCCESS != osvrRenderManagerOpenDisplayOpenGL( + gRenderManagerOGL, &openResults) || + (openResults.status == OSVR_OPEN_STATUS_FAILURE)) { + std::cerr << "Could not open display" << std::endl; + osvrDestroyRenderManager(gRenderManager); + gRenderManager = gRenderManagerOGL = nullptr; + return false; + } + + gRenderManagerInitialized = true; + return true; + } + catch (const std::runtime_error &ex) { + // LOGI("[OSVR] RenderManager initialization failed: %s", ex.what()); + return false; + } } static const GLfloat gTriangleColors[] = { - // white - 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + // white + 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, - // green - 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, - 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, + // green + 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, + 0.0f, 0.75f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, - // blue - 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + // blue + 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + 0.0f, 0.0f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - // green/purple - 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, - 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, + // green/purple + 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, + 0.0f, 0.75f, 0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, - // red/green - 0.75f, 0.75f, 0.0f, 1.0f, 0.75f, 0.75f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, - 0.75f, 0.75f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, + // red/green + 0.75f, 0.75f, 0.0f, 1.0f, 0.75f, 0.75f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, + 0.75f, 0.75f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, - // red/blue - 0.75f, 0.0f, 0.75f, 1.0f, 0.75f, 0.0f, 0.75f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 0.75f, 0.0f, 0.75f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f}; + // red/blue + 0.75f, 0.0f, 0.75f, 1.0f, 0.75f, 0.0f, 0.75f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 0.75f, 0.0f, 0.75f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f }; static const GLfloat gTriangleTexCoordinates[] = { - // A cube face (letters are unique vertices) - // A--B - // | | - // D--C - - // As two triangles (clockwise) - // A B D - // B C D - - // white - 1.0f, 0.0f, // A - 1.0f, 1.0f, // B - 0.0f, 0.0f, // D - 1.0f, 1.0f, // B - 0.0f, 1.0f, // C - 0.0f, 0.0f, // D - - // green - 1.0f, 0.0f, // A - 1.0f, 1.0f, // B - 0.0f, 0.0f, // D - 1.0f, 1.0f, // B - 0.0f, 1.0f, // C - 0.0f, 0.0f, // D - - // blue - 1.0f, 1.0f, // A - 0.0f, 1.0f, // B - 1.0f, 0.0f, // D - 0.0f, 1.0f, // B - 0.0f, 0.0f, // C - 1.0f, 0.0f, // D - - // blue-green - 1.0f, 0.0f, // A - 1.0f, 1.0f, // B - 0.0f, 0.0f, // D - 1.0f, 1.0f, // B - 0.0f, 1.0f, // C - 0.0f, 0.0f, // D - - // yellow - 0.0f, 0.0f, // A - 1.0f, 0.0f, // B - 0.0f, 1.0f, // D - 1.0f, 0.0f, // B - 1.0f, 1.0f, // C - 0.0f, 1.0f, // D - - // purple/magenta - 1.0f, 1.0f, // A - 0.0f, 1.0f, // B - 1.0f, 0.0f, // D - 0.0f, 1.0f, // B - 0.0f, 0.0f, // C - 1.0f, 0.0f, // D + // A cube face (letters are unique vertices) + // A--B + // | | + // D--C + + // As two triangles (clockwise) + // A B D + // B C D + + // white + 1.0f, 0.0f, // A + 1.0f, 1.0f, // B + 0.0f, 0.0f, // D + 1.0f, 1.0f, // B + 0.0f, 1.0f, // C + 0.0f, 0.0f, // D + + // green + 1.0f, 0.0f, // A + 1.0f, 1.0f, // B + 0.0f, 0.0f, // D + 1.0f, 1.0f, // B + 0.0f, 1.0f, // C + 0.0f, 0.0f, // D + + // blue + 1.0f, 1.0f, // A + 0.0f, 1.0f, // B + 1.0f, 0.0f, // D + 0.0f, 1.0f, // B + 0.0f, 0.0f, // C + 1.0f, 0.0f, // D + + // blue-green + 1.0f, 0.0f, // A + 1.0f, 1.0f, // B + 0.0f, 0.0f, // D + 1.0f, 1.0f, // B + 0.0f, 1.0f, // C + 0.0f, 0.0f, // D + + // yellow + 0.0f, 0.0f, // A + 1.0f, 0.0f, // B + 0.0f, 1.0f, // D + 1.0f, 0.0f, // B + 1.0f, 1.0f, // C + 0.0f, 1.0f, // D + + // purple/magenta + 1.0f, 1.0f, // A + 0.0f, 1.0f, // B + 1.0f, 0.0f, // D + 0.0f, 1.0f, // B + 0.0f, 0.0f, // C + 1.0f, 0.0f, // D }; static const GLfloat gTriangleVertices[] = { - // A cube face (letters are unique vertices) - // A--B - // | | - // D--C - - // As two triangles (clockwise) - // A B D - // B C D - - // glNormal3f(0.0, 0.0, -1.0); - 1.0f, 1.0f, -1.0f, // A - 1.0f, -1.0f, -1.0f, // B - -1.0f, 1.0f, -1.0f, // D - 1.0f, -1.0f, -1.0f, // B - -1.0f, -1.0f, -1.0f, // C - -1.0f, 1.0f, -1.0f, // D - - // glNormal3f(0.0, 0.0, 1.0); - -1.0f, 1.0f, 1.0f, // A - -1.0f, -1.0f, 1.0f, // B - 1.0f, 1.0f, 1.0f, // D - -1.0f, -1.0f, 1.0f, // B - 1.0f, -1.0f, 1.0f, // C - 1.0f, 1.0f, 1.0f, // D - - // glNormal3f(0.0, -1.0, 0.0); - 1.0f, -1.0f, 1.0f, // A - -1.0f, -1.0f, 1.0f, // B - 1.0f, -1.0f, -1.0f, // D - -1.0f, -1.0f, 1.0f, // B - -1.0f, -1.0f, -1.0f, // C - 1.0f, -1.0f, -1.0f, // D - - // glNormal3f(0.0, 1.0, 0.0); - 1.0f, 1.0f, 1.0f, // A - 1.0f, 1.0f, -1.0f, // B - -1.0f, 1.0f, 1.0f, // D - 1.0f, 1.0f, -1.0f, // B - -1.0f, 1.0f, -1.0f, // C - -1.0f, 1.0f, 1.0f, // D - - // glNormal3f(-1.0, 0.0, 0.0); - -1.0f, 1.0f, 1.0f, // A - -1.0f, 1.0f, -1.0f, // B - -1.0f, -1.0f, 1.0f, // D - -1.0f, 1.0f, -1.0f, // B - -1.0f, -1.0f, -1.0f, // C - -1.0f, -1.0f, 1.0f, // D - - // glNormal3f(1.0, 0.0, 0.0); - 1.0f, -1.0f, 1.0f, // A - 1.0f, -1.0f, -1.0f, // B - 1.0f, 1.0f, 1.0f, // D - 1.0f, -1.0f, -1.0f, // B - 1.0f, 1.0f, -1.0f, // C - 1.0f, 1.0f, 1.0f // D + // A cube face (letters are unique vertices) + // A--B + // | | + // D--C + + // As two triangles (clockwise) + // A B D + // B C D + + // glNormal3f(0.0, 0.0, -1.0); + 1.0f, 1.0f, -1.0f, // A + 1.0f, -1.0f, -1.0f, // B + -1.0f, 1.0f, -1.0f, // D + 1.0f, -1.0f, -1.0f, // B + -1.0f, -1.0f, -1.0f, // C + -1.0f, 1.0f, -1.0f, // D + + // glNormal3f(0.0, 0.0, 1.0); + -1.0f, 1.0f, 1.0f, // A + -1.0f, -1.0f, 1.0f, // B + 1.0f, 1.0f, 1.0f, // D + -1.0f, -1.0f, 1.0f, // B + 1.0f, -1.0f, 1.0f, // C + 1.0f, 1.0f, 1.0f, // D + + // glNormal3f(0.0, -1.0, 0.0); + 1.0f, -1.0f, 1.0f, // A + -1.0f, -1.0f, 1.0f, // B + 1.0f, -1.0f, -1.0f, // D + -1.0f, -1.0f, 1.0f, // B + -1.0f, -1.0f, -1.0f, // C + 1.0f, -1.0f, -1.0f, // D + + // glNormal3f(0.0, 1.0, 0.0); + 1.0f, 1.0f, 1.0f, // A + 1.0f, 1.0f, -1.0f, // B + -1.0f, 1.0f, 1.0f, // D + 1.0f, 1.0f, -1.0f, // B + -1.0f, 1.0f, -1.0f, // C + -1.0f, 1.0f, 1.0f, // D + + // glNormal3f(-1.0, 0.0, 0.0); + -1.0f, 1.0f, 1.0f, // A + -1.0f, 1.0f, -1.0f, // B + -1.0f, -1.0f, 1.0f, // D + -1.0f, 1.0f, -1.0f, // B + -1.0f, -1.0f, -1.0f, // C + -1.0f, -1.0f, 1.0f, // D + + // glNormal3f(1.0, 0.0, 0.0); + 1.0f, -1.0f, 1.0f, // A + 1.0f, -1.0f, -1.0f, // B + 1.0f, 1.0f, 1.0f, // D + 1.0f, -1.0f, -1.0f, // B + 1.0f, 1.0f, -1.0f, // C + 1.0f, 1.0f, 1.0f // D }; static bool setupGraphics(int width, int height) { - // printGLString("Version", GL_VERSION); - // printGLString("Vendor", GL_VENDOR); - // printGLString("Renderer", GL_RENDERER); - // printGLString("Extensions", GL_EXTENSIONS); - - // initializeGLES2Ext(); - GLint frameBuffer; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &frameBuffer); - gFrameBuffer = (GLuint)frameBuffer; - // LOGI("Window GL_FRAMEBUFFER_BINDING: %d", gFrameBuffer); - - // LOGI("setupGraphics(%d, %d)", width, height); - // gWidth = width; - // gHeight = height; - - // bool osvrSetupSuccess = setupOSVR(); - - gProgram = createProgram(gVertexShader, gFragmentShader); - if (!gProgram) { - // LOGE("Could not create program."); - osvrJniWrapperClass = jniEnvironment->FindClass( - "org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class - if (osvrJniWrapperClass == nullptr) { - return false; - } else { // if class found, continue - - jmethodID logmid = jniEnvironment->GetStaticMethodID( - osvrJniWrapperClass, "logMsg", - "(Ljava/lang/String;)V"); // find method - std::string stringy = - "[OSVR-Unity-Android] Could not create program."; - jstring jstr2 = jniEnvironment->NewStringUTF(stringy.c_str()); - jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, logmid, - jstr2); - } - return false; - } - gvPositionHandle = glGetAttribLocation(gProgram, "vPosition"); - checkGlError("glGetAttribLocation"); - // LOGI("glGetAttribLocation(\"vPosition\") = %d\n", gvPositionHandle); - - gvColorHandle = glGetAttribLocation(gProgram, "vColor"); - checkGlError("glGetAttribLocation"); - // LOGI("glGetAttribLocation(\"vColor\") = %d\n", gvColorHandle); - - gvTexCoordinateHandle = glGetAttribLocation(gProgram, "vTexCoordinate"); - checkGlError("glGetAttribLocation"); - // LOGI("glGetAttribLocation(\"vTexCoordinate\") = %d\n", - // gvTexCoordinateHandle); - - gvProjectionUniformId = glGetUniformLocation(gProgram, "projection"); - gvViewUniformId = glGetUniformLocation(gProgram, "view"); - gvModelUniformId = glGetUniformLocation(gProgram, "model"); - guTextureUniformId = glGetUniformLocation(gProgram, "uTexture"); - - glViewport(0, 0, width, height); - checkGlError("glViewport"); - - glDisable(GL_CULL_FACE); - - // @todo can we resize the texture after it has been created? - // if not, we may have to delete the dummy one and create a new one after - // the first imaging report. - // LOGI("Creating texture... here we go!"); - - gTextureID = createTexture(width, height); - - // return osvrSetupSuccess; - gGraphicsInitializedOnce = true; - return true; + // printGLString("Version", GL_VERSION); + // printGLString("Vendor", GL_VENDOR); + // printGLString("Renderer", GL_RENDERER); + // printGLString("Extensions", GL_EXTENSIONS); + + // initializeGLES2Ext(); + GLint frameBuffer; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &frameBuffer); + gFrameBuffer = (GLuint)frameBuffer; + // LOGI("Window GL_FRAMEBUFFER_BINDING: %d", gFrameBuffer); + + // LOGI("setupGraphics(%d, %d)", width, height); + // gWidth = width; + // gHeight = height; + + // bool osvrSetupSuccess = setupOSVR(); + + gProgram = createProgram(gVertexShader, gFragmentShader); + if (!gProgram) { + // LOGE("Could not create program."); + osvrJniWrapperClass = jniEnvironment->FindClass( + "org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class + if (osvrJniWrapperClass == nullptr) { + return false; + } + else { // if class found, continue + + jmethodID logmid = jniEnvironment->GetStaticMethodID( + osvrJniWrapperClass, "logMsg", + "(Ljava/lang/String;)V"); // find method + std::string stringy = + "[OSVR-Unity-Android] Could not create program."; + jstring jstr2 = jniEnvironment->NewStringUTF(stringy.c_str()); + jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, logmid, + jstr2); + } + return false; + } + gvPositionHandle = glGetAttribLocation(gProgram, "vPosition"); + checkGlError("glGetAttribLocation"); + // LOGI("glGetAttribLocation(\"vPosition\") = %d\n", gvPositionHandle); + + gvColorHandle = glGetAttribLocation(gProgram, "vColor"); + checkGlError("glGetAttribLocation"); + // LOGI("glGetAttribLocation(\"vColor\") = %d\n", gvColorHandle); + + gvTexCoordinateHandle = glGetAttribLocation(gProgram, "vTexCoordinate"); + checkGlError("glGetAttribLocation"); + // LOGI("glGetAttribLocation(\"vTexCoordinate\") = %d\n", + // gvTexCoordinateHandle); + + gvProjectionUniformId = glGetUniformLocation(gProgram, "projection"); + gvViewUniformId = glGetUniformLocation(gProgram, "view"); + gvModelUniformId = glGetUniformLocation(gProgram, "model"); + guTextureUniformId = glGetUniformLocation(gProgram, "uTexture"); + + glViewport(0, 0, width, height); + checkGlError("glViewport"); + + glDisable(GL_CULL_FACE); + + // @todo can we resize the texture after it has been created? + // if not, we may have to delete the dummy one and create a new one after + // the first imaging report. + // LOGI("Creating texture... here we go!"); + + gTextureID = createTexture(width, height); + + // return osvrSetupSuccess; + gGraphicsInitializedOnce = true; + return true; } /** * Just the current frame in the display. */ static void renderFrame() { - if (!gOSVRInitialized) { - // @todo implement some logging/error handling? - return; - } - - // this call is idempotent, so we can make it every frame. - // have to ensure render manager is setup from the rendering thread with - // a current GLES context, so this is a lazy setup call - if (!setupRenderManager()) { - // @todo implement some logging/error handling? - return; - } - - OSVR_ReturnCode rc; - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - checkGlError("glClearColor"); - glViewport(0, 0, gWidth, gHeight); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - checkGlError("glClear"); - - if (gRenderManager && gClientContext) { - osvrClientUpdate(gClientContext); - if (gLastFrame != nullptr) { - updateTexture(gLastFrameWidth, gLastFrameHeight, gLastFrame); - osvrClientFreeImage(gClientContext, gLastFrame); - gLastFrame = nullptr; - } - - OSVR_RenderParams renderParams; - rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); - checkReturnCode(rc, - "osvrRenderManagerGetDefaultRenderParams call failed."); - - RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, - renderParams); - - // Get the present started - OSVR_RenderManagerPresentState presentState; - rc = osvrRenderManagerStartPresentRenderBuffers(&presentState); - checkReturnCode( - rc, "osvrRenderManagerStartPresentRenderBuffers call failed."); - - for (OSVR_RenderInfoCount renderInfoCount = 0; - renderInfoCount < renderInfoCollection.getNumRenderInfo(); - renderInfoCount++) { - - // get the current render info - OSVR_RenderInfoOpenGL currentRenderInfo = - renderInfoCollection.getRenderInfo(renderInfoCount); - // Set color and depth buffers for the frame buffer - OSVR_RenderTargetInfo renderTargetInfo = - gRenderTargets[renderInfoCount]; - - // present this render target (deferred until the finish call below) - OSVR_ViewportDescription normalizedViewport = {0}; - normalizedViewport.left = 0.0f; - normalizedViewport.lower = 0.0f; - normalizedViewport.width = 1.0f; - normalizedViewport.height = 1.0f; - OSVR_RenderBufferOpenGL buffer = {0}; - buffer.colorBufferName = GetEyeTextureOpenGL(renderInfoCount); - buffer.depthStencilBufferName = renderTargetInfo.depthBufferName; - - rc = osvrRenderManagerPresentRenderBufferOpenGL( - presentState, buffer, currentRenderInfo, normalizedViewport); - checkReturnCode( - rc, "osvrRenderManagerPresentRenderBufferOpenGL call failed."); - } - - // actually kick off the present - rc = osvrRenderManagerFinishPresentRenderBuffers( - gRenderManager, presentState, renderParams, false); - checkReturnCode( - rc, "osvrRenderManagerFinishPresentRenderBuffers call failed."); - } + if (!gOSVRInitialized) { + // @todo implement some logging/error handling? + return; + } + + // this call is idempotent, so we can make it every frame. + // have to ensure render manager is setup from the rendering thread with + // a current GLES context, so this is a lazy setup call + if (!setupRenderManager()) { + // @todo implement some logging/error handling? + return; + } + + OSVR_ReturnCode rc; + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + checkGlError("glClearColor"); + glViewport(0, 0, gWidth, gHeight); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + checkGlError("glClear"); + + if (gRenderManager && gClientContext) { + osvrClientUpdate(gClientContext); + if (gLastFrame != nullptr) { + updateTexture(gLastFrameWidth, gLastFrameHeight, gLastFrame); + osvrClientFreeImage(gClientContext, gLastFrame); + gLastFrame = nullptr; + } + + OSVR_RenderParams renderParams; + rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); + checkReturnCode(rc, + "osvrRenderManagerGetDefaultRenderParams call failed."); + + RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, + renderParams); + + // Get the present started + OSVR_RenderManagerPresentState presentState; + rc = osvrRenderManagerStartPresentRenderBuffers(&presentState); + checkReturnCode( + rc, "osvrRenderManagerStartPresentRenderBuffers call failed."); + + int frame = iterations % numBuffers; + + for (OSVR_RenderInfoCount renderInfoCount = 0; + renderInfoCount < renderInfoCollection.getNumRenderInfo(); + renderInfoCount++) { + + // get the current render info + OSVR_RenderInfoOpenGL currentRenderInfo = + renderInfoCollection.getRenderInfo(renderInfoCount); + // Set color and depth buffers for the frame buffer + OSVR_RenderTargetInfoOpenGL renderTargetInfo = frameInfoOGL[frame]->renderBuffers[renderInfoCount]; + //gRenderTargets[renderInfoCount]; + + // present this render target (deferred until the finish call below) + OSVR_ViewportDescription normalizedViewport = { 0 }; + normalizedViewport.left = 0.0f; + normalizedViewport.lower = 0.0f; + normalizedViewport.width = 1.0f; + normalizedViewport.height = 1.0f; + OSVR_RenderBufferOpenGL buffer = { 0 }; + buffer.colorBufferName = GetEyeTextureOpenGL(renderInfoCount, frame); + buffer.depthStencilBufferName = renderTargetInfo.depthBufferName; + + rc = osvrRenderManagerPresentRenderBufferOpenGL( + presentState, buffer, currentRenderInfo, normalizedViewport); + checkReturnCode( + rc, "osvrRenderManagerPresentRenderBufferOpenGL call failed."); + } + + iterations++; + // actually kick off the present + rc = osvrRenderManagerFinishPresentRenderBuffers( + gRenderManager, presentState, renderParams, false); + checkReturnCode( + rc, "osvrRenderManagerFinishPresentRenderBuffers call failed."); + } } static void stop() { - // LOGI("[OSVR] Shutting down..."); + // LOGI("[OSVR] Shutting down..."); - if (gRenderManager) { - osvrDestroyRenderManager(gRenderManager); - gRenderManager = gRenderManagerOGL = nullptr; - } + if (gRenderManager) { + osvrDestroyRenderManager(gRenderManager); + gRenderManager = gRenderManagerOGL = nullptr; + } - // is this needed? Maybe not. the display config manages the lifetime. - if (gClientContext != nullptr) { - osvrClientShutdown(gClientContext); - gClientContext = nullptr; - } + // is this needed? Maybe not. the display config manages the lifetime. + if (gClientContext != nullptr) { + osvrClientShutdown(gClientContext); + gClientContext = nullptr; + } - osvrClientReleaseAutoStartedServer(); + osvrClientReleaseAutoStartedServer(); } OSVR_ReturnCode CreateRenderManagerAndroid(OSVR_ClientContext context) { - gClientContext = context; - if (setupOSVR()) { - if (setupGraphics(gWidth, gHeight)) { - if (setupRenderManager()) { - return OSVR_RETURN_SUCCESS; - } else - return 3; - } else - return 2; - } else - return 1; - - return OSVR_RETURN_SUCCESS; + gClientContext = context; + if (setupOSVR()) { + if (setupGraphics(gWidth, gHeight)) { + if (setupRenderManager()) { + return OSVR_RETURN_SUCCESS; + } + else + return 3; + } + else + return 2; + } + else + return 1; + + return OSVR_RETURN_SUCCESS; } void ShutdownRenderManagerAndroid() { - stop(); - contextSet = false; + stop(); + contextSet = false; } #endif void UNITY_INTERFACE_API ShutdownRenderManager() { - DebugLog("[OSVR Rendering Plugin] Shutting down RenderManager."); + DebugLog("[OSVR Rendering Plugin] Shutting down RenderManager."); #if UNITY_ANDROID - ShutdownRenderManagerAndroid(); - return; + ShutdownRenderManagerAndroid(); + return; #else // non-Android platforms - if (s_render != nullptr) { - osvrDestroyRenderManager(s_render); - s_render = nullptr; - s_leftEyeTexturePtr = nullptr; + if (s_render != nullptr) { + osvrDestroyRenderManager(s_render); + s_render = nullptr; + s_leftEyeTexturePtr = nullptr; s_leftEyeTexturePtrBuffer2 = nullptr; s_rightEyeTexturePtr = nullptr; s_rightEyeTexturePtrBuffer2 = nullptr; @@ -1458,15 +1498,15 @@ void UNITY_INTERFACE_API ShutdownRenderManager() { //s_lastRenderInfo.clear(); /*for (int i = 0; i < frameInfo.size(); i++) { - for (int j = 0; j < frameInfo[i]->renderBuffers.size(); j++) - { - frameInfo[i]->renderBuffers[j] = nullptr; - } + for (int j = 0; j < frameInfo[i]->renderBuffers.size(); j++) + { + frameInfo[i]->renderBuffers[j] = nullptr; + } }*/ frameInfo.clear(); - } - s_clientContext = nullptr; + } + s_clientContext = nullptr; #endif } @@ -1474,104 +1514,104 @@ void UNITY_INTERFACE_API ShutdownRenderManager() { OSVR_ReturnCode UNITY_INTERFACE_API CreateRenderManagerFromUnity(OSVR_ClientContext context) { #if UNITY_ANDROID - return CreateRenderManagerAndroid(context); + return CreateRenderManagerAndroid(context); #else - if (s_render != nullptr) { - if (osvrRenderManagerGetDoingOkay(s_render)) { - DebugLog("[OSVR Rendering Plugin] RenderManager already created " - "and doing OK - will just return success without trying " - "to re-initialize."); - return OSVR_RETURN_SUCCESS; - } - - DebugLog("[OSVR Rendering Plugin] RenderManager already created, " - "but not doing OK. Will shut down before creating again."); - // ShutdownRenderManager(); + if (s_render != nullptr) { + if (osvrRenderManagerGetDoingOkay(s_render)) { + DebugLog("[OSVR Rendering Plugin] RenderManager already created " + "and doing OK - will just return success without trying " + "to re-initialize."); + return OSVR_RETURN_SUCCESS; + } + + DebugLog("[OSVR Rendering Plugin] RenderManager already created, " + "but not doing OK. Will shut down before creating again."); + // ShutdownRenderManager(); return OSVR_RETURN_SUCCESS; - } - if (s_clientContext != nullptr) { - DebugLog( - "[OSVR Rendering Plugin] Client context already set! Replacing..."); - } - s_clientContext = context; - - if (!s_deviceType) { - // @todo pass the platform from Unity - // This is a patch to workaround a bug in Unity where the renderer type - // is not being set on Windows x86 builds. Until the OpenGL path is - // working, it's safe to assume we're using D3D11, but we'd rather get - // the platform from Unity than assume it's D3D11. - - s_deviceType = kUnityGfxRendererD3D11; - } - - bool setLibraryFromOpenDisplayReturn = false; - /// @todo We should always have a legit value in - /// s_deviceType.getDeviceTypeEnum() at this point, right? - switch (s_deviceType.getDeviceTypeEnum()) { + } + if (s_clientContext != nullptr) { + DebugLog( + "[OSVR Rendering Plugin] Client context already set! Replacing..."); + } + s_clientContext = context; + + if (!s_deviceType) { + // @todo pass the platform from Unity + // This is a patch to workaround a bug in Unity where the renderer type + // is not being set on Windows x86 builds. Until the OpenGL path is + // working, it's safe to assume we're using D3D11, but we'd rather get + // the platform from Unity than assume it's D3D11. + + s_deviceType = kUnityGfxRendererD3D11; + } + + bool setLibraryFromOpenDisplayReturn = false; + /// @todo We should always have a legit value in + /// s_deviceType.getDeviceTypeEnum() at this point, right? + switch (s_deviceType.getDeviceTypeEnum()) { #if SUPPORT_D3D11 - case OSVRSupportedRenderers::D3D11: - if (OSVR_RETURN_SUCCESS != - osvrCreateRenderManagerD3D11(context, "Direct3D11", s_libraryD3D, - &s_render, &s_renderD3D)) { - DebugLog("[OSVR Rendering Plugin] Could not create RenderManager"); - return OSVR_RETURN_FAILURE; - } + case OSVRSupportedRenderers::D3D11: + if (OSVR_RETURN_SUCCESS != + osvrCreateRenderManagerD3D11(context, "Direct3D11", s_libraryD3D, + &s_render, &s_renderD3D)) { + DebugLog("[OSVR Rendering Plugin] Could not create RenderManager"); + return OSVR_RETURN_FAILURE; + } #ifdef ATTEMPT_D3D_SHARING - setLibraryFromOpenDisplayReturn = true; + setLibraryFromOpenDisplayReturn = true; #endif // ATTEMPT_D3D_SHARING - break; + break; #endif // SUPPORT_D3D11 #if SUPPORT_OPENGL - case OSVRSupportedRenderers::OpenGL: - // s_render = osvr::renderkit::createRenderManager(context, "OpenGL"); - setLibraryFromOpenDisplayReturn = true; - break; + case OSVRSupportedRenderers::OpenGL: + // s_render = osvr::renderkit::createRenderManager(context, "OpenGL"); + setLibraryFromOpenDisplayReturn = true; + break; #endif // SUPPORT_OPENGL - } - - if (s_render == nullptr) { - DebugLog("[OSVR Rendering Plugin] here we aer."); - - DebugLog("[OSVR Rendering Plugin] Could not create RenderManager"); - - ShutdownRenderManager(); - return OSVR_RETURN_FAILURE; - } - - // Open the display and make sure this worked. - OSVR_OpenResultsD3D11 openResults; - if ((OSVR_RETURN_SUCCESS != - osvrRenderManagerOpenDisplayD3D11(s_renderD3D, &openResults)) || - (openResults.status == OSVR_OPEN_STATUS_FAILURE)) { - DebugLog("[OSVR Rendering Plugin] Could not open display"); - ShutdownRenderManager(); - return OSVR_RETURN_FAILURE; - } - if (openResults.library.device == nullptr) { - DebugLog("[OSVR Rendering Plugin] Could not get device when opening " - "display"); - - ShutdownRenderManager(); - return OSVR_RETURN_FAILURE; - } - if (openResults.library.context == nullptr) { - DebugLog("[OSVR Rendering Plugin] Could not get context when opening " - "display"); - - ShutdownRenderManager(); - return OSVR_RETURN_FAILURE; - } - - // create a new set of RenderParams for passing to GetRenderInfo() - osvrRenderManagerGetDefaultRenderParams(&s_renderParams); - - UpdateRenderInfo(); - - DebugLog("[OSVR Rendering Plugin] CreateRenderManagerFromUnity Success!"); - return OSVR_RETURN_SUCCESS; + } + + if (s_render == nullptr) { + DebugLog("[OSVR Rendering Plugin] here we aer."); + + DebugLog("[OSVR Rendering Plugin] Could not create RenderManager"); + + ShutdownRenderManager(); + return OSVR_RETURN_FAILURE; + } + + // Open the display and make sure this worked. + OSVR_OpenResultsD3D11 openResults; + if ((OSVR_RETURN_SUCCESS != + osvrRenderManagerOpenDisplayD3D11(s_renderD3D, &openResults)) || + (openResults.status == OSVR_OPEN_STATUS_FAILURE)) { + DebugLog("[OSVR Rendering Plugin] Could not open display"); + ShutdownRenderManager(); + return OSVR_RETURN_FAILURE; + } + if (openResults.library.device == nullptr) { + DebugLog("[OSVR Rendering Plugin] Could not get device when opening " + "display"); + + ShutdownRenderManager(); + return OSVR_RETURN_FAILURE; + } + if (openResults.library.context == nullptr) { + DebugLog("[OSVR Rendering Plugin] Could not get context when opening " + "display"); + + ShutdownRenderManager(); + return OSVR_RETURN_FAILURE; + } + + // create a new set of RenderParams for passing to GetRenderInfo() + osvrRenderManagerGetDefaultRenderParams(&s_renderParams); + + UpdateRenderInfo(); + + DebugLog("[OSVR Rendering Plugin] CreateRenderManagerFromUnity Success!"); + return OSVR_RETURN_SUCCESS; #endif // non-Android platforms } @@ -1579,141 +1619,141 @@ CreateRenderManagerFromUnity(OSVR_ClientContext context) { /// returning failure if any of them in the loop return failure. template inline OSVR_ReturnCode applyRenderBufferConstructor(const int numBuffers, - F &&bufferConstructor, - G &&bufferCleanup) { + F &&bufferConstructor, + G &&bufferCleanup) { #if UNITY_ANDROID - return OSVR_RETURN_SUCCESS; + return OSVR_RETURN_SUCCESS; #else - /// If we bail any time before the end, we'll automatically clean up the - /// render buffers with this lambda. - /* auto cleanupBuffers = osvr::util::finally([&] { - DebugLog("[OSVR Rendering Plugin] Cleaning up render buffers."); - for (auto &rb : s_renderBuffers) { - bufferCleanup(rb); - } - s_renderBuffers.clear(); - DebugLog("[OSVR Rendering Plugin] Render buffer cleanup complete."); - });*/ - - /// Construct all the buffers as isntructed - for (int i = 0; i < numBuffers; ++i) { - auto ret = bufferConstructor(i); - if (ret != OSVR_RETURN_SUCCESS) { - DebugLog("[OSVR Rendering Plugin] Failed in a buffer constructor!"); - return OSVR_RETURN_FAILURE; - } - } - - /// Register our constructed buffers so that we can use them for - /// presentation. - /* if (!s_render->RegisterRenderBuffers(s_renderBuffers)) { - DebugLog("RegisterRenderBuffers() returned false, cannot continue"); - return OSVR_RETURN_FAILURE; - }*/ - // Register our constructed buffers so that we can use them for - // presentation. - - UpdateRenderInfo(); - - OSVR_RenderManagerRegisterBufferState registerBufferState; - if ((OSVR_RETURN_SUCCESS != - osvrRenderManagerStartRegisterRenderBuffers(®isterBufferState))) { - DebugLog("[OSVR Rendering Plugin]Could not start registering render " - "buffers"); - ShutdownRenderManager(); - } - for (size_t i = 0; i < numRenderInfo; i++) { - if ((OSVR_RETURN_SUCCESS != - osvrRenderManagerRegisterRenderBufferD3D11(registerBufferState, - s_renderBuffers[i]))) { - DebugLog( - "[OSVR Rendering Plugin]Could not register render buffers"); - ShutdownRenderManager(); - } - } - if ((OSVR_RETURN_SUCCESS != osvrRenderManagerFinishRegisterRenderBuffers( - s_render, registerBufferState, true))) { - DebugLog("[OSVR Rendering Plugin]Could not finish registering render " - "buffers"); - ShutdownRenderManager(); - } - /// Only if we succeed, do we cancel the cleanup and carry on. - // cleanupBuffers.cancel(); - return OSVR_RETURN_SUCCESS; + /// If we bail any time before the end, we'll automatically clean up the + /// render buffers with this lambda. + /* auto cleanupBuffers = osvr::util::finally([&] { + DebugLog("[OSVR Rendering Plugin] Cleaning up render buffers."); + for (auto &rb : s_renderBuffers) { + bufferCleanup(rb); + } + s_renderBuffers.clear(); + DebugLog("[OSVR Rendering Plugin] Render buffer cleanup complete."); + });*/ + + /// Construct all the buffers as isntructed + for (int i = 0; i < numBuffers; ++i) { + auto ret = bufferConstructor(i); + if (ret != OSVR_RETURN_SUCCESS) { + DebugLog("[OSVR Rendering Plugin] Failed in a buffer constructor!"); + return OSVR_RETURN_FAILURE; + } + } + + /// Register our constructed buffers so that we can use them for + /// presentation. + /* if (!s_render->RegisterRenderBuffers(s_renderBuffers)) { + DebugLog("RegisterRenderBuffers() returned false, cannot continue"); + return OSVR_RETURN_FAILURE; + }*/ + // Register our constructed buffers so that we can use them for + // presentation. + + UpdateRenderInfo(); + + OSVR_RenderManagerRegisterBufferState registerBufferState; + if ((OSVR_RETURN_SUCCESS != + osvrRenderManagerStartRegisterRenderBuffers(®isterBufferState))) { + DebugLog("[OSVR Rendering Plugin]Could not start registering render " + "buffers"); + ShutdownRenderManager(); + } + for (size_t i = 0; i < numRenderInfo; i++) { + if ((OSVR_RETURN_SUCCESS != + osvrRenderManagerRegisterRenderBufferD3D11(registerBufferState, + s_renderBuffers[i]))) { + DebugLog( + "[OSVR Rendering Plugin]Could not register render buffers"); + ShutdownRenderManager(); + } + } + if ((OSVR_RETURN_SUCCESS != osvrRenderManagerFinishRegisterRenderBuffers( + s_render, registerBufferState, true))) { + DebugLog("[OSVR Rendering Plugin]Could not finish registering render " + "buffers"); + ShutdownRenderManager(); + } + /// Only if we succeed, do we cancel the cleanup and carry on. + // cleanupBuffers.cancel(); + return OSVR_RETURN_SUCCESS; #endif } #if SUPPORT_OPENGL inline OSVR_ReturnCode ConstructBuffersOpenGL(int eye) { - // Init glew - /* glewExperimental = 1u; - /// @todo doesn't rendermanager do this glewInit for us? - GLenum err = glewInit(); - if (err != GLEW_OK) { - DebugLog("glewInit failed, aborting."); - /// @todo shouldn't we return here then? - } - - if (eye == 0) { - // do this once - glGenFramebuffers(1, &s_frameBuffer); - glBindFramebuffer(GL_FRAMEBUFFER, s_frameBuffer); - } - - // The color buffer for this eye. We need to put this into - // a generic structure for the Present function, but we only need - // to fill in the OpenGL portion. - if (eye == 0) // left eye - { - GLuint leftEyeColorBuffer = 0; - glGenRenderbuffers(1, &leftEyeColorBuffer); - osvr::renderkit::RenderBuffer rb; - rb.OpenGL = new osvr::renderkit::RenderBufferOpenGL; - rb.OpenGL->colorBufferName = leftEyeColorBuffer; - s_renderBuffers.push_back(rb); - // "Bind" the newly created texture : all future texture - // functions will modify this texture glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, leftEyeColorBuffer); - - // Give an empty image to OpenGL ( the last "0" means "empty" ) - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, - static_cast(s_renderInfo[eye].viewport.width), - static_cast(s_renderInfo[eye].viewport.height), - 0, - GL_RGB, GL_UNSIGNED_BYTE, &leftEyeColorBuffer); - } else // right eye - { - GLuint rightEyeColorBuffer = 0; - glGenRenderbuffers(1, &rightEyeColorBuffer); - osvr::renderkit::RenderBuffer rb; - rb.OpenGL = new osvr::renderkit::RenderBufferOpenGL; - rb.OpenGL->colorBufferName = rightEyeColorBuffer; - s_renderBuffers.push_back(rb); - // "Bind" the newly created texture : all future texture - // functions will modify this texture glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, rightEyeColorBuffer); - - // Give an empty image to OpenGL ( the last "0" means "empty" ) - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, - static_cast(s_renderInfo[eye].viewport.width), - static_cast(s_renderInfo[eye].viewport.height), - 0, - GL_RGB, GL_UNSIGNED_BYTE, &rightEyeColorBuffer); - } - - // Bilinear filtering - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - */ - return OSVR_RETURN_SUCCESS; + // Init glew + /* glewExperimental = 1u; + /// @todo doesn't rendermanager do this glewInit for us? + GLenum err = glewInit(); + if (err != GLEW_OK) { + DebugLog("glewInit failed, aborting."); + /// @todo shouldn't we return here then? + } + + if (eye == 0) { + // do this once + glGenFramebuffers(1, &s_frameBuffer); + glBindFramebuffer(GL_FRAMEBUFFER, s_frameBuffer); + } + + // The color buffer for this eye. We need to put this into + // a generic structure for the Present function, but we only need + // to fill in the OpenGL portion. + if (eye == 0) // left eye + { + GLuint leftEyeColorBuffer = 0; + glGenRenderbuffers(1, &leftEyeColorBuffer); + osvr::renderkit::RenderBuffer rb; + rb.OpenGL = new osvr::renderkit::RenderBufferOpenGL; + rb.OpenGL->colorBufferName = leftEyeColorBuffer; + s_renderBuffers.push_back(rb); + // "Bind" the newly created texture : all future texture + // functions will modify this texture glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, leftEyeColorBuffer); + + // Give an empty image to OpenGL ( the last "0" means "empty" ) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, + static_cast(s_renderInfo[eye].viewport.width), + static_cast(s_renderInfo[eye].viewport.height), + 0, + GL_RGB, GL_UNSIGNED_BYTE, &leftEyeColorBuffer); + } else // right eye + { + GLuint rightEyeColorBuffer = 0; + glGenRenderbuffers(1, &rightEyeColorBuffer); + osvr::renderkit::RenderBuffer rb; + rb.OpenGL = new osvr::renderkit::RenderBufferOpenGL; + rb.OpenGL->colorBufferName = rightEyeColorBuffer; + s_renderBuffers.push_back(rb); + // "Bind" the newly created texture : all future texture + // functions will modify this texture glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, rightEyeColorBuffer); + + // Give an empty image to OpenGL ( the last "0" means "empty" ) + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, + static_cast(s_renderInfo[eye].viewport.width), + static_cast(s_renderInfo[eye].viewport.height), + 0, + GL_RGB, GL_UNSIGNED_BYTE, &rightEyeColorBuffer); + } + + // Bilinear filtering + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + */ + return OSVR_RETURN_SUCCESS; } inline void CleanupBufferOpenGL(OSVR_RenderBufferOpenGL &rb) { - /// @todo incomplete cleanup - but better than leaking in case of failure. - // delete rb.OpenGL; - // rb.OpenGL = nullptr; + /// @todo incomplete cleanup - but better than leaking in case of failure. + // delete rb.OpenGL; + // rb.OpenGL = nullptr; } #endif // SUPPORT_OPENGL @@ -1731,49 +1771,49 @@ inline ID3D11Texture2D *GetEyeTextureD3D11(int eye, int buffer) { } } -inline OSVR_ReturnCode ConstructBuffersD3D11(int eye, int buffer, FrameInfo* fInfo) { - DebugLog("[OSVR Rendering Plugin] ConstructBuffersD3D11"); - HRESULT hr; - // The color buffer for this eye. We need to put this into - // a generic structure for the Present function, but we only need - // to fill in the Direct3D portion. - // Note that this texture format must be RGBA and unsigned byte, - // so that we can present it to Direct3D for DirectMode. - ID3D11Texture2D *D3DTexture = GetEyeTextureD3D11(eye, buffer); - unsigned width = static_cast(s_renderInfo[eye].viewport.width); - unsigned height = static_cast(s_renderInfo[eye].viewport.height); - - D3DTexture->GetDesc(&s_textureDesc); - - // Fill in the resource view for your render texture buffer here - D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc = {}; - // This must match what was created in the texture to be rendered - /// @todo Figure this out by introspection on the texture? - // renderTargetViewDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; - /// @todo Interesting - change this line to DXGI_FORMAT_R8G8B8A8_UNORM_SRGB - /// and not only do you not get direct mode, you get multicolored static on - /// the display. - renderTargetViewDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - renderTargetViewDesc.Texture2D.MipSlice = 0; - - // Create the render target view. - ID3D11RenderTargetView *renderTargetView = - nullptr; //< Pointer to our render target view - hr = s_renderInfo[eye].library.device->CreateRenderTargetView( - D3DTexture, &renderTargetViewDesc, &renderTargetView); - if (FAILED(hr)) { - DebugLog( - "[OSVR Rendering Plugin] Could not create render target for eye"); - return OSVR_RETURN_FAILURE; - } - - // Push the filled-in RenderBuffer onto the stack. - OSVR_RenderBufferD3D11 rbD3D; - rbD3D.colorBuffer = D3DTexture; - rbD3D.colorBufferView = renderTargetView; +inline OSVR_ReturnCode ConstructBuffersD3D11(int eye, int buffer, FrameInfoD3D11* fInfo) { + DebugLog("[OSVR Rendering Plugin] ConstructBuffersD3D11"); + HRESULT hr; + // The color buffer for this eye. We need to put this into + // a generic structure for the Present function, but we only need + // to fill in the Direct3D portion. + // Note that this texture format must be RGBA and unsigned byte, + // so that we can present it to Direct3D for DirectMode. + ID3D11Texture2D *D3DTexture = GetEyeTextureD3D11(eye, buffer); + unsigned width = static_cast(s_renderInfo[eye].viewport.width); + unsigned height = static_cast(s_renderInfo[eye].viewport.height); + + D3DTexture->GetDesc(&s_textureDesc); + + // Fill in the resource view for your render texture buffer here + D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc = {}; + // This must match what was created in the texture to be rendered + /// @todo Figure this out by introspection on the texture? + // renderTargetViewDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + /// @todo Interesting - change this line to DXGI_FORMAT_R8G8B8A8_UNORM_SRGB + /// and not only do you not get direct mode, you get multicolored static on + /// the display. + renderTargetViewDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + renderTargetViewDesc.Texture2D.MipSlice = 0; + + // Create the render target view. + ID3D11RenderTargetView *renderTargetView = + nullptr; //< Pointer to our render target view + hr = s_renderInfo[eye].library.device->CreateRenderTargetView( + D3DTexture, &renderTargetViewDesc, &renderTargetView); + if (FAILED(hr)) { + DebugLog( + "[OSVR Rendering Plugin] Could not create render target for eye"); + return OSVR_RETURN_FAILURE; + } + + // Push the filled-in RenderBuffer onto the stack. + OSVR_RenderBufferD3D11 rbD3D; + rbD3D.colorBuffer = D3DTexture; + rbD3D.colorBufferView = renderTargetView; fInfo->renderBuffers.push_back(rbD3D); - //s_renderBuffers.push_back(rbD3D); + //s_renderBuffers.push_back(rbD3D); IDXGIKeyedMutex* keyedMutex = nullptr; hr = D3DTexture->QueryInterface( @@ -1831,7 +1871,7 @@ inline OSVR_ReturnCode ConstructBuffersD3D11(int eye, int buffer, FrameInfo* fIn } fInfo->depthStencilView = depthStencilView; - return OSVR_RETURN_SUCCESS; + return OSVR_RETURN_SUCCESS; } inline void CleanupBufferD3D11(OSVR_RenderBufferD3D11 &rb) { delete &rb; } @@ -1839,25 +1879,26 @@ inline void CleanupBufferD3D11(OSVR_RenderBufferD3D11 &rb) { delete &rb; } OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { #if UNITY_ANDROID - if (!setupRenderTextures(gRenderManager)) { - return OSVR_RETURN_FAILURE; - } else - return OSVR_RETURN_SUCCESS; + if (!setupRenderTextures(gRenderManager)) { + return OSVR_RETURN_FAILURE; + } + else + return OSVR_RETURN_SUCCESS; #else - if (!s_deviceType) { - DebugLog("[OSVR Rendering Plugin] Device type not supported."); - return OSVR_RETURN_FAILURE; - } - UpdateRenderInfo(); - - // construct buffers - //const int n = static_cast(numRenderInfo); - switch (s_deviceType.getDeviceTypeEnum()) { + if (!s_deviceType) { + DebugLog("[OSVR Rendering Plugin] Device type not supported."); + return OSVR_RETURN_FAILURE; + } + UpdateRenderInfo(); + + // construct buffers + //const int n = static_cast(numRenderInfo); + switch (s_deviceType.getDeviceTypeEnum()) { #if SUPPORT_D3D11 - case OSVRSupportedRenderers::D3D11: + case OSVRSupportedRenderers::D3D11: for (int i = 0; i < numBuffers; i++) { - FrameInfo* f = new FrameInfo(); + FrameInfoD3D11* f = new FrameInfoD3D11(); f->renderBuffers.clear(); for (int j = 0; j < numRenderInfo; j++) { @@ -1872,7 +1913,7 @@ OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { if ((OSVR_RETURN_SUCCESS != osvrRenderManagerStartRegisterRenderBuffers( ®isterBufferState))) { DebugLog("[OSVR Rendering Plugin] Could not start registering render buffers"); - ShutdownRenderManager(); + ShutdownRenderManager(); return OSVR_RETURN_FAILURE; } for (size_t i = 0; i < frameInfo.size(); i++) { @@ -1885,7 +1926,7 @@ OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { return OSVR_RETURN_FAILURE; } } - + } if ((OSVR_RETURN_SUCCESS != osvrRenderManagerFinishRegisterRenderBuffers( s_render, registerBufferState, false))) { @@ -1893,150 +1934,153 @@ OSVR_ReturnCode UNITY_INTERFACE_API ConstructRenderBuffers() { ShutdownRenderManager(); return OSVR_RETURN_FAILURE; } - //return applyRenderBufferConstructor(n, ConstructBuffersD3D11, - // CleanupBufferD3D11); - break; + //return applyRenderBufferConstructor(n, ConstructBuffersD3D11, + // CleanupBufferD3D11); + break; #endif #if SUPPORT_OPENGL - case OSVRSupportedRenderers::OpenGL: - // return applyRenderBufferConstructor(n, ConstructBuffersOpenGL, - // CleanupBufferOpenGL); - break; + case OSVRSupportedRenderers::OpenGL: + // return applyRenderBufferConstructor(n, ConstructBuffersOpenGL, + // CleanupBufferOpenGL); + break; #endif - case OSVRSupportedRenderers::EmptyRenderer: - default: - DebugLog("Device type not supported."); - return OSVR_RETURN_FAILURE; - } + case OSVRSupportedRenderers::EmptyRenderer: + default: + DebugLog("Device type not supported."); + return OSVR_RETURN_FAILURE; + } #endif // non-Android platforms } void UNITY_INTERFACE_API SetNearClipDistance(double distance) { - s_nearClipDistance = distance; + s_nearClipDistance = distance; #if !UNITY_ANDROID - s_renderParams.nearClipDistanceMeters = s_nearClipDistance; + s_renderParams.nearClipDistanceMeters = s_nearClipDistance; #endif } void UNITY_INTERFACE_API SetFarClipDistance(double distance) { - s_farClipDistance = distance; + s_farClipDistance = distance; #if !UNITY_ANDROID - s_renderParams.farClipDistanceMeters = s_farClipDistance; + s_renderParams.farClipDistanceMeters = s_farClipDistance; #endif } void UNITY_INTERFACE_API SetIPD(double ipdMeters) { - s_ipd = ipdMeters; - // s_renderParams.IPDMeters = s_ipd; + s_ipd = ipdMeters; + // s_renderParams.IPDMeters = s_ipd; } OSVR_ViewportDescription UNITY_INTERFACE_API GetViewport(std::uint8_t eye) { #if UNITY_ANDROID - OSVR_RenderParams renderParams; - OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); - checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); - RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, - renderParams); - OSVR_RenderInfoOpenGL currentRenderInfo = - renderInfoCollection.getRenderInfo(eye); - OSVR_ViewportDescription viewDesc; - viewDesc.width = currentRenderInfo.viewport.width; - viewDesc.height = currentRenderInfo.viewport.height; - viewDesc.left = currentRenderInfo.viewport.left; - viewDesc.lower = currentRenderInfo.viewport.lower; - return viewDesc; + OSVR_RenderParams renderParams; + OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); + checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); + RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, + renderParams); + OSVR_RenderInfoOpenGL currentRenderInfo = + renderInfoCollection.getRenderInfo(eye); + OSVR_ViewportDescription viewDesc; + viewDesc.width = currentRenderInfo.viewport.width; + viewDesc.height = currentRenderInfo.viewport.height; + viewDesc.left = currentRenderInfo.viewport.left; + viewDesc.lower = currentRenderInfo.viewport.lower; + return viewDesc; #else // non-Android platoforms - OSVR_ViewportDescription viewportDescription; - if (numRenderInfo > 0 && eye <= numRenderInfo - 1) { - viewportDescription = s_lastRenderInfo[eye].viewport; - - // cache the viewport width and height - // patches issue where sometimes empty viewport is returned - //@todo fix the real cause of why this method bugs out occasionally on - //some machines, more often on others - if (viewportWidth == 0 && s_lastRenderInfo[eye].viewport.width != 0) { - viewportWidth = s_lastRenderInfo[eye].viewport.width; - } - if (viewportHeight == 0 && s_lastRenderInfo[eye].viewport.height != 0) { - viewportHeight = s_lastRenderInfo[eye].viewport.height; - } - lastGoodViewportDescription = viewportDescription; - } else { - // we shouldn't be here unless we hit a bug, in which case, we avoid - // error by returning cached viewport values - std::string errorLog = "[OSVR Rendering Plugin] Error in GetViewport, " - "returning cached values. Eye = " + - std::to_string(int(eye)); - DebugLog(errorLog.c_str()); - /*viewportDescription.left = 0; - viewportDescription.lower = 0; - viewportDescription.width = viewportWidth; - viewportDescription.height = viewportHeight;*/ - lastGoodViewportDescription = viewportDescription; - } - return viewportDescription; + OSVR_ViewportDescription viewportDescription; + if (numRenderInfo > 0 && eye <= numRenderInfo - 1) { + viewportDescription = s_lastRenderInfo[eye].viewport; + + // cache the viewport width and height + // patches issue where sometimes empty viewport is returned + //@todo fix the real cause of why this method bugs out occasionally on + //some machines, more often on others + if (viewportWidth == 0 && s_lastRenderInfo[eye].viewport.width != 0) { + viewportWidth = s_lastRenderInfo[eye].viewport.width; + } + if (viewportHeight == 0 && s_lastRenderInfo[eye].viewport.height != 0) { + viewportHeight = s_lastRenderInfo[eye].viewport.height; + } + lastGoodViewportDescription = viewportDescription; + } + else { + // we shouldn't be here unless we hit a bug, in which case, we avoid + // error by returning cached viewport values + std::string errorLog = "[OSVR Rendering Plugin] Error in GetViewport, " + "returning cached values. Eye = " + + std::to_string(int(eye)); + DebugLog(errorLog.c_str()); + /*viewportDescription.left = 0; + viewportDescription.lower = 0; + viewportDescription.width = viewportWidth; + viewportDescription.height = viewportHeight;*/ + lastGoodViewportDescription = viewportDescription; + } + return viewportDescription; #endif // non-Android platforms } OSVR_ProjectionMatrix UNITY_INTERFACE_API GetProjectionMatrix(std::uint8_t eye) { #if UNITY_ANDROID - OSVR_RenderParams renderParams; - OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); - checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); - RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, - renderParams); - OSVR_RenderInfoOpenGL currentRenderInfo = - renderInfoCollection.getRenderInfo(eye); - OSVR_ProjectionMatrix proj; - proj.left = currentRenderInfo.projection.left; - proj.right = currentRenderInfo.projection.right; - proj.top = currentRenderInfo.projection.top; - proj.bottom = currentRenderInfo.projection.bottom; - proj.nearClip = currentRenderInfo.projection.nearClip; - proj.farClip = currentRenderInfo.projection.farClip; - return proj; + OSVR_RenderParams renderParams; + OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); + checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); + RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, + renderParams); + OSVR_RenderInfoOpenGL currentRenderInfo = + renderInfoCollection.getRenderInfo(eye); + OSVR_ProjectionMatrix proj; + proj.left = currentRenderInfo.projection.left; + proj.right = currentRenderInfo.projection.right; + proj.top = currentRenderInfo.projection.top; + proj.bottom = currentRenderInfo.projection.bottom; + proj.nearClip = currentRenderInfo.projection.nearClip; + proj.farClip = currentRenderInfo.projection.farClip; + return proj; #else - OSVR_ProjectionMatrix pm; - if (numRenderInfo > 0 && eye <= numRenderInfo - 1) { - pm = s_lastRenderInfo[eye].projection; - lastGoodProjMatrix = pm; - } else { - std::string errorLog = "[OSVR Rendering Plugin] Error in " - "GetProjectionMatrix, returning default values. " - "Eye = " + - std::to_string(int(eye)); - DebugLog(errorLog.c_str()); - pm = lastGoodProjMatrix; - } - return pm; + OSVR_ProjectionMatrix pm; + if (numRenderInfo > 0 && eye <= numRenderInfo - 1) { + pm = s_lastRenderInfo[eye].projection; + lastGoodProjMatrix = pm; + } + else { + std::string errorLog = "[OSVR Rendering Plugin] Error in " + "GetProjectionMatrix, returning default values. " + "Eye = " + + std::to_string(int(eye)); + DebugLog(errorLog.c_str()); + pm = lastGoodProjMatrix; + } + return pm; #endif // non-Android platforms } OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { #if UNITY_ANDROID - OSVR_RenderParams renderParams; - OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); - checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); - RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, - renderParams); - OSVR_RenderInfoOpenGL currentRenderInfo = - renderInfoCollection.getRenderInfo(eye); - return currentRenderInfo.pose; + OSVR_RenderParams renderParams; + OSVR_ReturnCode rc = osvrRenderManagerGetDefaultRenderParams(&renderParams); + checkReturnCode(rc, "osvrRenderManagerGetDefaultRenderParams call failed."); + RenderInfoCollectionOpenGL renderInfoCollection(gRenderManager, + renderParams); + OSVR_RenderInfoOpenGL currentRenderInfo = + renderInfoCollection.getRenderInfo(eye); + return currentRenderInfo.pose; #else - OSVR_Pose3 pose; - osvrPose3SetIdentity(&pose); - if (numRenderInfo > 0 && eye <= numRenderInfo - 1 && s_render != nullptr) { - pose = s_lastRenderInfo[eye].pose; - lastGoodPose = pose; - } else { - std::string errorLog = "[OSVR Rendering Plugin] Error in GetEyePose, " - "returning default values. Eye = " + - std::to_string(int(eye)); - DebugLog(errorLog.c_str()); - pose = lastGoodPose; - } - return pose; + OSVR_Pose3 pose; + osvrPose3SetIdentity(&pose); + if (numRenderInfo > 0 && eye <= numRenderInfo - 1 && s_render != nullptr) { + pose = s_lastRenderInfo[eye].pose; + lastGoodPose = pose; + } + else { + std::string errorLog = "[OSVR Rendering Plugin] Error in GetEyePose, " + "returning default values. Eye = " + + std::to_string(int(eye)); + DebugLog(errorLog.c_str()); + pose = lastGoodPose; + } + return pose; #endif // non-Android platforms } @@ -2055,21 +2099,45 @@ OSVR_Pose3 UNITY_INTERFACE_API GetEyePose(std::uint8_t eye) { // http://docs.unity3d.com/ScriptReference/Texture.GetNativeTexturePtr.html int UNITY_INTERFACE_API SetColorBufferFromUnity(void *texturePtr, std::uint8_t eye, std::uint8_t buffer) { - if (!s_deviceType) { - return OSVR_RETURN_FAILURE; - } + if (!s_deviceType) { + return OSVR_RETURN_FAILURE; + } - DebugLog("[OSVR Rendering Plugin] SetColorBufferFromUnity"); + DebugLog("[OSVR Rendering Plugin] SetColorBufferFromUnity"); #if UNITY_ANDROID - if (eye == 0) { - gLeftEyeTextureID = (GLuint)texturePtr; - } else { - gRightEyeTextureID = (GLuint)texturePtr; - } - return OSVR_RETURN_SUCCESS; + if (eye == 0) { + if (buffer == 0) + { + DebugLog("[OSVR Rendering Plugin] SetColorBufferFromUnity eye 0 buffer 0"); + + gLeftEyeTextureID = (GLuint)texturePtr; + } + else + { + DebugLog("[OSVR Rendering Plugin] SetColorBufferFromUnity eye 1 buffer 0"); + + gLeftEyeTextureIDBuffer2 = (GLuint)texturePtr; + } + } + else { + if (buffer == 0) + { + DebugLog("[OSVR Rendering Plugin] SetColorBufferFromUnity eye 0 buffer 1"); + + gRightEyeTextureID = (GLuint)texturePtr; + } + else + { + DebugLog("[OSVR Rendering Plugin] SetColorBufferFromUnity eye 1 buffer 1"); + + gRightEyeTextureIDBuffer2 = (GLuint)texturePtr; + } + } + + return OSVR_RETURN_SUCCESS; #else - if (eye == 0) { + if (eye == 0) { if (buffer == 0) { DebugLog("[OSVR Rendering Plugin] SetColorBufferFromUnity eye 0 buffer 0"); @@ -2082,7 +2150,8 @@ int UNITY_INTERFACE_API SetColorBufferFromUnity(void *texturePtr, s_leftEyeTexturePtrBuffer2 = texturePtr; } - } else { + } + else { if (buffer == 0) { DebugLog("[OSVR Rendering Plugin] SetColorBufferFromUnity eye 0 buffer 1"); @@ -2097,20 +2166,20 @@ int UNITY_INTERFACE_API SetColorBufferFromUnity(void *texturePtr, } } - return OSVR_RETURN_SUCCESS; + return OSVR_RETURN_SUCCESS; #endif } #if SUPPORT_D3D11 // Renders the view from our Unity cameras by copying data at // Unity.RenderTexture.GetNativeTexturePtr() to RenderManager colorBuffers void RenderViewD3D11(const OSVR_RenderInfoD3D11 &ri, - ID3D11RenderTargetView *renderTargetView, int eyeIndex, int frame) { - auto context = ri.library.context; - // Set up to render to the textures for this eye - context->OMSetRenderTargets(1, &renderTargetView, NULL); + ID3D11RenderTargetView *renderTargetView, int eyeIndex, int frame) { + auto context = ri.library.context; + // Set up to render to the textures for this eye + context->OMSetRenderTargets(1, &renderTargetView, NULL); - // copy the updated RenderTexture from Unity to RenderManager colorBuffer - frameInfo[frame]->renderBuffers[eyeIndex].colorBuffer = GetEyeTextureD3D11(eyeIndex, frame); + // copy the updated RenderTexture from Unity to RenderManager colorBuffer + frameInfo[frame]->renderBuffers[eyeIndex].colorBuffer = GetEyeTextureD3D11(eyeIndex, frame); } #endif // SUPPORT_D3D11 @@ -2118,85 +2187,85 @@ void RenderViewD3D11(const OSVR_RenderInfoD3D11 &ri, // Render the world from the specified point of view. //@todo This is not functional yet. inline void RenderViewOpenGL( - const OSVR_RenderInfoOpenGL &ri, //< Info needed to render - GLuint frameBufferObj, //< Frame buffer object to bind our buffers to - GLuint colorBuffer, //< Color buffer to render into - int eyeIndex) { - // Render to our framebuffer - /* glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObj); - - // Set color and depth buffers for the frame buffer - glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorBuffer, - 0); - // glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - // GL_RENDERBUFFER, depthBuffer); - - // Set the list of draw buffers. - GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0}; - glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers - - // Always check that our framebuffer is ok - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - DebugLog("RenderView: Incomplete Framebuffer"); - return; - } - - // Set the viewport to cover our entire render texture. - glViewport(0, 0, static_cast(ri.viewport.width), - static_cast(ri.viewport.height)); - - // Set the OpenGL projection matrix - GLdouble projection[16]; - osvr::renderkit::OSVR_Projection_to_OpenGL(projection, ri.projection); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMultMatrixd(projection); - - /// Put the transform into the OpenGL ModelView matrix - GLdouble modelView[16]; - osvr::renderkit::OSVR_PoseState_to_OpenGL(modelView, ri.pose); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glMultMatrixd(modelView); - - // Clear the screen to red and clear depth - glClearColor(1, 0, 0, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // ================================================================= - // This is where we draw our world and hands and any other objects. - // We're in World Space. To find out about where to render objects - // in OSVR spaces (like left/right hand space) we need to query the - // interface and handle the coordinate tranforms ourselves. - - // update native texture from code - glBindTexture(GL_TEXTURE_2D, - s_renderBuffers[eyeIndex].OpenGL->colorBufferName); - int texWidth, texHeight; - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texWidth); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texHeight); - - GLuint glTex = eyeIndex == 0 ? (GLuint)s_leftEyeTexturePtr - : (GLuint)s_rightEyeTexturePtr; - - // unsigned char* data = new unsigned char[texWidth*texHeight * 4]; - // FillTextureFromCode(texWidth, texHeight, texHeight * 4, data); - // glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, - // GL_UNSIGNED_BYTE, (GLuint)); - // delete[] data; - // Draw a cube with a 5-meter radius as the room we are floating in. - // draw_cube(5.0); - */ + const OSVR_RenderInfoOpenGL &ri, //< Info needed to render + GLuint frameBufferObj, //< Frame buffer object to bind our buffers to + GLuint colorBuffer, //< Color buffer to render into + int eyeIndex) { + // Render to our framebuffer + /* glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObj); + + // Set color and depth buffers for the frame buffer + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorBuffer, + 0); + // glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + // GL_RENDERBUFFER, depthBuffer); + + // Set the list of draw buffers. + GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0}; + glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers + + // Always check that our framebuffer is ok + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + DebugLog("RenderView: Incomplete Framebuffer"); + return; + } + + // Set the viewport to cover our entire render texture. + glViewport(0, 0, static_cast(ri.viewport.width), + static_cast(ri.viewport.height)); + + // Set the OpenGL projection matrix + GLdouble projection[16]; + osvr::renderkit::OSVR_Projection_to_OpenGL(projection, ri.projection); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMultMatrixd(projection); + + /// Put the transform into the OpenGL ModelView matrix + GLdouble modelView[16]; + osvr::renderkit::OSVR_PoseState_to_OpenGL(modelView, ri.pose); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glMultMatrixd(modelView); + + // Clear the screen to red and clear depth + glClearColor(1, 0, 0, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // ================================================================= + // This is where we draw our world and hands and any other objects. + // We're in World Space. To find out about where to render objects + // in OSVR spaces (like left/right hand space) we need to query the + // interface and handle the coordinate tranforms ourselves. + + // update native texture from code + glBindTexture(GL_TEXTURE_2D, + s_renderBuffers[eyeIndex].OpenGL->colorBufferName); + int texWidth, texHeight; + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texWidth); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texHeight); + + GLuint glTex = eyeIndex == 0 ? (GLuint)s_leftEyeTexturePtr + : (GLuint)s_rightEyeTexturePtr; + + // unsigned char* data = new unsigned char[texWidth*texHeight * 4]; + // FillTextureFromCode(texWidth, texHeight, texHeight * 4, data); + // glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, + // GL_UNSIGNED_BYTE, (GLuint)); + // delete[] data; + // Draw a cube with a 5-meter radius as the room we are floating in. + // draw_cube(5.0); + */ } #endif // SUPPORT_OPENGL inline void DoRender() { - if (!s_deviceType) { - return; - } - switch (s_deviceType.getDeviceTypeEnum()) { + if (!s_deviceType) { + return; + } + switch (s_deviceType.getDeviceTypeEnum()) { #if SUPPORT_D3D11 - case OSVRSupportedRenderers::D3D11: { + case OSVRSupportedRenderers::D3D11: { int frame = iterations % numBuffers; @@ -2207,32 +2276,32 @@ inline void DoRender() { //std::cout << "RenderThread: locking buffer for frame " << frame << " using key " << 0 << std::endl; /*auto hr = frameInfo[frame]->keyedMutex->AcquireSync(0, 500); if (FAILED(hr) || hr == E_FAIL || hr == WAIT_ABANDONED || hr == WAIT_TIMEOUT) { - std::cerr << "RenderThread: could not lock buffer for frame " << frame << std::endl; - switch (hr) { - case E_FAIL: - std::cerr << "RenderThread: error == E_FAIL" << std::endl; - break; - case WAIT_ABANDONED: - std::cerr << "RenderThread: error == WAIT_ABANDONED" << std::endl; - break; - case WAIT_TIMEOUT: - std::cerr << "RenderThread: error == WAIT_TIMEOUT" << std::endl; - break; - default: - std::cerr << "RenderThread: error == (unknown error type: " << hr << ")" << std::endl; - break; - } - osvrDestroyRenderManager(s_render); - return; + std::cerr << "RenderThread: could not lock buffer for frame " << frame << std::endl; + switch (hr) { + case E_FAIL: + std::cerr << "RenderThread: error == E_FAIL" << std::endl; + break; + case WAIT_ABANDONED: + std::cerr << "RenderThread: error == WAIT_ABANDONED" << std::endl; + break; + case WAIT_TIMEOUT: + std::cerr << "RenderThread: error == WAIT_TIMEOUT" << std::endl; + break; + default: + std::cerr << "RenderThread: error == (unknown error type: " << hr << ")" << std::endl; + break; + } + osvrDestroyRenderManager(s_render); + return; }*/ - const auto n = static_cast(numRenderInfo); - // Render into each buffer using the specified information. - for (int i = 0; i < n; ++i) { - RenderViewD3D11(s_renderInfo[i], frameInfo[frame]->renderBuffers[i].colorBufferView, - i, frame); - } + const auto n = static_cast(numRenderInfo); + // Render into each buffer using the specified information. + for (int i = 0; i < n; ++i) { + RenderViewD3D11(s_renderInfo[i], frameInfo[frame]->renderBuffers[i].colorBufferView, + i, frame); + } // Grab and lock the mutex, so that we will be able to render // to it whether or not RenderManager locks it on our behalf. @@ -2240,19 +2309,19 @@ inline void DoRender() { //std::cout << "RenderThread: Unlocking buffer for frame " << frame << " using key " << 1 << std::endl; /*hr = frameInfo[frame]->keyedMutex->ReleaseSync(0); if (FAILED(hr)) { - std::cerr << "RenderThread: could not unlock buffer for frame " << frame << std::endl; - osvrDestroyRenderManager(s_render); - return; + std::cerr << "RenderThread: could not unlock buffer for frame " << frame << std::endl; + osvrDestroyRenderManager(s_render); + return; }*/ - // Send the rendered results to the screen - OSVR_RenderManagerPresentState presentState; - if ((OSVR_RETURN_SUCCESS != - osvrRenderManagerStartPresentRenderBuffers(&presentState))) { - DebugLog("[OSVR Rendering Plugin] Could not start presenting " - "render buffers"); - ShutdownRenderManager(); - } + // Send the rendered results to the screen + OSVR_RenderManagerPresentState presentState; + if ((OSVR_RETURN_SUCCESS != + osvrRenderManagerStartPresentRenderBuffers(&presentState))) { + DebugLog("[OSVR Rendering Plugin] Could not start presenting " + "render buffers"); + ShutdownRenderManager(); + } // create normalized cropping viewports for side-by-side rendering to a single render target std::vector NVCPs; double fraction = 1.0 / s_renderInfo.size(); @@ -2267,58 +2336,58 @@ inline void DoRender() { OSVR_ViewportDescription fullView; fullView.left = fullView.lower = 0; fullView.width = fullView.height = 1; - for (size_t i = 0; i < numRenderInfo; i++) { - if ((OSVR_RETURN_SUCCESS != - osvrRenderManagerPresentRenderBufferD3D11( - presentState, frameInfo[frame]->renderBuffers[i], s_renderInfo[i], - fullView))) { - DebugLog( - "[OSVR Rendering Plugin] Could not present render buffer "); - ShutdownRenderManager(); - } - } - - if ((OSVR_RETURN_SUCCESS != - osvrRenderManagerFinishPresentRenderBuffers( - s_render, presentState, s_renderParams, true))) { - DebugLog("[OSVR Rendering Plugin] Could not finish presenting " - "render buffers"); - ShutdownRenderManager(); - } + for (size_t i = 0; i < numRenderInfo; i++) { + if ((OSVR_RETURN_SUCCESS != + osvrRenderManagerPresentRenderBufferD3D11( + presentState, frameInfo[frame]->renderBuffers[i], s_renderInfo[i], + fullView))) { + DebugLog( + "[OSVR Rendering Plugin] Could not present render buffer "); + ShutdownRenderManager(); + } + } + + if ((OSVR_RETURN_SUCCESS != + osvrRenderManagerFinishPresentRenderBuffers( + s_render, presentState, s_renderParams, true))) { + DebugLog("[OSVR Rendering Plugin] Could not finish presenting " + "render buffers"); + ShutdownRenderManager(); + } iterations++; - break; - } + break; + } #endif // SUPPORT_D3D11 #if SUPPORT_OPENGL - case OSVRSupportedRenderers::OpenGL: { + case OSVRSupportedRenderers::OpenGL: { #if UNITY_ANDROID - renderFrame(); + renderFrame(); #endif - // OpenGL - //@todo OpenGL path is not working yet - // Render into each buffer using the specified information. - - /* for (int i = 0; i < n; ++i) { - RenderViewOpenGL(s_renderInfo[i], s_frameBuffer, - s_renderBuffers[i].OpenGL->colorBufferName, i); - } - - // Send the rendered results to the screen - if (!s_render->PresentRenderBuffers(s_renderBuffers, s_renderInfo)) { - DebugLog("PresentRenderBuffers() returned false, maybe because " - "it was asked to quit"); - } - break;*/ - } + // OpenGL + //@todo OpenGL path is not working yet + // Render into each buffer using the specified information. + + /* for (int i = 0; i < n; ++i) { + RenderViewOpenGL(s_renderInfo[i], s_frameBuffer, + s_renderBuffers[i].OpenGL->colorBufferName, i); + } + + // Send the rendered results to the screen + if (!s_render->PresentRenderBuffers(s_renderBuffers, s_renderInfo)) { + DebugLog("PresentRenderBuffers() returned false, maybe because " + "it was asked to quit"); + } + break;*/ + } #endif // SUPPORT_OPENGL - case OSVRSupportedRenderers::EmptyRenderer: - default: - break; - } + case OSVRSupportedRenderers::EmptyRenderer: + default: + break; + } } // -------------------------------------------------------------------------- @@ -2328,38 +2397,38 @@ inline void DoRender() { /// @todo does this actually need to be exported? It seems like /// GetRenderEventFunc returning it would be sufficient... void UNITY_INTERFACE_API OnRenderEvent(int eventID) { - // Unknown graphics device type? Do nothing. - if (!s_deviceType) { - return; - } - - switch (eventID) { - // Call the Render loop - case kOsvrEventID_Render: - DoRender(); - break; - case kOsvrEventID_Shutdown: - break; - case kOsvrEventID_Update: + // Unknown graphics device type? Do nothing. + if (!s_deviceType) { + return; + } + + switch (eventID) { + // Call the Render loop + case kOsvrEventID_Render: + DoRender(); + break; + case kOsvrEventID_Shutdown: + break; + case kOsvrEventID_Update: #if UNITY_WIN - UpdateRenderInfo(); + UpdateRenderInfo(); #endif - break; + break; case kOsvrEventID_ConstructBuffers: ConstructRenderBuffers(); - // SetRoomRotationUsingHead(); - break; - case kOsvrEventID_ClearRoomToWorldTransform: - // ClearRoomToWorldTransform(); - break; - default: - break; - } + // SetRoomRotationUsingHead(); + break; + case kOsvrEventID_ClearRoomToWorldTransform: + // ClearRoomToWorldTransform(); + break; + default: + break; + } } // -------------------------------------------------------------------------- // GetRenderEventFunc, a function we export which is used to get a // rendering event callback function. UnityRenderingEvent UNITY_INTERFACE_API GetRenderEventFunc() { - return &OnRenderEvent; + return &OnRenderEvent; } From 15e27b854542797d7dc7a7a485359f34e9cbf5ca Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Tue, 26 Dec 2017 19:35:04 -0500 Subject: [PATCH 42/43] fixed cmake build error on Windows without breaking OSVR-Android-Build --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a26f9cd..90d03ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,7 +56,7 @@ target_include_directories(osvrUnityRenderingPlugin PRIVATE ${Boost_INCLUDE_DIRS if (OPENGL_FOUND AND GLEW_FOUND) target_include_directories(osvrUnityRenderingPlugin PRIVATE ${OPENGL_INCLUDE_DIRS}) - target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} GLEW::GLEW JsonCpp::JsonCpp SDL2::SDL2 osvr::osvrClientKit osvrRenderManager::osvrRenderManager android ${EXTRA_ANDROID_LINKER_FLAGS}) + target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} GLEW::GLEW JsonCpp::JsonCpp SDL2::SDL2 osvr::osvrClientKit osvrRenderManager::osvrRenderManager) # Handle static glew. if(GLEW_LIBRARY MATCHES ".*s.lib") target_compile_definitions(osvrUnityRenderingPlugin PRIVATE GLEW_STATIC) @@ -64,7 +64,7 @@ if (OPENGL_FOUND AND GLEW_FOUND) endif() if (OPENGL_FOUND) target_include_directories(osvrUnityRenderingPlugin PRIVATE ${OPENGL_INCLUDE_DIRS}) - target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} JsonCpp::JsonCpp osvr::osvrClientKit osvrRenderManager::osvrRenderManager android ${EXTRA_ANDROID_LINKER_FLAGS}) + target_link_libraries(osvrUnityRenderingPlugin ${OPENGL_LIBRARY} JsonCpp::JsonCpp osvr::osvrClientKit osvrRenderManager::osvrRenderManager) endif() if(OPENGLES2_FOUND) target_include_directories(osvrUnityRenderingPlugin PRIVATE ${OPENGLES2_INCLUDE_DIR}) From d998a22c0c2d55a149ccd7635759db9d33373700 Mon Sep 17 00:00:00 2001 From: Greg Aring Date: Fri, 29 Dec 2017 23:54:55 -0500 Subject: [PATCH 43/43] Creating const strings for JNI class paths and log method name. Refactoring and comments. --- OsvrRenderingPlugin.cpp | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/OsvrRenderingPlugin.cpp b/OsvrRenderingPlugin.cpp index 4135056..5d84967 100644 --- a/OsvrRenderingPlugin.cpp +++ b/OsvrRenderingPlugin.cpp @@ -117,7 +117,8 @@ static JNIEnv *jniEnvironment = 0; static jclass osvrJniWrapperClass; static jmethodID logMsgId; static jobject unityActivityClassInstance; - +static const char* OSVR_JNI_CLASS_PATH = "org/osvr/osvrunityjni/OsvrJNIWrapper"; +static const char* OSVR_JNI_LOG_METHOD_NAME = "logMsg"; static int gWidth = 0; static int gHeight = 0; static GLuint gProgram; @@ -160,7 +161,7 @@ static OSVR_RenderParams gRenderParams = { 0 }; //static std::vector buffers; //static std::vector gRenderTargets; static bool contextSet = false; -static jmethodID logmid = nullptr; +static jmethodID androidDebugLogMethodID = nullptr; struct FrameInfoOpenGL { // Set up the vector of textures to render to and any framebuffer // we need to group them. @@ -270,16 +271,18 @@ void UNITY_INTERFACE_API LinkDebug(DebugFnPtr d) { s_debugLog = d; } // Only for debugging purposes, as this causes some errors at shutdown inline void DebugLog(const char *str) { - //@todo complete logMsg implementation in JNI plugin - // for now just return on Android #if UNITY_ANDROID - if (logmid != nullptr) + //@todo resolve issue where uncommenting this code + //causes a crash when the scene switches or quits + /* + if (androidDebugLogMethodID != nullptr) { - jstring jstr2 = jniEnvironment->NewStringUTF(str); - jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, - logmid, jstr2); - } + jstring jstr = jniEnvironment->NewStringUTF(str); + jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, + androidDebugLogMethodID, jstr); + */ return; + #else // all platforms besides Android #if !defined(NDEBUG) || defined(ENABLE_LOGGING) if (s_debugLog != nullptr) { @@ -403,15 +406,15 @@ OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) { case kUnityGfxDeviceEventInitialize: { #if UNITY_ANDROID osvrJniWrapperClass = jniEnvironment->FindClass( - "org/osvr/osvrunityjni/OsvrJNIWrapper"); // try to find the class + OSVR_JNI_CLASS_PATH); // try to find the class if (osvrJniWrapperClass == nullptr) { return; } else { // if osvrJniWrapperClass found, continue // get the Android logger method ID - logmid = jniEnvironment->GetStaticMethodID( - osvrJniWrapperClass, "logMsg", + androidDebugLogMethodID = jniEnvironment->GetStaticMethodID( + osvrJniWrapperClass, OSVR_JNI_LOG_METHOD_NAME, "(Ljava/lang/String;)V"); // find method // get the method ID for setting the GL context jmethodID setGlContextId = jniEnvironment->GetStaticMethodID( @@ -422,13 +425,14 @@ OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) { else { jlong currentEglContextHandle = jniEnvironment->CallStaticLongMethod( - osvrJniWrapperClass, setGlContextId); // call mathod + osvrJniWrapperClass, setGlContextId); // call method to set Unity GL context + // example code for logging the context ID /*long myLongValue = (long)currentEglContextHandle; std::string stringy = "[OSVR-Unity-Android] setCurrentContext with handle : " + std::to_string(myLongValue); jstring jstr2 = jniEnvironment->NewStringUTF(stringy.c_str()); jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, - logmid, jstr2);*/ + androidDebugLogMethodID, jstr2);*/ contextSet = true; } // get the display width and height via JNI @@ -1308,13 +1312,13 @@ static bool setupGraphics(int width, int height) { } else { // if class found, continue - jmethodID logmid = jniEnvironment->GetStaticMethodID( + jmethodID androidDebugLogMethodID = jniEnvironment->GetStaticMethodID( osvrJniWrapperClass, "logMsg", "(Ljava/lang/String;)V"); // find method std::string stringy = "[OSVR-Unity-Android] Could not create program."; jstring jstr2 = jniEnvironment->NewStringUTF(stringy.c_str()); - jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, logmid, + jniEnvironment->CallStaticVoidMethod(osvrJniWrapperClass, androidDebugLogMethodID, jstr2); } return false; @@ -1482,7 +1486,7 @@ void ShutdownRenderManagerAndroid() { #endif void UNITY_INTERFACE_API ShutdownRenderManager() { - DebugLog("[OSVR Rendering Plugin] Shutting down RenderManager."); + //DebugLog("[OSVR Rendering Plugin] Shutting down RenderManager."); #if UNITY_ANDROID ShutdownRenderManagerAndroid(); return;