mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-07-22 07:21:34 +00:00
* 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.
283 lines
10 KiB
C++
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;
|
|
} |