summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2021-03-11 09:14:30 -0800
committerGitHub <noreply@github.com>2021-03-11 09:14:30 -0800
commita07455c175db33d8d95bc5cd83738808d74cd105 (patch)
tree02660537db912b7d48f34c751dc5731b88daa0db
parent6cbd9d68a03f0a22305d4e224a3da7633b23de38 (diff)
Add Linux support to `platform` and `gfx`. (#1744)
-rw-r--r--build/visual-studio/platform/platform.vcxproj46
-rw-r--r--build/visual-studio/platform/platform.vcxproj.filters9
-rw-r--r--examples/gpu-printing/gpu-printing.cpp2
-rw-r--r--examples/hello-world/main.cpp3
-rw-r--r--examples/shader-toy/main.cpp4
-rw-r--r--premake5.lua78
-rw-r--r--source/core/slang-downstream-compiler.cpp5
-rw-r--r--source/core/slang-platform.cpp2
-rw-r--r--source/slang/slang-check.cpp2
-rw-r--r--tools/gfx/immediate-renderer-base.cpp36
-rw-r--r--tools/gfx/render.cpp6
-rw-r--r--tools/gfx/vulkan/render-vk.cpp51
-rw-r--r--tools/platform/gui.cpp3
-rw-r--r--tools/platform/linux/x11-key-code.cpp247
-rw-r--r--tools/platform/linux/x11-window.cpp474
-rw-r--r--tools/platform/placeholder/placeholder-window.cpp33
-rw-r--r--tools/platform/window.h60
-rw-r--r--tools/platform/windows/win-window.cpp2
18 files changed, 964 insertions, 99 deletions
diff --git a/build/visual-studio/platform/platform.vcxproj b/build/visual-studio/platform/platform.vcxproj
index 518ac20f7..63085d492 100644
--- a/build/visual-studio/platform/platform.vcxproj
+++ b/build/visual-studio/platform/platform.vcxproj
@@ -27,25 +27,25 @@
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
@@ -67,34 +67,38 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
<OutDir>..\..\..\bin\windows-x86\debug\</OutDir>
<IntDir>..\..\..\intermediate\windows-x86\debug\platform\</IntDir>
<TargetName>platform</TargetName>
- <TargetExt>.lib</TargetExt>
+ <TargetExt>.dll</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
<OutDir>..\..\..\bin\windows-x64\debug\</OutDir>
<IntDir>..\..\..\intermediate\windows-x64\debug\platform\</IntDir>
<TargetName>platform</TargetName>
- <TargetExt>.lib</TargetExt>
+ <TargetExt>.dll</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
<OutDir>..\..\..\bin\windows-x86\release\</OutDir>
<IntDir>..\..\..\intermediate\windows-x86\release\platform\</IntDir>
<TargetName>platform</TargetName>
- <TargetExt>.lib</TargetExt>
+ <TargetExt>.dll</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
<OutDir>..\..\..\bin\windows-x64\release\</OutDir>
<IntDir>..\..\..\intermediate\windows-x64\release\platform\</IntDir>
<TargetName>platform</TargetName>
- <TargetExt>.lib</TargetExt>
+ <TargetExt>.dll</TargetExt>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
- <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;SLANG_PLATFORM_DYNAMIC;SLANG_PLATFORM_DYNAMIC_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\external\imgui;..\..\..\tools\gfx;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<Optimization>Disabled</Optimization>
@@ -103,13 +107,14 @@
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>..\..\..\bin\windows-x86\debug\platform.lib</ImportLibrary>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
- <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>_DEBUG;SLANG_PLATFORM_DYNAMIC;SLANG_PLATFORM_DYNAMIC_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\external\imgui;..\..\..\tools\gfx;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<Optimization>Disabled</Optimization>
@@ -118,13 +123,14 @@
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>..\..\..\bin\windows-x64\debug\platform.lib</ImportLibrary>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
- <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;SLANG_PLATFORM_DYNAMIC;SLANG_PLATFORM_DYNAMIC_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\external\imgui;..\..\..\tools\gfx;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -137,13 +143,14 @@
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
+ <ImportLibrary>..\..\..\bin\windows-x86\release\platform.lib</ImportLibrary>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
- <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NDEBUG;SLANG_PLATFORM_DYNAMIC;SLANG_PLATFORM_DYNAMIC_EXPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\external\imgui;..\..\..\tools\gfx;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -156,6 +163,7 @@
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
+ <ImportLibrary>..\..\..\bin\windows-x64\release\platform.lib</ImportLibrary>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
@@ -167,9 +175,23 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\tools\platform\gui.cpp" />
+ <ClCompile Include="..\..\..\tools\platform\linux\x11-key-code.cpp" />
+ <ClCompile Include="..\..\..\tools\platform\linux\x11-window.cpp" />
<ClCompile Include="..\..\..\tools\platform\model.cpp" />
+ <ClCompile Include="..\..\..\tools\platform\placeholder\placeholder-window.cpp" />
<ClCompile Include="..\..\..\tools\platform\windows\win-window.cpp" />
</ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\core\core.vcxproj">
+ <Project>{F9BE7957-8399-899E-0C49-E714FDDD4B65}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\slang\slang.vcxproj">
+ <Project>{DB00DA62-0533-4AFD-B59F-A67D5B3A0808}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\gfx\gfx.vcxproj">
+ <Project>{222F7498-B40C-4F3F-A704-DDEB91A4484A}</Project>
+ </ProjectReference>
+ </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
diff --git a/build/visual-studio/platform/platform.vcxproj.filters b/build/visual-studio/platform/platform.vcxproj.filters
index 17d756451..f90263e01 100644
--- a/build/visual-studio/platform/platform.vcxproj.filters
+++ b/build/visual-studio/platform/platform.vcxproj.filters
@@ -29,9 +29,18 @@
<ClCompile Include="..\..\..\tools\platform\gui.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\tools\platform\linux\x11-key-code.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\tools\platform\linux\x11-window.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\tools\platform\model.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\tools\platform\placeholder\placeholder-window.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\tools\platform\windows\win-window.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/examples/gpu-printing/gpu-printing.cpp b/examples/gpu-printing/gpu-printing.cpp
index 7503c8e03..f1e842e95 100644
--- a/examples/gpu-printing/gpu-printing.cpp
+++ b/examples/gpu-printing/gpu-printing.cpp
@@ -3,6 +3,8 @@
#include <assert.h>
+#include <string.h>
+
// This file implements the CPU side of a simple GPU printing
// library. The CPU code is responsible for scanning through
// buffers of "print commands" produced by GPU shaders, and
diff --git a/examples/hello-world/main.cpp b/examples/hello-world/main.cpp
index 7b43abcab..b3bee9c07 100644
--- a/examples/hello-world/main.cpp
+++ b/examples/hello-world/main.cpp
@@ -322,8 +322,7 @@ Slang::Result initialize()
swapchainDesc.height = gWindowHeight;
swapchainDesc.imageCount = kSwapchainImageCount;
swapchainDesc.queue = gQueue;
- gfx::WindowHandle windowHandle;
- memcpy(&windowHandle, &gWindow->getNativeHandle(), sizeof(windowHandle));
+ gfx::WindowHandle windowHandle = gWindow->getNativeHandle().convert<gfx::WindowHandle>();
gSwapchain = gDevice->createSwapchain(swapchainDesc, windowHandle);
IFramebufferLayout::AttachmentLayout renderTargetLayout = {gSwapchain->getDesc().format, 1};
diff --git a/examples/shader-toy/main.cpp b/examples/shader-toy/main.cpp
index 70bff13a8..27fdf4daa 100644
--- a/examples/shader-toy/main.cpp
+++ b/examples/shader-toy/main.cpp
@@ -442,9 +442,7 @@ Result initialize()
swapchainDesc.height = gWindowHeight;
swapchainDesc.imageCount = kSwapchainImageCount;
swapchainDesc.queue = gQueue;
- gfx::WindowHandle windowHandle;
- memcpy(&windowHandle, &gWindow->getNativeHandle(), sizeof(windowHandle));
- gSwapchain = gDevice->createSwapchain(swapchainDesc, windowHandle);
+ gSwapchain = gDevice->createSwapchain(swapchainDesc, gWindow->getNativeHandle().convert<gfx::WindowHandle>());
IFramebufferLayout::AttachmentLayout renderTargetLayout = {gSwapchain->getDesc().format, 1};
IFramebufferLayout::AttachmentLayout depthLayout = {gfx::Format::D_Float32, 1};
diff --git a/premake5.lua b/premake5.lua
index bd5c72c63..a5a94971d 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -135,6 +135,14 @@ newoption {
allowed = { { "true", "True"}, { "false", "False" } }
}
+newoption {
+ trigger = "enable-xlib",
+ description = "(Optional) If true build `gfx` and `platform` with xlib to support windowed apps on linux.",
+ value = "bool",
+ default = "true",
+ allowed = { { "true", "True"}, { "false", "False" } }
+ }
+
buildLocation = _OPTIONS["build-location"]
executeBinary = (_OPTIONS["execute-binary"] == "true")
targetDetail = _OPTIONS["target-detail"]
@@ -145,7 +153,7 @@ optixPath = _OPTIONS["optix-sdk-path"]
enableOptix = not not (_OPTIONS["enable-optix"] == "true" or optixPath)
enableProfile = (_OPTIONS["enable-profile"] == "true")
enableEmbedStdLib = (_OPTIONS["enable-embed-stdlib"] == "true")
-
+enableXlib = (_OPTIONS["enable-xlib"] == "true")
-- This is the path where nvapi is expected to be found
nvapiPath = "external/nvapi"
@@ -165,6 +173,10 @@ end
-- Is true when the target is really windows (ie not something on top of windows like cygwin)
isTargetWindows = (os.target() == "windows") and not (targetDetail == "mingw" or targetDetail == "cygwin")
+if isTargetWindows then
+ enableXlib = false
+end
+
-- Even if we have the nvapi path, we only want to currently enable on windows targets
enableNvapi = not not (os.isdir(nvapiPath) and isTargetWindows and _OPTIONS["enable-nvapi"] == "true")
@@ -526,6 +538,15 @@ function example(name)
-- depends on the `core` library). We specify all of that here,
-- rather than in each example.
links { "slang", "core", "gfx", "gfx-util", "platform" }
+
+ if isTargetWindows then
+ else
+ if enableXlib then
+ defines { "SLANG_ENABLE_XLIB" }
+ libdirs { "/usr/X11/lib" }
+ links {"X11"}
+ end
+ end
end
--
@@ -552,26 +573,24 @@ function generatorProject(name, sourcePath)
kind "StaticLib"
end
-if isTargetWindows then
- --
- -- With all of these helper routines defined, we can now define the
- -- actual projects quite simply. For example, here is the entire
- -- declaration of the "Hello, World" example project:
- --
- example "hello-world"
- --
- -- Note how we are calling our custom `example()` subroutine with
- -- the same syntax sugar that Premake usually advocates for their
- -- `project()` function. This allows us to treat `example` as
- -- a kind of specialized "subclass" of `project`
- --
+--
+-- With all of these helper routines defined, we can now define the
+-- actual projects quite simply. For example, here is the entire
+-- declaration of the "Hello, World" example project:
+--
+example "hello-world"
+--
+-- Note how we are calling our custom `example()` subroutine with
+-- the same syntax sugar that Premake usually advocates for their
+-- `project()` function. This allows us to treat `example` as
+-- a kind of specialized "subclass" of `project`
+--
- -- Let's go ahead and set up the projects for our other example now.
- example "gpu-printing"
- kind "ConsoleApp"
+-- Let's go ahead and set up the projects for our other example now.
+example "gpu-printing"
+ kind "ConsoleApp"
- example "shader-toy"
-end
+example "shader-toy"
example "shader-object"
kind "ConsoleApp"
@@ -788,10 +807,16 @@ tool "gfx"
--addSourceDir "tools/gfx/open-gl"
else
-- Linux like
- --addSourceDir "tools/gfx/vulkan"
+ addSourceDir "tools/gfx/vulkan"
--addSourceDir "tools/gfx/open-gl"
end
+ if enableXlib then
+ defines { "SLANG_ENABLE_XLIB" }
+ libdirs { "/usr/X11/lib" }
+ links {"X11"}
+ end
+
-- If NVAPI is enabled
if enableNvapi then
-- Add the include path
@@ -828,17 +853,24 @@ tool "gfx-util"
--
tool "platform"
uuid "3565fe5e-4fa3-11eb-ae93-0242ac130002"
- kind "StaticLib"
+ kind "SharedLib"
pic "On"
-
+ links {"core", "slang", "gfx" }
+ defines { "SLANG_PLATFORM_DYNAMIC", "SLANG_PLATFORM_DYNAMIC_EXPORT" }
includedirs { ".", "external", "source", "external/imgui", "tools/gfx" }
-
addSourceDir "tools/platform"
addSourceDir "tools/platform/linux"
addSourceDir "tools/platform/windows"
+ addSourceDir "tools/platform/placeholder"
-- Include windowing support on Windows.
if isTargetWindows then
systemversion "10.0.14393.0"
+ else
+ if enableXlib then
+ defines { "SLANG_ENABLE_XLIB" }
+ libdirs { "/usr/X11/lib" }
+ links {"X11"}
+ end
end
--
diff --git a/source/core/slang-downstream-compiler.cpp b/source/core/slang-downstream-compiler.cpp
index b9b5a059d..1a81fcac8 100644
--- a/source/core/slang-downstream-compiler.cpp
+++ b/source/core/slang-downstream-compiler.cpp
@@ -610,6 +610,11 @@ static SlangResult _locateFXCCompilers(const String& path, ISlangSharedLibraryLo
static SlangResult _locateGlslangCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set)
{
+#if SLANG_UNIX_FAMILY
+ // On unix systems we need to ensure pthread is loaded first.
+ ComPtr<ISlangSharedLibrary> pthreadLibrary;
+ DefaultSharedLibraryLoader::load(loader, path, "pthread", pthreadLibrary.writeRef());
+#endif
ComPtr<ISlangSharedLibrary> sharedLibrary;
if (SLANG_SUCCEEDED(DefaultSharedLibraryLoader::load(loader, path, "slang-glslang", sharedLibrary.writeRef())))
{
diff --git a/source/core/slang-platform.cpp b/source/core/slang-platform.cpp
index 20dfed5a8..e46851095 100644
--- a/source/core/slang-platform.cpp
+++ b/source/core/slang-platform.cpp
@@ -171,7 +171,7 @@ SLANG_COMPILE_TIME_ASSERT(E_OUTOFMEMORY == SLANG_E_OUT_OF_MEMORY);
{
handleOut = nullptr;
- void* h = dlopen(platformFileName, RTLD_NOW | RTLD_LOCAL);
+ void* h = dlopen(platformFileName, RTLD_NOW | RTLD_GLOBAL);
if(!h)
{
#if 0
diff --git a/source/slang/slang-check.cpp b/source/slang/slang-check.cpp
index 7f378f7b7..cfc8c504c 100644
--- a/source/slang/slang-check.cpp
+++ b/source/slang/slang-check.cpp
@@ -146,7 +146,7 @@ namespace Slang
if (SLANG_FAILED(locator(m_downstreamCompilerPaths[int(type)], m_sharedLibraryLoader, m_downstreamCompilerSet)))
{
// If the locator reported a failure the first time we invoked
- // it, then we will invoke it against with a wrapper shared librar
+ // it, then we will invoke it against with a wrapper shared library
// loader that reported library load failures to our diagnost `sink`.
//
// This means that in the case of failure the user will see a listing
diff --git a/tools/gfx/immediate-renderer-base.cpp b/tools/gfx/immediate-renderer-base.cpp
index 36d98f957..14c6cf217 100644
--- a/tools/gfx/immediate-renderer-base.cpp
+++ b/tools/gfx/immediate-renderer-base.cpp
@@ -57,8 +57,8 @@ public:
*outObject = nullptr;
return SLANG_E_NO_INTERFACE;
}
- virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() { return 1; }
- virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() { return 1; }
+ virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() override { return 1; }
+ virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() override { return 1; }
public:
CommandWriter* m_writer;
@@ -99,13 +99,13 @@ public:
m_writer->clearFrame(clearMask, clearDepth, clearStencil);
}
- virtual SLANG_NO_THROW void SLANG_MCALL setPipelineState(IPipelineState* state)
+ virtual SLANG_NO_THROW void SLANG_MCALL setPipelineState(IPipelineState* state) override
{
m_writer->setPipelineState(state);
}
virtual SLANG_NO_THROW void SLANG_MCALL
- bindRootShaderObject(IShaderObject* object)
+ bindRootShaderObject(IShaderObject* object) override
{
m_writer->bindRootShaderObject(PipelineType::Graphics, object);
}
@@ -113,22 +113,22 @@ public:
virtual SLANG_NO_THROW void SLANG_MCALL setDescriptorSet(
IPipelineLayout* layout,
UInt index,
- IDescriptorSet* descriptorSet)
+ IDescriptorSet* descriptorSet) override
{
m_writer->setDescriptorSet(PipelineType::Graphics, layout, index, descriptorSet);
}
virtual SLANG_NO_THROW void SLANG_MCALL
- setViewports(uint32_t count, const Viewport* viewports)
+ setViewports(uint32_t count, const Viewport* viewports) override
{
m_writer->setViewports(count, viewports);
}
virtual SLANG_NO_THROW void SLANG_MCALL
- setScissorRects(uint32_t count, const ScissorRect* scissors)
+ setScissorRects(uint32_t count, const ScissorRect* scissors) override
{
m_writer->setScissorRects(count, scissors);
}
- virtual SLANG_NO_THROW void SLANG_MCALL setPrimitiveTopology(PrimitiveTopology topology)
+ virtual SLANG_NO_THROW void SLANG_MCALL setPrimitiveTopology(PrimitiveTopology topology) override
{
m_writer->setPrimitiveTopology(topology);
}
@@ -137,29 +137,29 @@ public:
UInt slotCount,
IBufferResource* const* buffers,
const UInt* strides,
- const UInt* offsets)
+ const UInt* offsets) override
{
m_writer->setVertexBuffers(startSlot, slotCount, buffers, strides, offsets);
}
virtual SLANG_NO_THROW void SLANG_MCALL
- setIndexBuffer(IBufferResource* buffer, Format indexFormat, UInt offset)
+ setIndexBuffer(IBufferResource* buffer, Format indexFormat, UInt offset) override
{
m_writer->setIndexBuffer(buffer, indexFormat, offset);
}
- virtual SLANG_NO_THROW void SLANG_MCALL draw(UInt vertexCount, UInt startVertex)
+ virtual SLANG_NO_THROW void SLANG_MCALL draw(UInt vertexCount, UInt startVertex) override
{
m_writer->draw(vertexCount, startVertex);
}
virtual SLANG_NO_THROW void SLANG_MCALL
- drawIndexed(UInt indexCount, UInt startIndex, UInt baseVertex)
+ drawIndexed(UInt indexCount, UInt startIndex, UInt baseVertex) override
{
m_writer->drawIndexed(indexCount, startIndex, baseVertex);
}
- virtual SLANG_NO_THROW void SLANG_MCALL setStencilReference(uint32_t referenceValue)
+ virtual SLANG_NO_THROW void SLANG_MCALL setStencilReference(uint32_t referenceValue) override
{
m_writer->setStencilReference(referenceValue);
}
@@ -193,8 +193,8 @@ public:
*outObject = nullptr;
return SLANG_E_NO_INTERFACE;
}
- virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() { return 1; }
- virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() { return 1; }
+ virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() override { return 1; }
+ virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() override { return 1; }
public:
CommandWriter* m_writer;
@@ -255,8 +255,8 @@ public:
*outObject = nullptr;
return SLANG_E_NO_INTERFACE;
}
- virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() { return 1; }
- virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() { return 1; }
+ virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() override { return 1; }
+ virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() override { return 1; }
public:
CommandWriter* m_writer;
@@ -278,7 +278,7 @@ public:
}
virtual SLANG_NO_THROW void SLANG_MCALL
- uploadBufferData(IBufferResource* dst, size_t offset, size_t size, void* data)
+ uploadBufferData(IBufferResource* dst, size_t offset, size_t size, void* data) override
{
m_writer->uploadBufferData(dst, offset, size, data);
}
diff --git a/tools/gfx/render.cpp b/tools/gfx/render.cpp
index 5ef2a454e..4ecb52287 100644
--- a/tools/gfx/render.cpp
+++ b/tools/gfx/render.cpp
@@ -90,6 +90,12 @@ extern "C"
return SLANG_FAIL;
}
break;
+#elif SLANG_LINUX_FAMILY
+ case DeviceType::Default:
+ case DeviceType::Vulkan:
+ {
+ return createVKDevice(desc, outDevice);
+ }
#endif
default:
diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp
index c0ece3e2f..ee494d4c8 100644
--- a/tools/gfx/vulkan/render-vk.cpp
+++ b/tools/gfx/vulkan/render-vk.cpp
@@ -30,6 +30,11 @@
# endif
#endif
+// Undef xlib macros
+#ifdef Always
+#undef Always
+#endif
+
namespace gfx {
using namespace Slang;
@@ -1552,7 +1557,7 @@ public:
size_t dstOffset,
IBufferResource* src,
size_t srcOffset,
- size_t size)
+ size_t size) override
{
SLANG_UNUSED(dst);
SLANG_UNUSED(srcOffset);
@@ -1561,7 +1566,7 @@ public:
SLANG_UNUSED(size);
}
virtual SLANG_NO_THROW void SLANG_MCALL
- uploadBufferData(IBufferResource* buffer, size_t offset, size_t size, void* data)
+ uploadBufferData(IBufferResource* buffer, size_t offset, size_t size, void* data) override
{
_uploadBufferData(
m_commandBuffer->m_commandBuffer,
@@ -1850,9 +1855,7 @@ public:
::GetClientRect((HWND)m_windowHandle.handleValues[0], &rc);
*widthOut = rc.right - rc.left;
*heightOut = rc.bottom - rc.top;
-#else
- auto platformDesc = _getPlatformDesc<XPlatformDesc>();
-
+#elif defined(SLANG_ENABLE_XLIB)
XWindowAttributes winAttr = {};
XGetWindowAttributes(
(Display*)m_windowHandle.handleValues[0],
@@ -1861,6 +1864,9 @@ public:
*widthOut = winAttr.width;
*heightOut = winAttr.height;
+#else
+ *widthOut = 0;
+ *heightOut = 0;
#endif
}
@@ -2088,9 +2094,9 @@ public:
return SLANG_OK;
}
- virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() { return m_desc; }
+ virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() override { return m_desc; }
virtual SLANG_NO_THROW Result
- SLANG_MCALL getImage(uint32_t index, ITextureResource** outResource)
+ SLANG_MCALL getImage(uint32_t index, ITextureResource** outResource) override
{
if (m_images.getCount() <= (Index)index)
return SLANG_FAIL;
@@ -2098,14 +2104,14 @@ public:
m_images[index]->addRef();
return SLANG_OK;
}
- virtual SLANG_NO_THROW Result SLANG_MCALL resize(uint32_t width, uint32_t height)
+ virtual SLANG_NO_THROW Result SLANG_MCALL resize(uint32_t width, uint32_t height) override
{
SLANG_UNUSED(width);
SLANG_UNUSED(height);
destroySwapchainAndImages();
return createSwapchainAndImages();
}
- virtual SLANG_NO_THROW Result SLANG_MCALL present()
+ virtual SLANG_NO_THROW Result SLANG_MCALL present() override
{
uint32_t swapChainIndices[] = {uint32_t(m_currentImageIndex)};
@@ -2123,7 +2129,7 @@ public:
m_queue->m_pendingWaitSemaphore = VK_NULL_HANDLE;
return SLANG_OK;
}
- virtual SLANG_NO_THROW int SLANG_MCALL acquireNextImage()
+ virtual SLANG_NO_THROW int SLANG_MCALL acquireNextImage() override
{
if (!m_images.getCount())
return -1;
@@ -2283,9 +2289,9 @@ VkBool32 VKDevice::handleDebugMessage(VkDebugReportFlagsEXT flags, VkDebugReport
fprintf(stderr, "%s", buffer);
fflush(stderr);
-
+#ifdef _WIN32
OutputDebugStringA(buffer);
-
+#endif
return VK_FALSE;
}
@@ -2339,8 +2345,9 @@ Result VKDevice::initVulkanInstanceAndDevice(bool useValidationLayer)
applicationInfo.pApplicationName = "slang-render-test";
applicationInfo.pEngineName = "slang-render-test";
applicationInfo.apiVersion = VK_API_VERSION_1_0;
-
- char const* instanceExtensions[] =
+ applicationInfo.engineVersion = 1;
+ applicationInfo.applicationVersion = 1;
+ const char* instanceExtensions[] =
{
VK_KHR_SURFACE_EXTENSION_NAME,
@@ -2348,8 +2355,8 @@ Result VKDevice::initVulkanInstanceAndDevice(bool useValidationLayer)
#if SLANG_WINDOWS_FAMILY
VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
-#else
- VK_KHR_XLIB_SURFACE_EXTENSION_NAME
+#elif defined(SLANG_ENABLE_XLIB)
+ VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
#endif
#if ENABLE_VALIDATION_LAYER
@@ -2361,7 +2368,6 @@ Result VKDevice::initVulkanInstanceAndDevice(bool useValidationLayer)
VkInstanceCreateInfo instanceCreateInfo = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
instanceCreateInfo.pApplicationInfo = &applicationInfo;
-
instanceCreateInfo.enabledExtensionCount = SLANG_COUNT_OF(instanceExtensions);
instanceCreateInfo.ppEnabledExtensionNames = &instanceExtensions[0];
@@ -2414,9 +2420,7 @@ Result VKDevice::initVulkanInstanceAndDevice(bool useValidationLayer)
instanceCreateInfo.ppEnabledLayerNames = layerNames;
}
}
-
- if (m_api.vkCreateInstance(&instanceCreateInfo, nullptr, &instance) != VK_SUCCESS)
- return SLANG_FAIL;
+ SLANG_RETURN_ON_FAIL(m_api.vkCreateInstance(&instanceCreateInfo, nullptr, &instance));
SLANG_RETURN_ON_FAIL(m_api.initInstanceProcs(instance));
if (useValidationLayer)
@@ -2673,6 +2677,13 @@ Result VKDevice::createCommandQueue(const ICommandQueue::Desc& desc, ICommandQue
Result VKDevice::createSwapchain(
const ISwapchain::Desc& desc, WindowHandle window, ISwapchain** outSwapchain)
{
+#if !defined(SLANG_ENABLE_XLIB)
+ if (window.type == WindowHandle::Type::XLibHandle)
+ {
+ return SLANG_FAIL;
+ }
+#endif
+
RefPtr<SwapchainImpl> sc = new SwapchainImpl();
SLANG_RETURN_ON_FAIL(sc->init(this, desc, window));
*outSwapchain = sc.detach();
diff --git a/tools/platform/gui.cpp b/tools/platform/gui.cpp
index 5c210f460..f2f9561d5 100644
--- a/tools/platform/gui.cpp
+++ b/tools/platform/gui.cpp
@@ -34,7 +34,6 @@ LRESULT CALLBACK guiWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam
return handled;
}
-void setNativeWindowHook(Window* window, WNDPROC proc);
#endif
@@ -51,8 +50,6 @@ GUI::GUI(
#ifdef _WIN32
ImGui_ImplWin32_Init((HWND)window->getNativeHandle().handleValues[0]);
-
- setNativeWindowHook(window, &guiWindowProc);
#endif
// Let's do the initialization work required for our graphics API
diff --git a/tools/platform/linux/x11-key-code.cpp b/tools/platform/linux/x11-key-code.cpp
new file mode 100644
index 000000000..ce4e8945c
--- /dev/null
+++ b/tools/platform/linux/x11-key-code.cpp
@@ -0,0 +1,247 @@
+#if defined(SLANG_ENABLE_XLIB)
+
+#include "core/slang-basic.h"
+#include "../window.h"
+#include <X11/keysym.h>
+#include <X11/Xlib.h>
+
+#ifdef None
+#undef None
+#endif
+
+// Translates X11 key code values to Win32 Virtual Key values
+
+using namespace Slang;
+
+namespace platform
+{
+ Dictionary<int, KeyCode> keyCodeMap;
+
+ struct Win32KeyCode
+ {
+ KeyCode vKeyCode;
+ int keySym;
+ };
+
+ Win32KeyCode keys[] =
+ {
+ {KeyCode::Left, XK_Left},
+ {KeyCode::Up, XK_Up},
+ {KeyCode::Down, XK_Down},
+ {KeyCode::Right, XK_Right},
+ {KeyCode::Escape, XK_Escape},
+ {KeyCode::Return, XK_Return},
+ {KeyCode::Space, XK_space},
+ {KeyCode::Shift, XK_Shift_L},
+ {KeyCode::Shift, XK_Shift_R},
+ {KeyCode::Ctrl, XK_Control_L},
+ {KeyCode::Ctrl, XK_Control_R},
+ {KeyCode::Alt, XK_Alt_L},
+ {KeyCode::Alt, XK_Alt_R},
+ {KeyCode::Backspace, XK_BackSpace},
+ {KeyCode::Delete, XK_Delete},
+ {KeyCode::Home, XK_Home},
+ {KeyCode::End, XK_End},
+ {KeyCode::PageUp, XK_Page_Up},
+ {KeyCode::PageDown, XK_Page_Down},
+ {KeyCode::Insert, XK_Insert},
+ {KeyCode::Tab, XK_Tab},
+ {KeyCode::A, 0x41},
+ {KeyCode::B, 0x42},
+ {KeyCode::C, 0x43},
+ {KeyCode::D, 0x44},
+ {KeyCode::E, 0x45},
+ {KeyCode::F, 0x46},
+ {KeyCode::G, 0x47},
+ {KeyCode::H, 0x48},
+ {KeyCode::I, 0x49},
+ {KeyCode::J, 0x4A},
+ {KeyCode::K, 0x4B},
+ {KeyCode::L, 0x4C},
+ {KeyCode::M, 0x4D},
+ {KeyCode::N, 0x4E},
+ {KeyCode::O, 0x4F},
+ {KeyCode::P, 0x50},
+ {KeyCode::Q, 0x51},
+ {KeyCode::R, 0x52},
+ {KeyCode::S, 0x53},
+ {KeyCode::T, 0x54},
+ {KeyCode::U, 0x55},
+ {KeyCode::V, 0x56},
+ {KeyCode::W, 0x57},
+ {KeyCode::X, 0x58},
+ {KeyCode::Y, 0x59},
+ {KeyCode::Z, 0x5A},
+ {KeyCode::Semicolon, XK_semicolon},
+ {KeyCode::Comma, XK_comma},
+ {KeyCode::Dot, XK_period},
+ {KeyCode::Slash, XK_slash},
+ {KeyCode::Quote, XK_apostrophe},
+ {KeyCode::LBracket, XK_bracketleft},
+ {KeyCode::RBracket, XK_bracketright},
+ {KeyCode::Backslash, XK_backslash},
+ {KeyCode::Minus, XK_minus},
+ {KeyCode::Plus, XK_equal},
+ {KeyCode::Tilde, XK_asciitilde},
+ {KeyCode::Key0, 0x30},
+ {KeyCode::Key1, 0x31},
+ {KeyCode::Key2, 0x32},
+ {KeyCode::Key3, 0x33},
+ {KeyCode::Key4, 0x34},
+ {KeyCode::Key5, 0x35},
+ {KeyCode::Key6, 0x36},
+ {KeyCode::Key7, 0x37},
+ {KeyCode::Key8, 0x38},
+ {KeyCode::Key9, 0x39},
+ {KeyCode::F1, XK_F1},
+ {KeyCode::F2, XK_F2},
+ {KeyCode::F3, XK_F3},
+ {KeyCode::F4, XK_F4},
+ {KeyCode::F5, XK_F5},
+ {KeyCode::F6, XK_F6},
+ {KeyCode::F7, XK_F7},
+ {KeyCode::F8, XK_F8},
+ {KeyCode::F9, XK_F9},
+ {KeyCode::F10, XK_F10},
+ {KeyCode::F11, XK_F11},
+ {KeyCode::F12, XK_F12}
+ };
+
+ void initKeyCodeTranslationTable(Display* display)
+ {
+ for (auto entry : keys)
+ {
+ auto systemKeyCode = XKeysymToKeycode(display, entry.keySym);
+ keyCodeMap[systemKeyCode] = entry.vKeyCode;
+ }
+ }
+
+ void freeKeyCodeTranslationTable()
+ {
+ keyCodeMap = decltype(keyCodeMap)();
+ }
+
+ KeyCode translateKeyCode(int keyCode)
+ {
+ KeyCode result = KeyCode::None;
+ keyCodeMap.TryGetValue(keyCode, result);
+ return result;
+ }
+
+ int getKeyChar(KeyCode keyCode, int keyState)
+ {
+ bool shift = (keyState & ShiftMask) != 0;
+ if (keyCode >= KeyCode::A && keyCode <= KeyCode::Z )
+ {
+ bool capslock = (keyState & LockMask) != 0;
+ bool isCapital = capslock ^ shift;
+ if (isCapital)
+ return (int)keyCode;
+ else
+ return (int)keyCode + ('a'-'A');
+ }
+ else if (keyCode == KeyCode::Space)
+ {
+ return ' ';
+ }
+ else if (keyCode == KeyCode::Return)
+ {
+ return (int)keyCode;
+ }
+ else if (keyCode >= KeyCode::Key0 && keyCode <= KeyCode::Key9)
+ {
+ if (!shift)
+ return (int)keyCode;
+ else
+ {
+ switch (keyCode)
+ {
+ case KeyCode::Key0:
+ return ')';
+ case KeyCode::Key1:
+ return '!';
+ case KeyCode::Key2:
+ return '@';
+ case KeyCode::Key3:
+ return '#';
+ case KeyCode::Key4:
+ return '$';
+ case KeyCode::Key5:
+ return '%';
+ case KeyCode::Key6:
+ return '^';
+ case KeyCode::Key7:
+ return '&';
+ case KeyCode::Key8:
+ return '*';
+ case KeyCode::Key9:
+ return '(';
+ default:
+ return 0;
+ }
+ }
+ }
+ if (shift)
+ {
+ switch (keyCode)
+ {
+ case KeyCode::Semicolon:
+ return ':';
+ case KeyCode::Comma:
+ return '<';
+ case KeyCode::Dot:
+ return '>';
+ case KeyCode::Slash:
+ return '?';
+ case KeyCode::Quote:
+ return '\"';
+ case KeyCode::LBracket:
+ return '{';
+ case KeyCode::RBracket:
+ return '}';
+ case KeyCode::Backslash:
+ return '|';
+ case KeyCode::Minus:
+ return '_';
+ case KeyCode::Plus:
+ return '+';
+ case KeyCode::Tilde:
+ return '~';
+ default:
+ return 0;
+ }
+ }
+ else
+ {
+ switch (keyCode)
+ {
+ case KeyCode::Semicolon:
+ return ';';
+ case KeyCode::Comma:
+ return ',';
+ case KeyCode::Dot:
+ return '.';
+ case KeyCode::Slash:
+ return '/';
+ case KeyCode::Quote:
+ return '\'';
+ case KeyCode::LBracket:
+ return '[';
+ case KeyCode::RBracket:
+ return ']';
+ case KeyCode::Backslash:
+ return '\\';
+ case KeyCode::Minus:
+ return '-';
+ case KeyCode::Plus:
+ return '=';
+ case KeyCode::Tilde:
+ return '`';
+ default:
+ return 0;
+ }
+ }
+ }
+} // namespace platform
+
+#endif
diff --git a/tools/platform/linux/x11-window.cpp b/tools/platform/linux/x11-window.cpp
new file mode 100644
index 000000000..2721c00f3
--- /dev/null
+++ b/tools/platform/linux/x11-window.cpp
@@ -0,0 +1,474 @@
+#ifdef SLANG_ENABLE_XLIB
+
+#include "../window.h"
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xresource.h>
+
+#ifdef None
+#undef None
+#endif
+
+#include "core/slang-basic.h"
+
+using namespace Slang;
+
+namespace platform
+{
+typedef ::Window X11WindowHandle;
+class X11PlatformWindow;
+
+void initKeyCodeTranslationTable(Display *display);
+void freeKeyCodeTranslationTable();
+KeyCode translateKeyCode(int keyCode);
+int getKeyChar(KeyCode keyCode, int keyState);
+
+const int kKeyStateTableSize = 256;
+
+enum class KeyState
+{
+ Released,
+ Pressed,
+ Hold
+};
+
+enum class KeyEvent
+{
+ Press, Release
+};
+
+enum class MouseEvent
+{
+ Move, Down, Up, Scroll
+};
+
+class X11AppContext
+{
+public:
+ static bool isTerminated;
+ static RefPtr<Window> mainWindow;
+ static OrderedDictionary<X11WindowHandle, X11PlatformWindow*> windows;
+ static X11WindowHandle mainWindowHandle;
+ static Display* xdisplay;
+ static KeyState keyStates[kKeyStateTableSize];
+ static X11PlatformWindow *currentMouseEventWindow;
+};
+
+bool X11AppContext::isTerminated = false;
+RefPtr<Window> X11AppContext::mainWindow;
+OrderedDictionary<X11WindowHandle, X11PlatformWindow*> X11AppContext::windows;
+X11WindowHandle X11AppContext::mainWindowHandle;
+Display* X11AppContext::xdisplay = nullptr;
+KeyState X11AppContext::keyStates[kKeyStateTableSize] = {};
+X11PlatformWindow* X11AppContext::currentMouseEventWindow = nullptr;
+
+void Application::init()
+{
+
+}
+
+static void doEventsImpl(bool waitForEvents);
+
+void Application::doEvents() { doEventsImpl(false); }
+
+void Application::quit() { X11AppContext::isTerminated = true; }
+
+void Application::dispose()
+{
+ X11AppContext::mainWindow = nullptr;
+ X11AppContext::windows = decltype(X11AppContext::windows)();
+ freeKeyCodeTranslationTable();
+}
+
+void Application::run(Window* mainWindow, bool waitForEvents)
+{
+ if (mainWindow)
+ {
+ X11AppContext::mainWindow = mainWindow;
+ X11AppContext::mainWindowHandle = (X11WindowHandle)mainWindow->getNativeHandle().handleValues[1];
+ mainWindow->show();
+ while (!X11AppContext::isTerminated)
+ {
+ doEventsImpl(waitForEvents);
+ if (!X11AppContext::isTerminated)
+ mainWindow->events.mainLoop();
+ }
+ }
+}
+
+class X11PlatformWindow : public Window
+{
+public:
+ X11WindowHandle handle;
+ bool visible = false;
+ int currentWidth = 0;
+ int currentHeight = 0;
+ bool fixedSized = false;
+ X11PlatformWindow(const WindowDesc &desc)
+ {
+ currentWidth = desc.width;
+ currentHeight = desc.height;
+
+ int blackColor = BlackPixel(X11AppContext::xdisplay, DefaultScreen(X11AppContext::xdisplay));
+ int whiteColor = WhitePixel(X11AppContext::xdisplay, DefaultScreen(X11AppContext::xdisplay));
+ handle = XCreateSimpleWindow(X11AppContext::xdisplay, DefaultRootWindow(X11AppContext::xdisplay), 0, 0,
+ desc.width, desc.height, 0, blackColor, blackColor);
+ X11AppContext::windows[handle] = this;
+ Atom wmDelete = XInternAtom(X11AppContext::xdisplay, "WM_DELETE_WINDOW", True);
+ XSetWMProtocols(X11AppContext::xdisplay, handle, &wmDelete, 1);
+ XSelectInput(X11AppContext::xdisplay, handle, StructureNotifyMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
+ ButtonPressMask | ButtonReleaseMask | ExposureMask | FocusChangeMask);
+
+ if (desc.style == WindowStyle::FixedSize)
+ {
+ fixedSized = true;
+ setFixedSizeHint(desc.width, desc.height);
+ }
+ setText(desc.title);
+ }
+
+ ~X11PlatformWindow()
+ {
+ close();
+ }
+
+ void setFixedSizeHint(int w, int h)
+ {
+ auto sizeHints = XAllocSizeHints();
+ sizeHints->flags = PMinSize | PMaxSize;
+ sizeHints->min_width = sizeHints->max_width = w;
+ sizeHints->min_height = sizeHints->max_height = h;
+ XSetWMNormalHints(X11AppContext::xdisplay, handle, sizeHints);
+ XFree(sizeHints);
+ }
+
+ virtual void setClientSize(uint32_t width, uint32_t height) override
+ {
+ if (fixedSized)
+ setFixedSizeHint(width, height);
+ XResizeWindow(X11AppContext::xdisplay, handle, width, height);
+ handleResizeEvent(width, height);
+ }
+
+ virtual Rect getClientRect() override
+ {
+ Rect rect = {};
+ if (!handle)
+ return rect;
+ X11WindowHandle winRoot = 0, winParent = 0;
+ X11WindowHandle* winChildren = nullptr;
+ unsigned int numChilren = 0;
+ XQueryTree(X11AppContext::xdisplay, handle, &winRoot, &winParent, &winChildren, &numChilren);
+ unsigned borderWidth, depth;
+ XGetGeometry(X11AppContext::xdisplay, handle, &winRoot, &rect.x, &rect.y, (uint32_t*)&rect.width, (uint32_t*)&rect.height, &borderWidth, &depth);
+ return rect;
+ }
+
+ virtual void centerScreen() override
+ {
+ auto currentRect = getClientRect();
+ XWindowAttributes attributes;
+ XGetWindowAttributes(X11AppContext::xdisplay, handle, &attributes);
+ int screenWidth = WidthOfScreen(attributes.screen);
+ int screenHeight = HeightOfScreen(attributes.screen);
+ int x = (screenWidth - currentRect.width) / 2;
+ int y = (screenHeight - currentRect.height) / 2;
+ XMoveWindow(X11AppContext::xdisplay, handle, x, y);
+ }
+ virtual void close() override
+ {
+ if (handle)
+ {
+ X11AppContext::windows.Remove(handle);
+ XDestroyWindow(X11AppContext::xdisplay, handle);
+ handle = 0;
+ }
+ }
+ virtual bool getFocused() override
+ {
+ if (!handle) return false;
+ int revertTo;
+ X11WindowHandle focusedWindow;
+ XGetInputFocus(X11AppContext::xdisplay, &focusedWindow, &revertTo);
+ return focusedWindow == handle;
+ }
+ virtual WindowHandle getNativeHandle() override
+ {
+ WindowHandle rs;
+ rs.type = WindowHandle::Type::XLibHandle;
+ rs.handleValues[0] = (intptr_t)X11AppContext::xdisplay;
+ rs.handleValues[1] = (intptr_t)handle;
+ return rs;
+ }
+ virtual void setText(String text) override
+ {
+ if (!handle) return;
+ XStoreName(X11AppContext::xdisplay, handle, text.getBuffer());
+ XClassHint* hint = XAllocClassHint();
+ hint->res_class = (char *)"Slang platform window";
+ hint->res_name = (char *)"Slang platform window";
+ XSetClassHint(X11AppContext::xdisplay, handle, hint);
+ XFree(hint);
+ }
+ virtual bool getVisible() override
+ {
+ return visible;
+ }
+ virtual void show() override
+ {
+ XMapWindow(X11AppContext::xdisplay, handle);
+ visible = true;
+ }
+ virtual void hide() override
+ {
+ if (!handle) return;
+ XUnmapWindow(X11AppContext::xdisplay, handle);
+ visible = false;
+ }
+ virtual int getCurrentDpi() override
+ {
+ char *resourceString = XResourceManagerString(X11AppContext::xdisplay);
+ XrmDatabase db;
+ XrmValue value;
+ char *type = NULL;
+ double dpi = 96.0;
+ db = XrmGetStringDatabase(resourceString);
+ if (resourceString)
+ {
+ if (XrmGetResource(db, "Xft.dpi", "String", &type, &value))
+ {
+ if (value.addr)
+ {
+ dpi = atof(value.addr);
+ }
+ }
+ }
+ return (int)dpi;
+ }
+ void handleResizeEvent(int w, int h)
+ {
+ if (w != currentWidth || h != currentHeight)
+ {
+ currentWidth = w;
+ currentHeight = h;
+ events.sizeChanged();
+ }
+ }
+
+ static void addButtonState(ButtonState::Enum& state, ButtonState::Enum newState)
+ {
+ state = ButtonState::Enum((int)state | (int)newState);
+ }
+
+ ButtonState::Enum getButtonState(int state)
+ {
+ ButtonState::Enum buttonState = ButtonState::Enum::None;
+ if (state & ShiftMask) addButtonState(buttonState, ButtonState::Enum::Shift);
+ if (state & ControlMask) addButtonState(buttonState, ButtonState::Enum::Control);
+ if (state & Mod1Mask) addButtonState(buttonState, ButtonState::Enum::Alt);
+ if (state & Button1Mask) addButtonState(buttonState, ButtonState::Enum::LeftButton);
+ if (state & Button2Mask) addButtonState(buttonState, ButtonState::Enum::MiddleButton);
+ if (state & Button3Mask) addButtonState(buttonState, ButtonState::Enum::RightButton);
+ return buttonState;
+ }
+
+ void handleKeyEvent(KeyEvent eventType, KeyCode keyCode, int keyChar, int state)
+ {
+ KeyEventArgs e;
+ e.buttons = getButtonState(state);
+ e.cancelEvent = false;
+ e.key = keyCode;
+ e.keyChar = keyChar;
+ if (eventType == KeyEvent::Press)
+ {
+ events.keyDown(e);
+ if (keyChar)
+ events.keyPress(e);
+ }
+ else
+ {
+ events.keyUp(e);
+ }
+ }
+
+ void handleMouseEvent(MouseEvent eventType, int x, int y, int delta, int button, int state, unsigned long time)
+ {
+ auto buttonState = getButtonState(state);
+ if (button == Button1)
+ addButtonState(buttonState, ButtonState::Enum::LeftButton);
+ else if (button == Button2)
+ addButtonState(buttonState, ButtonState::Enum::MiddleButton);
+ else if (button == Button3)
+ addButtonState(buttonState, ButtonState::Enum::RightButton);
+ MouseEventArgs e;
+ e.buttons = buttonState;
+ e.delta = delta;
+ e.x = x;
+ e.y = y;
+
+ switch (eventType)
+ {
+ case MouseEvent::Down:
+ events.mouseDown(e);
+ break;
+ case MouseEvent::Up:
+ events.mouseUp(e);
+ break;
+ case MouseEvent::Move:
+ events.mouseMove(e);
+ break;
+ case MouseEvent::Scroll:
+ events.mouseWheel(e);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void handleCloseEvent()
+ {
+ hide();
+ if (X11AppContext::mainWindowHandle == handle)
+ Application::quit();
+ }
+
+ void handleExposeEvent()
+ {
+ }
+
+ void handleFocus(bool focus)
+ {
+ }
+
+};
+
+Window* Application::createWindow(const WindowDesc& desc)
+{
+ if (!X11AppContext::xdisplay)
+ {
+ XInitThreads();
+ XrmInitialize();
+ X11AppContext::xdisplay = XOpenDisplay(nullptr);
+ initKeyCodeTranslationTable(X11AppContext::xdisplay);
+ if (!X11AppContext::xdisplay)
+ printf("Failed to open XDisplay.\n");
+ }
+ return new X11PlatformWindow(desc);
+}
+
+void doEventsImpl(bool waitForEvents)
+{
+ auto xdisplay = X11AppContext::xdisplay;
+ if (!X11AppContext::xdisplay)
+ return;
+
+ static bool supressInvokeTasks = false;
+ X11PlatformWindow* sysWindow = nullptr;
+ KeyCode vKeyCode = KeyCode::None;
+ int iKeyCode = 0;
+ while (XPending(xdisplay))
+ {
+ XEvent nextEvent;
+ XNextEvent(xdisplay, &nextEvent);
+ switch (nextEvent.type)
+ {
+ case KeyPress:
+ vKeyCode = translateKeyCode(nextEvent.xkey.keycode);
+ iKeyCode = (int)vKeyCode;
+ if (iKeyCode < kKeyStateTableSize)
+ {
+ if (X11AppContext::keyStates[iKeyCode] == KeyState::Released)
+ X11AppContext::keyStates[iKeyCode] = KeyState::Pressed;
+ else if (X11AppContext::keyStates[iKeyCode] == KeyState::Pressed)
+ X11AppContext::keyStates[iKeyCode] = KeyState::Hold;
+ }
+ if (X11AppContext::windows.TryGetValue(nextEvent.xkey.window, sysWindow))
+ {
+ wchar_t keyChar = getKeyChar(vKeyCode, nextEvent.xkey.state);
+ sysWindow->handleKeyEvent(KeyEvent::Press, vKeyCode, keyChar, nextEvent.xkey.state);
+ }
+ break;
+ case KeyRelease:
+ vKeyCode = translateKeyCode(nextEvent.xkey.keycode);
+ iKeyCode = (int)vKeyCode;
+ if (iKeyCode < kKeyStateTableSize)
+ {
+ X11AppContext::keyStates[iKeyCode] = KeyState::Released;
+ }
+ if (X11AppContext::windows.TryGetValue(nextEvent.xkey.window, sysWindow))
+ {
+ sysWindow->handleKeyEvent(KeyEvent::Release, vKeyCode, 0, nextEvent.xkey.state);
+ }
+ break;
+ case MotionNotify:
+ if (X11AppContext::windows.TryGetValue(nextEvent.xmotion.window, sysWindow))
+ {
+ X11AppContext::currentMouseEventWindow = sysWindow;
+ sysWindow->handleMouseEvent(MouseEvent::Move, nextEvent.xmotion.x, nextEvent.xmotion.y, 0,
+ 0, nextEvent.xmotion.state, nextEvent.xmotion.time);
+ }
+ break;
+ case ButtonPress:
+ if (X11AppContext::windows.TryGetValue(nextEvent.xbutton.window, sysWindow))
+ {
+ X11AppContext::currentMouseEventWindow = sysWindow;
+ if (nextEvent.xbutton.button <= Button3)
+ sysWindow->handleMouseEvent(MouseEvent::Down, nextEvent.xbutton.x, nextEvent.xbutton.y, 0,
+ nextEvent.xbutton.button, nextEvent.xbutton.state, nextEvent.xbutton.time);
+ else if (nextEvent.xbutton.button == Button4)
+ sysWindow->handleMouseEvent(MouseEvent::Scroll, nextEvent.xbutton.x, nextEvent.xbutton.y, 120,
+ nextEvent.xbutton.button, nextEvent.xbutton.state, nextEvent.xbutton.time);
+ else if (nextEvent.xbutton.button == Button5)
+ sysWindow->handleMouseEvent(MouseEvent::Scroll, nextEvent.xbutton.x, nextEvent.xbutton.y, -120,
+ nextEvent.xbutton.button, nextEvent.xbutton.state, nextEvent.xbutton.time);
+ }
+ break;
+ case ButtonRelease:
+ if (X11AppContext::windows.TryGetValue(nextEvent.xbutton.window, sysWindow))
+ {
+ X11AppContext::currentMouseEventWindow = sysWindow;
+ sysWindow->handleMouseEvent(MouseEvent::Up, nextEvent.xbutton.x, nextEvent.xbutton.y, 0,
+ nextEvent.xbutton.button, nextEvent.xbutton.state, nextEvent.xbutton.time);
+ }
+ break;
+ case ConfigureNotify:
+ if (X11AppContext::windows.TryGetValue(nextEvent.xconfigure.window, sysWindow))
+ {
+ sysWindow->handleResizeEvent(nextEvent.xconfigure.width, nextEvent.xconfigure.height);
+ }
+ break;
+ case Expose:
+ if (X11AppContext::windows.TryGetValue(nextEvent.xexpose.window, sysWindow))
+ {
+ sysWindow->handleExposeEvent();
+ }
+ break;
+ case ClientMessage:
+ if (X11AppContext::windows.TryGetValue(nextEvent.xclient.window, sysWindow))
+ {
+ Atom wmDelete = XInternAtom(X11AppContext::xdisplay, "WM_DELETE_WINDOW", True);
+ if (nextEvent.xclient.data.l[0] == wmDelete)
+ {
+ sysWindow->handleCloseEvent();
+ }
+ }
+ break;
+ case FocusIn:
+ if (X11AppContext::windows.TryGetValue(nextEvent.xfocus.window, sysWindow))
+ {
+ sysWindow->handleFocus(true);
+ }
+ break;
+ case FocusOut:
+ if (X11AppContext::windows.TryGetValue(nextEvent.xfocus.window, sysWindow))
+ {
+ sysWindow->handleFocus(false);
+ }
+ break;
+ }
+ }
+}
+
+}
+
+#endif
diff --git a/tools/platform/placeholder/placeholder-window.cpp b/tools/platform/placeholder/placeholder-window.cpp
new file mode 100644
index 000000000..a94287d55
--- /dev/null
+++ b/tools/platform/placeholder/placeholder-window.cpp
@@ -0,0 +1,33 @@
+#if !defined(_WIN32) && !defined(SLANG_ENABLE_XLIB)
+
+#include "../window.h"
+
+using namespace Slang;
+
+namespace platform
+{
+
+void Application::init()
+{
+}
+
+void Application::doEvents() { }
+
+void Application::quit() { }
+
+void Application::dispose()
+{
+}
+
+void Application::run(Window* mainWindow, bool waitForEvents)
+{
+ SLANG_UNUSED(mainWindow);
+ SLANG_UNUSED(waitForEvents);
+}
+
+Window* Application::createWindow(const WindowDesc& desc) { return nullptr; }
+
+
+} // namespace platform
+
+#endif
diff --git a/tools/platform/window.h b/tools/platform/window.h
index e4a867f0b..884f28b0d 100644
--- a/tools/platform/window.h
+++ b/tools/platform/window.h
@@ -5,6 +5,25 @@
#include "source/core/slang-basic.h"
#include "source/core/slang-func-ptr.h"
+#if defined(SLANG_PLATFORM_DYNAMIC)
+# if defined(_MSC_VER)
+# ifdef SLANG_PLATFORM_DYNAMIC_EXPORT
+# define SLANG_PLATFORM_API SLANG_DLL_EXPORT
+# else
+# define SLANG_PLATFORM_API __declspec(dllimport)
+# endif
+# else
+// TODO: need to consider compiler capabilities
+//# ifdef SLANG_DYNAMIC_EXPORT
+# define SLANG_PLATFORM_API SLANG_DLL_EXPORT
+//# endif
+# endif
+#endif
+
+#ifndef SLANG_PLATFORM_API
+# define SLANG_PLATFORM_API
+#endif
+
namespace platform {
enum class KeyCode : uint32_t
@@ -99,14 +118,14 @@ struct WindowHandle
};
Type type;
intptr_t handleValues[2];
- static WindowHandle FromHwnd(void* hwnd)
+ static WindowHandle fromHwnd(void* hwnd)
{
WindowHandle handle = {};
handle.type = WindowHandle::Type::Win32Handle;
handle.handleValues[0] = (intptr_t)(hwnd);
return handle;
}
- static WindowHandle FromXWindow(void* xdisplay, uint32_t xwindow)
+ static WindowHandle fromXWindow(void* xdisplay, uint32_t xwindow)
{
WindowHandle handle = {};
handle.type = WindowHandle::Type::XLibHandle;
@@ -114,6 +133,15 @@ struct WindowHandle
handle.handleValues[1] = xwindow;
return handle;
}
+ template<typename T>
+ T convert()
+ {
+ T result;
+ result.type = (decltype(result.type))type;
+ result.handleValues[0] = handleValues[0];
+ result.handleValues[1] = handleValues[1];
+ return result;
+ }
};
struct ButtonState
@@ -174,6 +202,7 @@ public:
Slang::Action<MouseEventArgs> mouseMove;
Slang::Action<MouseEventArgs> mouseUp;
Slang::Action<MouseEventArgs> mouseDown;
+ Slang::Action<MouseEventArgs> mouseWheel;
};
Events events;
@@ -194,12 +223,12 @@ public:
class Application
{
public:
- static Window* createWindow(const WindowDesc& desc);
- static void init();
- static void run(Window* mainWindow, bool waitForEvents = false);
- static void quit();
- static void doEvents();
- static void dispose();
+ static SLANG_PLATFORM_API Window* createWindow(const WindowDesc& desc);
+ static SLANG_PLATFORM_API void init();
+ static SLANG_PLATFORM_API void run(Window* mainWindow, bool waitForEvents = false);
+ static SLANG_PLATFORM_API void quit();
+ static SLANG_PLATFORM_API void doEvents();
+ static SLANG_PLATFORM_API void dispose();
};
} // namespace platform
@@ -230,12 +259,13 @@ public:
#else
-# define PLATFORM_UI_MAIN(APPLICATION_ENTRY) \
- int main() \
- { \
- platform::Application::init(); \
- auto rs - APPLICATION_ENTRY(); \
- platform::Application::dispose(); \
- }
+#define PLATFORM_UI_MAIN(APPLICATION_ENTRY) \
+ int main() \
+ { \
+ platform::Application::init(); \
+ auto rs = APPLICATION_ENTRY(); \
+ platform::Application::dispose(); \
+ return rs; \
+ }
#endif
diff --git a/tools/platform/windows/win-window.cpp b/tools/platform/windows/win-window.cpp
index 8822a6393..0d80eda7b 100644
--- a/tools/platform/windows/win-window.cpp
+++ b/tools/platform/windows/win-window.cpp
@@ -406,7 +406,7 @@ public:
virtual bool getVisible() override { return visible; }
virtual WindowHandle getNativeHandle() override
{
- return WindowHandle::FromHwnd(handle);
+ return WindowHandle::fromHwnd(handle);
}
virtual void setText(Slang::String text) override
{