Files
renderdoc/renderdoc/driver/gl/gl_hooks_vrapi.cpp
T
baldurk 4a6462b63b Compile in interceptor-lib if LLVM is found, and use to hook on android
* Note we still have to use PLT hooking for android_dlopen_ext that
  libvulkan uses to load layers, since interceptor-lib can't hook that,
  and otherwise libvulkan will load our library multiple times into the
  process instead of re-using the existing injected library.
2018-01-31 18:24:14 +00:00

283 lines
10 KiB
C++

/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2017-2018 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include <dlfcn.h>
#include "core/core.h"
#include "driver/gl/gl_common.h"
#include "driver/gl/gl_driver.h"
#include "driver/gl/gl_hooks_linux_shared.h"
#include "hooks/hooks.h"
#include "official/VrApi_Types.h"
//-----------------------------------------------------------------------------------------------------------------
typedef void (*PFN_vrapi_SubmitFrame)(ovrMobile *, const ovrFrameParms *);
typedef int (*PFN_vrapi_GetTextureSwapChainLength)(ovrTextureSwapChain *);
typedef unsigned int (*PFN_vrapi_GetTextureSwapChainHandle)(ovrTextureSwapChain *, int);
typedef int (*PFN_vrapi_GetSystemPropertyInt)(const ovrJava *, const ovrSystemProperty);
typedef ovrTextureSwapChain *(*PFN_vrapi_CreateTextureSwapChain2)(ovrTextureType, ovrTextureFormat,
int, int, int, int);
typedef ovrTextureSwapChain *(*PFN_vrapi_CreateTextureSwapChain)(ovrTextureType, ovrTextureFormat,
int, int, int, bool);
//-----------------------------------------------------------------------------------------------------------------
void *libvrapi_symHandle = RTLD_NEXT;
//-----------------------------------------------------------------------------------------------------------------
class VRAPIHook : LibraryHook
{
public:
VRAPIHook()
: vrapi_SubmitFrame_real(NULL),
vrapi_GetTextureSwapChainLength_real(NULL),
vrapi_GetTextureSwapChainHandle_real(NULL),
vrapi_GetSystemPropertyInt_real(NULL),
m_PopulatedHooks(false),
m_HasHooks(false)
{
LibraryHooks::GetInstance().RegisterHook("libvrapi.so", this);
m_EnabledHooks = true;
}
~VRAPIHook() {}
static void libHooked(void *realLib);
bool CreateHooks(const char *libName);
void EnableHooks(const char *libName, bool enable) { m_EnabledHooks = enable; }
void OptionsUpdated(const char *libName) {}
void SetupExportedFunctions()
{
if(RenderDoc::Inst().IsReplayApp())
SetupHooks();
}
//---------------------------------------------------------------------------------------------------------
PFN_vrapi_CreateTextureSwapChain2 vrapi_CreateTextureSwapChain2_real;
PFN_vrapi_CreateTextureSwapChain vrapi_CreateTextureSwapChain_real;
PFN_vrapi_SubmitFrame vrapi_SubmitFrame_real;
PFN_vrapi_GetTextureSwapChainLength vrapi_GetTextureSwapChainLength_real;
PFN_vrapi_GetTextureSwapChainHandle vrapi_GetTextureSwapChainHandle_real;
PFN_vrapi_GetSystemPropertyInt vrapi_GetSystemPropertyInt_real;
bool m_PopulatedHooks;
bool m_HasHooks;
bool m_EnabledHooks;
bool SetupHooks()
{
if(vrapi_CreateTextureSwapChain2_real == NULL)
vrapi_CreateTextureSwapChain2_real = (PFN_vrapi_CreateTextureSwapChain2)PosixGetFunction(
libvrapi_symHandle, "vrapi_CreateTextureSwapChain2");
if(vrapi_CreateTextureSwapChain_real == NULL)
vrapi_CreateTextureSwapChain_real = (PFN_vrapi_CreateTextureSwapChain)PosixGetFunction(
libvrapi_symHandle, "vrapi_CreateTextureSwapChain");
if(vrapi_SubmitFrame_real == NULL)
vrapi_SubmitFrame_real =
(PFN_vrapi_SubmitFrame)PosixGetFunction(libvrapi_symHandle, "vrapi_SubmitFrame");
if(vrapi_GetTextureSwapChainLength_real == NULL)
vrapi_GetTextureSwapChainLength_real = (PFN_vrapi_GetTextureSwapChainLength)PosixGetFunction(
libvrapi_symHandle, "vrapi_GetTextureSwapChainLength");
if(vrapi_GetTextureSwapChainHandle_real == NULL)
vrapi_GetTextureSwapChainHandle_real = (PFN_vrapi_GetTextureSwapChainHandle)PosixGetFunction(
libvrapi_symHandle, "vrapi_GetTextureSwapChainHandle");
if(vrapi_GetSystemPropertyInt_real == NULL)
vrapi_GetSystemPropertyInt_real = (PFN_vrapi_GetSystemPropertyInt)PosixGetFunction(
libvrapi_symHandle, "vrapi_GetSystemPropertyInt");
return vrapi_SubmitFrame_real != NULL;
}
} vrapi_hooks;
//-----------------------------------------------------------------------------------------------------------------
GLenum GetInternalFormat(ovrTextureFormat ovr_format)
{
GLenum internalFormat = eGL_RGBA8;
GLenum conversion_table[] = {
eGL_RGBA8, // VRAPI_TEXTURE_FORMAT_NONE,
eGL_RGB565, // VRAPI_TEXTURE_FORMAT_565,
eGL_RGB5_A1, // VRAPI_TEXTURE_FORMAT_5551,
eGL_RGBA4, // VRAPI_TEXTURE_FORMAT_4444,
eGL_RGBA8, // VRAPI_TEXTURE_FORMAT_8888,
eGL_SRGB8_ALPHA8, // VRAPI_TEXTURE_FORMAT_8888_sRGB,
eGL_RGBA16F, // VRAPI_TEXTURE_FORMAT_RGBA16F,
eGL_DEPTH_COMPONENT16, // VRAPI_TEXTURE_FORMAT_DEPTH_16,
eGL_DEPTH_COMPONENT24, // VRAPI_TEXTURE_FORMAT_DEPTH_24,
eGL_DEPTH24_STENCIL8 // VRAPI_TEXTURE_FORMAT_DEPTH_24_STENCIL_8,
};
RDCASSERT(ovr_format < ARRAY_COUNT(conversion_table));
if(ovr_format < ARRAY_COUNT(conversion_table))
{
internalFormat = conversion_table[ovr_format];
}
return internalFormat;
}
GLenum GetTextureType(ovrTextureType ovr_tex_type)
{
GLenum textureType = eGL_TEXTURE_2D;
GLenum conversion_table[] = {
eGL_TEXTURE_2D, // VRAPI_TEXTURE_TYPE_2D,
eGL_TEXTURE_2D, // VRAPI_TEXTURE_TYPE_2D_EXTERNAL,
eGL_TEXTURE_2D_ARRAY, // VRAPI_TEXTURE_TYPE_2D_ARRAY,
eGL_TEXTURE_CUBE_MAP // VRAPI_TEXTURE_TYPE_CUBE
};
RDCASSERT(ovr_tex_type < ARRAY_COUNT(conversion_table));
if(ovr_tex_type < ARRAY_COUNT(conversion_table))
{
textureType = conversion_table[ovr_tex_type];
}
return textureType;
}
//-----------------------------------------------------------------------------------------------------------------
extern "C" {
__attribute__((visibility("default"))) ovrTextureSwapChain *vrapi_CreateTextureSwapChain2(
ovrTextureType type, ovrTextureFormat format, int width, int height, int levels, int bufferCount)
{
if(vrapi_hooks.vrapi_CreateTextureSwapChain2_real == NULL ||
vrapi_hooks.vrapi_GetTextureSwapChainHandle_real == NULL ||
vrapi_hooks.vrapi_GetTextureSwapChainLength_real == NULL)
{
vrapi_hooks.SetupHooks();
}
ovrTextureSwapChain *texture_swapchain = vrapi_hooks.vrapi_CreateTextureSwapChain2_real(
type, format, width, height, levels, bufferCount);
if(m_GLDriver)
{
int tex_count = vrapi_hooks.vrapi_GetTextureSwapChainLength_real(texture_swapchain);
SCOPED_LOCK(glLock);
for(int i = 0; i < tex_count; ++i)
{
GLuint tex = vrapi_hooks.vrapi_GetTextureSwapChainHandle_real(texture_swapchain, i);
GLenum internalformat = GetInternalFormat(format);
GLenum textureType = GetTextureType(type);
gl_CurChunk = GLChunk::vrapi_CreateTextureSwapChain2;
m_GLDriver->CreateVRAPITextureSwapChain(tex, textureType, internalformat, width, height,
levels);
}
}
return texture_swapchain;
}
__attribute__((visibility("default"))) ovrTextureSwapChain *vrapi_CreateTextureSwapChain(
ovrTextureType type, ovrTextureFormat format, int width, int height, int levels, bool buffered)
{
if(vrapi_hooks.vrapi_CreateTextureSwapChain_real == NULL ||
vrapi_hooks.vrapi_GetTextureSwapChainHandle_real == NULL ||
vrapi_hooks.vrapi_GetTextureSwapChainLength_real == NULL)
{
vrapi_hooks.SetupHooks();
}
ovrTextureSwapChain *texture_swapchain =
vrapi_hooks.vrapi_CreateTextureSwapChain_real(type, format, width, height, levels, buffered);
if(m_GLDriver)
{
int tex_count = vrapi_hooks.vrapi_GetTextureSwapChainLength_real(texture_swapchain);
SCOPED_LOCK(glLock);
for(int i = 0; i < tex_count; ++i)
{
GLuint tex = vrapi_hooks.vrapi_GetTextureSwapChainHandle_real(texture_swapchain, i);
GLenum internalformat = GetInternalFormat(format);
GLenum textureType = GetTextureType(type);
gl_CurChunk = GLChunk::vrapi_CreateTextureSwapChain;
m_GLDriver->CreateVRAPITextureSwapChain(tex, textureType, internalformat, width, height,
levels);
}
}
return texture_swapchain;
}
__attribute__((visibility("default"))) void vrapi_SubmitFrame(ovrMobile *ovr,
const ovrFrameParms *parms)
{
if(vrapi_hooks.vrapi_SubmitFrame_real == NULL || vrapi_hooks.vrapi_GetSystemPropertyInt_real == NULL)
{
vrapi_hooks.SetupHooks();
}
if(m_GLDriver)
{
SCOPED_LOCK(glLock);
m_GLDriver->SwapBuffers(ovr);
}
vrapi_hooks.vrapi_SubmitFrame_real(ovr, parms);
}
} // extern "C"
void VRAPIHook::libHooked(void *realLib)
{
libvrapi_symHandle = realLib;
vrapi_hooks.CreateHooks(NULL);
}
bool VRAPIHook::CreateHooks(const char *libName)
{
if(!m_EnabledHooks)
return false;
if(libName)
{
PosixHookFunction("vrapi_CreateTextureSwapChain2", (void *)&vrapi_CreateTextureSwapChain2);
PosixHookFunction("vrapi_CreateTextureSwapChain", (void *)&vrapi_CreateTextureSwapChain);
PosixHookFunction("vrapi_SubmitFrame", (void *)&vrapi_SubmitFrame);
PosixHookLibrary(libName, &libHooked);
return true;
}
bool success = SetupHooks();
if(!success)
return false;
m_HasHooks = true;
return true;
}