Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
cmake_minimum_required(VERSION 3.13...4.0)

if(CMAKE_CONFIGURATION_TYPES)
set(CMAKE_CONFIGURATION_TYPES "Release")
set(CMAKE_CONFIGURATION_TYPES "Release;RelWithDebInfo")
endif()

set(CMAKE_CXX_STANDARD 17)
Expand Down Expand Up @@ -169,8 +169,11 @@ check_exists(CEF_DLL_LIBRARY)
# 4505 "unreferenced local function has been removed" - supress meaningless freeglut warning
if(IS_WINDOWS)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -W4 -wd4100 -wd4127 -wd4505")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -W4 -wd4100 -wd4127 -wd4505")
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /DEBUG:FULL")
elseif(IS_MACOS)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -xobjective-c++")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -xobjective-c++")
elseif(IS_LINUX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-array-bounds")
endif()
Expand Down Expand Up @@ -199,6 +202,7 @@ add_library(
src/dullahan_debug.h
src/dullahan_impl.cpp
src/dullahan_impl.h
src/dullahan_platform_utils.h
src/dullahan_version.h
src/dullahan_version.h.in
${KEYBOARD_IMPL_SRC_FILE}
Expand Down Expand Up @@ -259,6 +263,7 @@ if(IS_WINDOWS)
target_include_directories(
dullahan_host
PUBLIC
${CMAKE_SOURCE_DIR}/src
${CEF_INCLUDE_DIR}
${CEF_INCLUDE_DIR}/..
)
Expand Down Expand Up @@ -313,6 +318,7 @@ elseif(IS_MACOS)
target_include_directories(
${_helper_target}
PUBLIC
${CMAKE_SOURCE_DIR}/src
${CEF_INCLUDE_DIR}
${CEF_INCLUDE_DIR}/..
)
Expand All @@ -330,6 +336,7 @@ elseif(IS_LINUX)
target_include_directories(
dullahan_host
PUBLIC
${CMAKE_SOURCE_DIR}/src
${CEF_INCLUDE_DIR}
${CEF_INCLUDE_DIR}/..
)
Expand All @@ -348,7 +355,7 @@ if(IS_WINDOWS)
add_custom_command(
TARGET dullahan_host POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy_directory
"$<$<CONFIG:release>:${CEF_RELEASE_BIN_DIR}>"
"$<$<OR:$<CONFIG:Release>,$<CONFIG:RelWithDebInfo>>:${CEF_RELEASE_BIN_DIR}>"
"$<TARGET_FILE_DIR:dullahan_host>"
COMMENT "Copying runtime files to executable directory")

Expand Down Expand Up @@ -408,6 +415,8 @@ if (BUILD_EXAMPLES)
dullahan
opengl32
comctl32
d3d11
dxgi
${CEF_LIBRARY}
${CEF_DLL_LIBRARY}
${THIRD-PARTY-PREFIX}/${GLFW_FOLDER}/${GLFW_LIB_PATH}
Expand Down Expand Up @@ -448,7 +457,7 @@ if (BUILD_EXAMPLES)
endif()

if(CMAKE_CONFIGURATION_TYPES)
set(CMAKE_CONFIGURATION_TYPES "Release")
set(CMAKE_CONFIGURATION_TYPES "Release;RelWithDebInfo")
endif()

# Install the Dullahan library and host executable
Expand All @@ -473,4 +482,4 @@ if( USE_SPOTIFY_CEF )
install( FILES ${CEF_RESOURCE_DIR}/${resFile} DESTINATION resources)
endif()
endforeach()
endif()
endif()
235 changes: 231 additions & 4 deletions examples/opengl-example/src/opengl-example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@

#include "opengl-example.h"

#include "dullahan.h"

void errorCallback(int error, const char* description)
{
std::cerr << "GLFW error: (" << error << ") - " << description << std::endl;
Expand Down Expand Up @@ -272,8 +270,9 @@ bool openglExample::init()
resizeCallback(width, height);

// Texture used to display browser output on the quad
// Only allocate the name - do not bind, as wglDXRegisterObjectNV
// requires the texture object to not have existing storage
glGenTextures(1, &mTextureId);
glBindTexture(GL_TEXTURE_2D, mTextureId);

// Generates the picking texture - each pixel in the texture
// holds the coordinates of its location for mouse picking
Expand Down Expand Up @@ -304,12 +303,99 @@ bool openglExample::init()
settings.use_mock_keychain = true;
#endif

#ifdef WIN32
settings.shared_texture_enable = true;
#endif

#ifdef WIN32
// Enumerate DXGI adapters to find the default GPU, create a D3D11
// device on it, and pass its LUID to dullahan so CEF renders on
// the same adapter.
IDXGIFactory1* dxgiFactory = nullptr;
IDXGIAdapter1* dxgiAdapter = nullptr;
CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&dxgiFactory);
if (dxgiFactory)
{
// Use adapter index 1 (secondary GPU)
if (dxgiFactory->EnumAdapters1(0, &dxgiAdapter) != DXGI_ERROR_NOT_FOUND)
{
DXGI_ADAPTER_DESC1 adapterDesc;
dxgiAdapter->GetDesc1(&adapterDesc);

settings.use_adapter_luid = true;
settings.adapter_luid.low_part = adapterDesc.AdapterLuid.LowPart;
settings.adapter_luid.high_part = adapterDesc.AdapterLuid.HighPart;

std::cerr << "Using GPU adapter: ";
std::wcerr << adapterDesc.Description;
std::cerr << " LUID=" << adapterDesc.AdapterLuid.HighPart
<< ":" << adapterDesc.AdapterLuid.LowPart << std::endl;
}
}

// Create D3D11 device on the selected adapter for shared texture interop
ID3D11Device* baseDevice = nullptr;
D3D_FEATURE_LEVEL featureLevel;
if (dxgiAdapter)
{
D3D11CreateDevice(dxgiAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0,
nullptr, 0, D3D11_SDK_VERSION,
&baseDevice, &featureLevel, &mD3DContext);
}
else
{
D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0,
nullptr, 0, D3D11_SDK_VERSION,
&baseDevice, &featureLevel, &mD3DContext);
}
if (baseDevice)
{
baseDevice->QueryInterface(__uuidof(ID3D11Device1), (void**)&mD3DDevice);
baseDevice->Release();
}

if (dxgiAdapter)
{
dxgiAdapter->Release();
}
if (dxgiFactory)
{
dxgiFactory->Release();
}
#endif

bool result = mDullahan->init(settings);
if (result)
{
resizeBrowser(mTextureWidth, mTextureHeight);

#ifdef WIN32
// Load WGL_NV_DX_interop2 extension functions
wglDXOpenDeviceNV = (PFNWGLDXOPENDEVICENVPROC)wglGetProcAddress("wglDXOpenDeviceNV");
wglDXCloseDeviceNV = (PFNWGLDXCLOSEDEVICENVPROC)wglGetProcAddress("wglDXCloseDeviceNV");
wglDXRegisterObjectNV = (PFNWGLDXREGISTEROBJECTNVPROC)wglGetProcAddress("wglDXRegisterObjectNV");
wglDXUnregisterObjectNV = (PFNWGLDXUNREGISTEROBJECTNVPROC)wglGetProcAddress("wglDXUnregisterObjectNV");
wglDXLockObjectsNV = (PFNWGLDXLOCKOBJECTSNVPROC)wglGetProcAddress("wglDXLockObjectsNV");
wglDXUnlockObjectsNV = (PFNWGLDXUNLOCKOBJECTSNVPROC)wglGetProcAddress("wglDXUnlockObjectsNV");

// Open D3D11 device for GL interop
if (mD3DDevice && wglDXOpenDeviceNV)
{
mInteropDevice = wglDXOpenDeviceNV(mD3DDevice);
}

std::cerr << "D3D11/GL interop setup: "
<< "D3DDevice=" << mD3DDevice
<< " wglDXOpenDeviceNV=" << (void*)wglDXOpenDeviceNV
<< " InteropDevice=" << mInteropDevice
<< std::endl;

mDullahan->setOnAcceleratedPageChangedCallback(
std::bind(&openglExample::onAcceleratedPageChanged, this,
std::placeholders::_1, std::placeholders::_2));
#else
mDullahan->setOnPageChangedCallback(std::bind(&openglExample::onPageChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
#endif
mDullahan->setOnRequestExitCallback(std::bind(&openglExample::onRequestExitCallback, this));

mDullahan->navigate(mHomeUrl);
Expand Down Expand Up @@ -439,7 +525,118 @@ bool openglExample::draw(int* tx, int* ty)
return hit_browser;
}

// Triggered when browser page content changes
#ifdef WIN32
// Triggered when accelerated (GPU) page content changes
void openglExample::onAcceleratedPageChanged(void* handle, const std::vector<dullahan::dullahan_rect>& dirty_rects)
{
if (!handle || !mInteropDevice)
{
return;
}
HANDLE viewer_handle = 0;
DuplicateHandle(
GetCurrentProcess(),
handle,
GetCurrentProcess(),
&viewer_handle,
0,
FALSE,
DUPLICATE_SAME_ACCESS);
// Open the shared D3D11 texture from the NT handle
ID3D11Texture2D* sharedTexture = nullptr;
HRESULT hr = mD3DDevice->OpenSharedResource1((HANDLE)viewer_handle, __uuidof(ID3D11Texture2D), (void**)&sharedTexture);
if (FAILED(hr))
{
return;
}

D3D11_TEXTURE2D_DESC desc;
sharedTexture->GetDesc(&desc);

// Acquire keyed mutex if present (CEF shared textures use keyed mutexes)
IDXGIKeyedMutex* keyedMutex = nullptr;
sharedTexture->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)&keyedMutex);
if (keyedMutex)
{
hr = keyedMutex->AcquireSync(0, 16);
if (FAILED(hr))
{
keyedMutex->Release();
sharedTexture->Release();
return;
}
}

// Recreate local texture and GL interop if dimensions changed
if ((int)desc.Width != mLocalTextureWidth || (int)desc.Height != mLocalTextureHeight)
{
// Tear down old interop
if (mInteropObject)
{
wglDXUnlockObjectsNV(mInteropDevice, 1, &mInteropObject);
wglDXUnregisterObjectNV(mInteropDevice, mInteropObject);
mInteropObject = nullptr;
}
if (mLocalTexture)
{
mLocalTexture->Release();
mLocalTexture = nullptr;
}

// Create a local texture without keyed mutex for GL interop
D3D11_TEXTURE2D_DESC localDesc = {};
localDesc.Width = desc.Width;
localDesc.Height = desc.Height;
localDesc.MipLevels = 1;
localDesc.ArraySize = 1;
localDesc.Format = desc.Format;
localDesc.SampleDesc.Count = 1;
localDesc.Usage = D3D11_USAGE_DEFAULT;
localDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
mD3DDevice->CreateTexture2D(&localDesc, nullptr, &mLocalTexture);

if (mLocalTexture)
{
mInteropObject = wglDXRegisterObjectNV(mInteropDevice, mLocalTexture,
mTextureId, GL_TEXTURE_2D,
WGL_ACCESS_READ_ONLY_NV);
}

mLocalTextureWidth = desc.Width;
mLocalTextureHeight = desc.Height;
mTextureWidth = desc.Width;
mTextureHeight = desc.Height;
resizeBrowser(mTextureWidth, mTextureHeight);
}

// Unlock GL access so D3D11 can write to the local texture
if (mInteropObject)
{
wglDXUnlockObjectsNV(mInteropDevice, 1, &mInteropObject);
}

// Copy from shared texture to local texture (GPU-to-GPU)
if (mLocalTexture)
{
mD3DContext->CopyResource(mLocalTexture, sharedTexture);
}

// Release the keyed mutex and shared texture
if (keyedMutex)
{
keyedMutex->ReleaseSync(0);
keyedMutex->Release();
}
sharedTexture->Release();

// Lock the local texture for GL access
if (mInteropObject)
{
wglDXLockObjectsNV(mInteropDevice, 1, &mInteropObject);
}
}
#else
// Triggered when browser page content changes (software path)
void openglExample::onPageChanged(const unsigned char* pixels, int x, int y, const int width, const int height)
{
if (width != mTextureWidth || height != mTextureHeight)
Expand All @@ -456,6 +653,7 @@ void openglExample::onPageChanged(const unsigned char* pixels, int x, int y, con
glBindTexture(GL_TEXTURE_2D, (GLuint)mTextureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)mTextureWidth, (GLsizei)mTextureHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
}
#endif

// Triggered by Dullahan when cleanup is complete and it's okay to exit
void openglExample::onRequestExitCallback()
Expand Down Expand Up @@ -683,6 +881,35 @@ bool openglExample::run()

bool openglExample::reset()
{
#ifdef WIN32
if (mInteropObject)
{
wglDXUnlockObjectsNV(mInteropDevice, 1, &mInteropObject);
wglDXUnregisterObjectNV(mInteropDevice, mInteropObject);
mInteropObject = nullptr;
}
if (mLocalTexture)
{
mLocalTexture->Release();
mLocalTexture = nullptr;
}
if (mInteropDevice)
{
wglDXCloseDeviceNV(mInteropDevice);
mInteropDevice = nullptr;
}
if (mD3DContext)
{
mD3DContext->Release();
mD3DContext = nullptr;
}
if (mD3DDevice)
{
mD3DDevice->Release();
mD3DDevice = nullptr;
}
#endif

resetUI();

glfwDestroyWindow(mWindow);
Expand Down
Loading
Loading