diff --git a/Projects/Android/jni/src/Lambda1VR/L1VR_SurfaceView.c b/Projects/Android/jni/src/Lambda1VR/L1VR_SurfaceView.c index 7f91f1e..77dd6c1 100644 --- a/Projects/Android/jni/src/Lambda1VR/L1VR_SurfaceView.c +++ b/Projects/Android/jni/src/Lambda1VR/L1VR_SurfaceView.c @@ -544,15 +544,6 @@ void * AppThreadFunction( void * parm ) TBXR_EnterVR(); TBXR_InitRenderer(); -#ifdef L1VR_STEAM_FRAME - //The positional movement scaling goes by vr_refresh, so make it the real rate - if (TBXR_GetRefresh() > 0) - { - char rate[16]; - Q_snprintf(rate, sizeof(rate), "%d", TBXR_GetRefresh()); - Cvar_Set2("vr_refresh", rate, true); - } -#endif TBXR_InitActions(); TBXR_WaitForSessionActive(); @@ -572,6 +563,20 @@ void * AppThreadFunction( void * parm ) TBXR_FrameSetup(); #ifdef L1VR_STEAM_FRAME + { + //The positional movement scaling goes by vr_refresh. SteamVR picks the rate for + //the app, so take it from the frame period rather than from what's on offer. + static bool refreshSet = false; + const XrDuration period = gAppState.FrameState.predictedDisplayPeriod; + if (!refreshSet && period > 0) + { + char rate[16]; + Q_snprintf(rate, sizeof(rate), "%d", (int)(1e9 / (double)period + 0.5)); + Cvar_Set2("vr_refresh", rate, true); + ALOGI("[openxr] frame period %.2f ms, vr_refresh %s", period / 1e6, rate); + refreshSet = true; + } + } if (!TBXR_ShouldRender()) { //Standby: keep the frame loop going, but the game waits too diff --git a/Projects/Android/jni/src/Lambda1VR/TBXR_Common.c b/Projects/Android/jni/src/Lambda1VR/TBXR_Common.c index 6aedfc3..f1226d5 100644 --- a/Projects/Android/jni/src/Lambda1VR/TBXR_Common.c +++ b/Projects/Android/jni/src/Lambda1VR/TBXR_Common.c @@ -504,6 +504,30 @@ static void ovrFramebuffer_Clear(ovrFramebuffer* frameBuffer) { frameBuffer->FrameBuffers = NULL; } +#ifdef L1VR_STEAM_FRAME +// The GL functions the swapchain attachments are set with, from the driver +typedef struct { + void (GL_APIENTRYP GenRenderbuffers)(GLsizei n, GLuint* renderbuffers); + void (GL_APIENTRYP BindRenderbuffer)(GLenum target, GLuint renderbuffer); + void (GL_APIENTRYP RenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + void (GL_APIENTRYP FramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + void (GL_APIENTRYP FramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + GLenum (GL_APIENTRYP CheckFramebufferStatus)(GLenum target); +} TBXR_DriverGL; + +static TBXR_DriverGL driverGL; + +static void TBXR_LoadDriverGL() +{ + driverGL.GenRenderbuffers = (void*)eglGetProcAddress("glGenRenderbuffers"); + driverGL.BindRenderbuffer = (void*)eglGetProcAddress("glBindRenderbuffer"); + driverGL.RenderbufferStorage = (void*)eglGetProcAddress("glRenderbufferStorage"); + driverGL.FramebufferTexture2D = (void*)eglGetProcAddress("glFramebufferTexture2D"); + driverGL.FramebufferRenderbuffer = (void*)eglGetProcAddress("glFramebufferRenderbuffer"); + driverGL.CheckFramebufferStatus = (void*)eglGetProcAddress("glCheckFramebufferStatus"); +} +#endif + typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); @@ -525,6 +549,9 @@ static bool ovrFramebuffer_Create( frameBuffer->Width = width; frameBuffer->Height = height; frameBuffer->Multisamples = multisamples; +#ifdef L1VR_STEAM_FRAME + TBXR_LoadDriverGL(); +#endif XrSwapchainCreateInfo swapChainCreateInfo; memset(&swapChainCreateInfo, 0, sizeof(swapChainCreateInfo)); @@ -583,22 +610,28 @@ static bool ovrFramebuffer_Create( #ifdef L1VR_STEAM_FRAME if (multisamples <= 1) { // No multisampling, so plain GLES 3 does it and the runtime's GL doesn't - // have to offer EXT_multisampled_render_to_texture. - GL(glGenRenderbuffers(1, &frameBuffer->DepthBuffers[i])); - GL(glBindRenderbuffer(GL_RENDERBUFFER, frameBuffer->DepthBuffers[i])); - GL(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height)); - GL(glBindRenderbuffer(GL_RENDERBUFFER, 0)); + // have to offer EXT_multisampled_render_to_texture. The attachments have to + // be set with the driver's own GL, the same way the EXT path above gets its + // functions: the plain names in this library are gl4es's, which would swap + // the swapchain's texture for one of its own and leave the attachment empty. + // The framebuffer itself is made and bound through gl4es though, it only + // binds framebuffers it has made (and the engine draws through it). + TBXR_DriverGL* gles = &driverGL; + gles->GenRenderbuffers(1, &frameBuffer->DepthBuffers[i]); + gles->BindRenderbuffer(GL_RENDERBUFFER, frameBuffer->DepthBuffers[i]); + gles->RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); + gles->BindRenderbuffer(GL_RENDERBUFFER, 0); GL(glGenFramebuffers(1, &frameBuffer->FrameBuffers[i])); GL(glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer->FrameBuffers[i])); - GL(glFramebufferTexture2D( - GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0)); - GL(glFramebufferRenderbuffer( + gles->FramebufferTexture2D( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0); + gles->FramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, - frameBuffer->DepthBuffers[i])); - GL(GLenum renderFramebufferStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER)); + frameBuffer->DepthBuffers[i]); + GLenum renderFramebufferStatus = gles->CheckFramebufferStatus(GL_FRAMEBUFFER); GL(glBindFramebuffer(GL_FRAMEBUFFER, 0)); if (renderFramebufferStatus != GL_FRAMEBUFFER_COMPLETE) { ALOGE( diff --git a/Projects/Android/jni/src/Xash3D/xash3d/engine/Android.mk b/Projects/Android/jni/src/Xash3D/xash3d/engine/Android.mk index 8d6e2ae..4416098 100644 --- a/Projects/Android/jni/src/Xash3D/xash3d/engine/Android.mk +++ b/Projects/Android/jni/src/Xash3D/xash3d/engine/Android.mk @@ -16,7 +16,8 @@ LOCAL_CFLAGS += -DVR # Valve Steam Frame build (gradle assembleFrame, docs/STEAM_FRAME_VR.md) ifeq ($(L1VR_STEAM_FRAME),1) -LOCAL_CFLAGS += -DL1VR_STEAM_FRAME +# the engine's messages go to logcat (tag Xash), but only with a developer level +LOCAL_CFLAGS += -DL1VR_STEAM_FRAME -DDEFAULT_DEV=3 endif LOCAL_CONLYFLAGS += -std=c99