diff options
| author | Yong He <yonghe@outlook.com> | 2021-03-08 10:01:20 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-03-08 10:01:20 -0800 |
| commit | fc9968dc4fd58fab37476f48e4405c2743c5349c (patch) | |
| tree | 6119b293a5a5cc24401dde5ff54287beb28fe63b | |
| parent | 95ca93938f5d45f4eaf340867965bd77a1724d6c (diff) | |
Refactor window library. (#1739)
* Refactor window library.
* Fix project file
* Fix warnings.
27 files changed, 1235 insertions, 696 deletions
diff --git a/build/visual-studio/core/core.vcxproj b/build/visual-studio/core/core.vcxproj index 01a7e3eb2..38bcf2ade 100644 --- a/build/visual-studio/core/core.vcxproj +++ b/build/visual-studio/core/core.vcxproj @@ -185,6 +185,7 @@ <ClInclude Include="..\..\..\source\core\slang-downstream-compiler.h" /> <ClInclude Include="..\..\..\source\core\slang-exception.h" /> <ClInclude Include="..\..\..\source\core\slang-free-list.h" /> + <ClInclude Include="..\..\..\source\core\slang-func-ptr.h" /> <ClInclude Include="..\..\..\source\core\slang-gcc-compiler-util.h" /> <ClInclude Include="..\..\..\source\core\slang-hash.h" /> <ClInclude Include="..\..\..\source\core\slang-hex-dump-util.h" /> diff --git a/build/visual-studio/core/core.vcxproj.filters b/build/visual-studio/core/core.vcxproj.filters index 3c2a7371d..9c718a6fb 100644 --- a/build/visual-studio/core/core.vcxproj.filters +++ b/build/visual-studio/core/core.vcxproj.filters @@ -54,6 +54,9 @@ <ClInclude Include="..\..\..\source\core\slang-free-list.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\..\..\source\core\slang-func-ptr.h"> + <Filter>Header Files</Filter> + </ClInclude> <ClInclude Include="..\..\..\source\core\slang-gcc-compiler-util.h"> <Filter>Header Files</Filter> </ClInclude> diff --git a/build/visual-studio/cpu-hello-world/cpu-hello-world.vcxproj b/build/visual-studio/cpu-hello-world/cpu-hello-world.vcxproj index 2fb93b42c..0ba5973d0 100644 --- a/build/visual-studio/cpu-hello-world/cpu-hello-world.vcxproj +++ b/build/visual-studio/cpu-hello-world/cpu-hello-world.vcxproj @@ -180,7 +180,7 @@ <ProjectReference Include="..\gfx-util\gfx-util.vcxproj"> <Project>{F5ADB74E-02A7-44FB-AA3B-FC02F8AC7A4B}</Project> </ProjectReference> - <ProjectReference Include="..\graphics-app-framework\graphics-app-framework.vcxproj"> + <ProjectReference Include="..\platform\platform.vcxproj"> <Project>{3565FE5E-4FA3-11EB-AE93-0242AC130002}</Project> </ProjectReference> </ItemGroup> diff --git a/build/visual-studio/gpu-printing/gpu-printing.vcxproj b/build/visual-studio/gpu-printing/gpu-printing.vcxproj index f7b783f39..b55e289d1 100644 --- a/build/visual-studio/gpu-printing/gpu-printing.vcxproj +++ b/build/visual-studio/gpu-printing/gpu-printing.vcxproj @@ -186,7 +186,7 @@ <ProjectReference Include="..\gfx-util\gfx-util.vcxproj"> <Project>{F5ADB74E-02A7-44FB-AA3B-FC02F8AC7A4B}</Project> </ProjectReference> - <ProjectReference Include="..\graphics-app-framework\graphics-app-framework.vcxproj"> + <ProjectReference Include="..\platform\platform.vcxproj"> <Project>{3565FE5E-4FA3-11EB-AE93-0242AC130002}</Project> </ProjectReference> </ItemGroup> diff --git a/build/visual-studio/hello-world/hello-world.vcxproj b/build/visual-studio/hello-world/hello-world.vcxproj index a7a51362b..28f8d1425 100644 --- a/build/visual-studio/hello-world/hello-world.vcxproj +++ b/build/visual-studio/hello-world/hello-world.vcxproj @@ -180,7 +180,7 @@ <ProjectReference Include="..\gfx-util\gfx-util.vcxproj"> <Project>{F5ADB74E-02A7-44FB-AA3B-FC02F8AC7A4B}</Project> </ProjectReference> - <ProjectReference Include="..\graphics-app-framework\graphics-app-framework.vcxproj"> + <ProjectReference Include="..\platform\platform.vcxproj"> <Project>{3565FE5E-4FA3-11EB-AE93-0242AC130002}</Project> </ProjectReference> </ItemGroup> diff --git a/build/visual-studio/platform/platform.vcxproj b/build/visual-studio/platform/platform.vcxproj new file mode 100644 index 000000000..518ac20f7 --- /dev/null +++ b/build/visual-studio/platform/platform.vcxproj @@ -0,0 +1,176 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{3565FE5E-4FA3-11EB-AE93-0242AC130002}</ProjectGuid> + <IgnoreWarnCompileDuplicatedFilename>true</IgnoreWarnCompileDuplicatedFilename> + <Keyword>Win32Proj</Keyword> + <RootNamespace>platform</RootNamespace> + <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <OutDir>..\..\..\bin\windows-x86\debug\</OutDir> + <IntDir>..\..\..\intermediate\windows-x86\debug\platform\</IntDir> + <TargetName>platform</TargetName> + <TargetExt>.lib</TargetExt> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <OutDir>..\..\..\bin\windows-x64\debug\</OutDir> + <IntDir>..\..\..\intermediate\windows-x64\debug\platform\</IntDir> + <TargetName>platform</TargetName> + <TargetExt>.lib</TargetExt> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <OutDir>..\..\..\bin\windows-x86\release\</OutDir> + <IntDir>..\..\..\intermediate\windows-x86\release\platform\</IntDir> + <TargetName>platform</TargetName> + <TargetExt>.lib</TargetExt> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <OutDir>..\..\..\bin\windows-x64\release\</OutDir> + <IntDir>..\..\..\intermediate\windows-x64\release\platform\</IntDir> + <TargetName>platform</TargetName> + <TargetExt>.lib</TargetExt> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\external\imgui;..\..\..\tools\gfx;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <Optimization>Disabled</Optimization> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\external\imgui;..\..\..\tools\gfx;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <DebugInformationFormat>EditAndContinue</DebugInformationFormat> + <Optimization>Disabled</Optimization> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\external\imgui;..\..\..\tools\gfx;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <Optimization>Full</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <MinimalRebuild>false</MinimalRebuild> + <StringPooling>true</StringPooling> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\external\imgui;..\..\..\tools\gfx;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <Optimization>Full</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <MinimalRebuild>false</MinimalRebuild> + <StringPooling>true</StringPooling> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Windows</SubSystem> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="..\..\..\tools\platform\gui.h" /> + <ClInclude Include="..\..\..\tools\platform\model.h" /> + <ClInclude Include="..\..\..\tools\platform\performance-counter.h" /> + <ClInclude Include="..\..\..\tools\platform\vector-math.h" /> + <ClInclude Include="..\..\..\tools\platform\window.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\..\..\tools\platform\gui.cpp" /> + <ClCompile Include="..\..\..\tools\platform\model.cpp" /> + <ClCompile Include="..\..\..\tools\platform\windows\win-window.cpp" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/build/visual-studio/platform/platform.vcxproj.filters b/build/visual-studio/platform/platform.vcxproj.filters new file mode 100644 index 000000000..17d756451 --- /dev/null +++ b/build/visual-studio/platform/platform.vcxproj.filters @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Header Files"> + <UniqueIdentifier>{21EB8090-0D4E-1035-B6D3-48EBA215DCB7}</UniqueIdentifier> + </Filter> + <Filter Include="Source Files"> + <UniqueIdentifier>{E9C7FDCE-D52A-8D73-7EB0-C5296AF258F6}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\..\..\tools\platform\gui.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\..\..\tools\platform\model.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\..\..\tools\platform\performance-counter.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\..\..\tools\platform\vector-math.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\..\..\tools\platform\window.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\..\..\tools\platform\gui.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\..\tools\platform\model.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\..\tools\platform\windows\win-window.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/build/visual-studio/render-test-tool/render-test-tool.vcxproj b/build/visual-studio/render-test-tool/render-test-tool.vcxproj index 0ce5b5361..8cca49a83 100644 --- a/build/visual-studio/render-test-tool/render-test-tool.vcxproj +++ b/build/visual-studio/render-test-tool/render-test-tool.vcxproj @@ -99,7 +99,7 @@ <PrecompiledHeader>NotUsing</PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>_DEBUG;SLANG_SHARED_LIBRARY_TOOL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\tools\gfx;..\..\..\tools\graphics-app-framework;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\tools\gfx;..\..\..\tools\platform;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> <Optimization>Disabled</Optimization> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> @@ -118,7 +118,7 @@ <PrecompiledHeader>NotUsing</PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>_DEBUG;SLANG_SHARED_LIBRARY_TOOL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\tools\gfx;..\..\..\tools\graphics-app-framework;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\tools\gfx;..\..\..\tools\platform;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <DebugInformationFormat>EditAndContinue</DebugInformationFormat> <Optimization>Disabled</Optimization> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> @@ -137,7 +137,7 @@ <PrecompiledHeader>NotUsing</PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>NDEBUG;SLANG_SHARED_LIBRARY_TOOL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\tools\gfx;..\..\..\tools\graphics-app-framework;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\tools\gfx;..\..\..\tools\platform;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <Optimization>Full</Optimization> <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> @@ -160,7 +160,7 @@ <PrecompiledHeader>NotUsing</PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>NDEBUG;SLANG_SHARED_LIBRARY_TOOL;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\tools\gfx;..\..\..\tools\graphics-app-framework;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories>..\..\..;..\..\..\external;..\..\..\source;..\..\..\tools\gfx;..\..\..\tools\platform;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <Optimization>Full</Optimization> <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> @@ -210,7 +210,7 @@ <ProjectReference Include="..\gfx-util\gfx-util.vcxproj"> <Project>{F5ADB74E-02A7-44FB-AA3B-FC02F8AC7A4B}</Project> </ProjectReference> - <ProjectReference Include="..\graphics-app-framework\graphics-app-framework.vcxproj"> + <ProjectReference Include="..\platform\platform.vcxproj"> <Project>{3565FE5E-4FA3-11EB-AE93-0242AC130002}</Project> </ProjectReference> </ItemGroup> diff --git a/build/visual-studio/shader-object/shader-object.vcxproj b/build/visual-studio/shader-object/shader-object.vcxproj index 1af67af5b..04315f910 100644 --- a/build/visual-studio/shader-object/shader-object.vcxproj +++ b/build/visual-studio/shader-object/shader-object.vcxproj @@ -180,7 +180,7 @@ <ProjectReference Include="..\gfx-util\gfx-util.vcxproj"> <Project>{F5ADB74E-02A7-44FB-AA3B-FC02F8AC7A4B}</Project> </ProjectReference> - <ProjectReference Include="..\graphics-app-framework\graphics-app-framework.vcxproj"> + <ProjectReference Include="..\platform\platform.vcxproj"> <Project>{3565FE5E-4FA3-11EB-AE93-0242AC130002}</Project> </ProjectReference> </ItemGroup> diff --git a/build/visual-studio/shader-toy/shader-toy.vcxproj b/build/visual-studio/shader-toy/shader-toy.vcxproj index 9fd7014a3..823841a46 100644 --- a/build/visual-studio/shader-toy/shader-toy.vcxproj +++ b/build/visual-studio/shader-toy/shader-toy.vcxproj @@ -181,7 +181,7 @@ <ProjectReference Include="..\gfx-util\gfx-util.vcxproj"> <Project>{F5ADB74E-02A7-44FB-AA3B-FC02F8AC7A4B}</Project> </ProjectReference> - <ProjectReference Include="..\graphics-app-framework\graphics-app-framework.vcxproj"> + <ProjectReference Include="..\platform\platform.vcxproj"> <Project>{3565FE5E-4FA3-11EB-AE93-0242AC130002}</Project> </ProjectReference> </ItemGroup> diff --git a/examples/gpu-printing/main.cpp b/examples/gpu-printing/main.cpp index 63eb31a82..e95233571 100644 --- a/examples/gpu-printing/main.cpp +++ b/examples/gpu-printing/main.cpp @@ -6,7 +6,7 @@ using Slang::ComPtr; #include "slang-gfx.h" -#include "tools/graphics-app-framework/window.h" +#include "tools/platform/window.h" #include "source/core/slang-basic.h" using namespace gfx; @@ -44,7 +44,7 @@ ComPtr<slang::IModule> compileShaderModuleFromFile(slang::ISession* slangSession const SlangResult compileRes = spCompile(slangRequest); if(auto diagnostics = spGetDiagnosticOutput(slangRequest)) { - reportError("%s", diagnostics); + printf("%s", diagnostics); } if(SLANG_FAILED(compileRes)) @@ -63,7 +63,6 @@ struct ExampleProgram int gWindowWidth = 640; int gWindowHeight = 480; -gfx::ApplicationContext* gAppContext; ComPtr<gfx::IRenderer> gRenderer; ComPtr<slang::ISession> gSlangSession; @@ -151,8 +150,6 @@ Result execute() auto descriptorSet = gRenderer->createDescriptorSet(descriptorSetLayout, IDescriptorSet::Flag::Transient); if(!descriptorSet) return SLANG_FAIL; -// descriptorSet->setConstantBuffer(0, 0, gConstantBuffer); - gDescriptorSet = descriptorSet; ComputePipelineStateDesc desc; @@ -201,21 +198,12 @@ Result execute() }; -// This "inner" main function is used by the platform abstraction -// layer to deal with differences in how an entry point needs -// to be defined for different platforms. -// -void innerMain(ApplicationContext* context) +int main() { ExampleProgram app; - if (SLANG_FAILED(app.execute())) { - return exitApplication(context, 1); + return -1; } + return 0; } - -// This macro instantiates an appropriate main function to -// invoke the `innerMain` above. -// -GFX_CONSOLE_MAIN(innerMain) diff --git a/examples/hello-world/main.cpp b/examples/hello-world/main.cpp index 47016b48d..330b52a59 100644 --- a/examples/hello-world/main.cpp +++ b/examples/hello-world/main.cpp @@ -34,7 +34,7 @@ // #include "slang-gfx.h" #include "gfx-util/shader-cursor.h" -#include "tools/graphics-app-framework/window.h" +#include "tools/platform/window.h" #include "slang-com-ptr.h" #include "source/core/slang-basic.h" @@ -76,7 +76,7 @@ void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob) { if( diagnosticsBlob != nullptr ) { - reportError("%s", (const char*) diagnosticsBlob->getBufferPointer()); + printf("%s", (const char*) diagnosticsBlob->getBufferPointer()); } } @@ -210,8 +210,7 @@ const uint32_t kSwapchainImageCount = 2; // of them come from the utility library we are using to simplify // building an example program. // -gfx::ApplicationContext* gAppContext; -gfx::Window* gWindow; +RefPtr<platform::Window> gWindow; Slang::ComPtr<gfx::IRenderer> gRenderer; ComPtr<gfx::IPipelineState> gPipelineState; @@ -230,12 +229,12 @@ Slang::Result initialize() { // Create a window for our application to render into. // - WindowDesc windowDesc; + platform::WindowDesc windowDesc; windowDesc.title = "Hello, World!"; windowDesc.width = gWindowWidth; windowDesc.height = gWindowHeight; - gWindow = createWindow(windowDesc); - + gWindow = platform::Application::createWindow(windowDesc); + gWindow->events.mainLoop = [this]() { renderFrame(); }; // Initialize the rendering layer. // // Note: for now we are hard-coding logic to use the @@ -323,8 +322,9 @@ Slang::Result initialize() swapchainDesc.height = gWindowHeight; swapchainDesc.imageCount = kSwapchainImageCount; swapchainDesc.queue = gQueue; - gSwapchain = gRenderer->createSwapchain( - swapchainDesc, gfx::WindowHandle::FromHwnd(getPlatformWindowHandle(gWindow))); + gfx::WindowHandle windowHandle; + memcpy(&windowHandle, &gWindow->getNativeHandle(), sizeof(windowHandle)); + gSwapchain = gRenderer->createSwapchain(swapchainDesc, windowHandle); IFramebufferLayout::AttachmentLayout renderTargetLayout = {gSwapchain->getDesc().format, 1}; IFramebufferLayout::AttachmentLayout depthLayout = {gfx::Format::D_Float32, 1}; @@ -405,11 +405,6 @@ Slang::Result initialize() renderPassDesc.depthStencilAccess = &depthStencilAccess; gRenderPass = gRenderer->createRenderPassLayout(renderPassDesc); - // Once we've initialized all the graphics API objects, - // it is time to show our application window and start rendering. - // - showWindow(gWindow); - return SLANG_OK; } @@ -526,7 +521,6 @@ void finalize() { gQueue->wait(); gSwapchain = nullptr; - destroyWindow(gWindow); } }; @@ -535,7 +529,7 @@ void finalize() // layer to deal with differences in how an entry point needs // to be defined for different platforms. // -void innerMain(ApplicationContext* context) +int innerMain() { // We construct an instance of our example application // `struct` type, and then walk through the lifecyle @@ -545,18 +539,17 @@ void innerMain(ApplicationContext* context) if (SLANG_FAILED(app.initialize())) { - return exitApplication(context, 1); + return -1; } - while(dispatchEvents(context)) - { - app.renderFrame(); - } + platform::Application::run(app.gWindow); app.finalize(); + + return 0; } // This macro instantiates an appropriate main function to // invoke the `innerMain` above. // -GFX_UI_MAIN(innerMain) +PLATFORM_UI_MAIN(innerMain) diff --git a/examples/shader-toy/main.cpp b/examples/shader-toy/main.cpp index 0d058fa2c..7c22954c0 100644 --- a/examples/shader-toy/main.cpp +++ b/examples/shader-toy/main.cpp @@ -20,9 +20,12 @@ using Slang::ComPtr; // compiler, and API. // #include "slang-gfx.h" -#include "tools/graphics-app-framework/window.h" +#include "tools/platform/window.h" +#include "tools/platform/performance-counter.h" #include "source/core/slang-basic.h" +#include <chrono> + using namespace gfx; // In order to display a shader toy effect using rasterization-based shader @@ -82,7 +85,7 @@ void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob) { if( diagnosticsBlob != nullptr ) { - reportError("%s", (const char*) diagnosticsBlob->getBufferPointer()); + printf("%s", (const char*) diagnosticsBlob->getBufferPointer()); } } @@ -329,8 +332,7 @@ int gWindowWidth = 1024; int gWindowHeight = 768; const uint32_t kSwapchainImageCount = 2; -gfx::ApplicationContext* gAppContext; -gfx::Window* gWindow; +Slang::RefPtr<platform::Window> gWindow; Slang::ComPtr<gfx::IRenderer> gRenderer; ComPtr<gfx::IBufferResource> gConstantBuffer; ComPtr<gfx::IPipelineLayout> gPipelineLayout; @@ -344,13 +346,15 @@ ComPtr<gfx::ICommandQueue> gQueue; Result initialize() { - WindowDesc windowDesc; + platform::WindowDesc windowDesc; windowDesc.title = "Slang Shader Toy"; windowDesc.width = gWindowWidth; windowDesc.height = gWindowHeight; - windowDesc.eventHandler = &_handleEvent; - windowDesc.userData = this; - gWindow = createWindow(windowDesc); + gWindow = platform::Application::createWindow(windowDesc); + gWindow->events.mainLoop = [this]() { renderFrame(); }; + gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) { handleEvent(e); }; + gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { handleEvent(e); }; + gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) { handleEvent(e); }; IRenderer::Desc rendererDesc; rendererDesc.rendererType = RendererType::DirectX11; @@ -430,8 +434,9 @@ Result initialize() swapchainDesc.height = gWindowHeight; swapchainDesc.imageCount = kSwapchainImageCount; swapchainDesc.queue = gQueue; - gSwapchain = gRenderer->createSwapchain( - swapchainDesc, gfx::WindowHandle::FromHwnd(getPlatformWindowHandle(gWindow))); + gfx::WindowHandle windowHandle; + memcpy(&windowHandle, &gWindow->getNativeHandle(), sizeof(windowHandle)); + gSwapchain = gRenderer->createSwapchain(swapchainDesc, windowHandle); IFramebufferLayout::AttachmentLayout renderTargetLayout = {gSwapchain->getDesc().format, 1}; IFramebufferLayout::AttachmentLayout depthLayout = {gfx::Format::D_Float32, 1}; @@ -513,9 +518,6 @@ Result initialize() renderPassDesc.renderTargetAccess = &renderTargetAccess; renderPassDesc.depthStencilAccess = &depthStencilAccess; gRenderPass = gRenderer->createRenderPassLayout(renderPassDesc); - - showWindow(gWindow); - return SLANG_OK; } @@ -527,7 +529,7 @@ float clickMouseX = 0.0f; float clickMouseY = 0.0f; bool firstTime = true; -uint64_t startTime = 0; +platform::TimePoint startTime; void renderFrame() { @@ -535,7 +537,7 @@ void renderFrame() auto commandBuffer = gQueue->createCommandBuffer(); if( firstTime ) { - startTime = getCurrentTime(); + startTime = platform::PerformanceCounter::now(); firstTime = false; } @@ -557,7 +559,7 @@ void renderFrame() uniforms.iMouse[1] = lastMouseY; uniforms.iMouse[2] = isMouseDown ? clickMouseX : -clickMouseX; uniforms.iMouse[3] = isMouseClick ? clickMouseY : -clickMouseY; - uniforms.iTime = float( double(getCurrentTime() - startTime) / double(getTimerFrequency()) ); + uniforms.iTime = platform::PerformanceCounter::getElapsedTimeInSeconds(startTime); uniforms.iResolution[0] = float(gWindowWidth); uniforms.iResolution[1] = float(gWindowHeight); @@ -588,59 +590,31 @@ void renderFrame() void finalize() { gQueue->wait(); - destroyWindow(gWindow); -} - -void handleEvent(Event const& event) -{ - switch( event.code ) - { - case EventCode::MouseDown: - isMouseDown = true; - lastMouseX = event.u.mouse.x; - lastMouseY = event.u.mouse.y; - break; - - case EventCode::MouseMoved: - lastMouseX = event.u.mouse.x; - lastMouseY = event.u.mouse.y; - break; - - case EventCode::MouseUp: - isMouseDown = false; - lastMouseX = event.u.mouse.x; - lastMouseY = event.u.mouse.y; - break; - - default: - break; - } } -static void _handleEvent(Event const& event) +void handleEvent(const platform::MouseEventArgs& event) { - ShaderToyApp* app = (ShaderToyApp*) getUserData(event.window); - app->handleEvent(event); + isMouseDown = ((int)event.buttons & (int)platform::ButtonState::Enum::LeftButton) != 0; + lastMouseX = (float)event.x; + lastMouseY = (float)event.y; } - }; -void innerMain(ApplicationContext* context) +int innerMain() { ShaderToyApp app; if (SLANG_FAILED(app.initialize())) { - return exitApplication(context, 1); + return -1; } - while(dispatchEvents(context)) - { - app.renderFrame(); - } + platform::Application::run(app.gWindow); app.finalize(); + + return 0; } -GFX_UI_MAIN(innerMain) +PLATFORM_UI_MAIN(innerMain) diff --git a/premake5.lua b/premake5.lua index e4f9b91cc..bd5c72c63 100644 --- a/premake5.lua +++ b/premake5.lua @@ -525,7 +525,7 @@ function example(name) -- and the `gfx` abstraction layer (which in turn -- depends on the `core` library). We specify all of that here, -- rather than in each example. - links { "slang", "core", "gfx", "gfx-util", "graphics-app-framework" } + links { "slang", "core", "gfx", "gfx-util", "platform" } end -- @@ -695,8 +695,8 @@ toolSharedLibrary "slang-reflection-test" toolSharedLibrary "render-test" uuid "61F7EB00-7281-4BF3-9470-7C2EA92620C3" - includedirs { ".", "external", "source", "tools/gfx", "tools/graphics-app-framework" } - links { "core", "slang", "gfx", "gfx-util", "graphics-app-framework" } + includedirs { ".", "external", "source", "tools/gfx", "tools/platform" } + links { "core", "slang", "gfx", "gfx-util", "platform" } if isTargetWindows then addSourceDir "tools/render-test/windows" @@ -824,21 +824,21 @@ tool "gfx-util" addSourceDir "tools/gfx-util" -- --- `graphics-app-framework` contains all the utils for a simple graphics application. +-- `platform` contains all the platform abstractions for a GUI application. -- -tool "graphics-app-framework" +tool "platform" uuid "3565fe5e-4fa3-11eb-ae93-0242ac130002" kind "StaticLib" pic "On" includedirs { ".", "external", "source", "external/imgui", "tools/gfx" } - addSourceDir "tools/graphics-app-framework" - + addSourceDir "tools/platform" + addSourceDir "tools/platform/linux" + addSourceDir "tools/platform/windows" -- Include windowing support on Windows. if isTargetWindows then systemversion "10.0.14393.0" - addSourceDir "tools/graphics-app-framework/windows" end -- @@ -47,7 +47,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gfx", "build\visual-studio\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gfx-util", "build\visual-studio\gfx-util\gfx-util.vcxproj", "{F5ADB74E-02A7-44FB-AA3B-FC02F8AC7A4B}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "graphics-app-framework", "build\visual-studio\graphics-app-framework\graphics-app-framework.vcxproj", "{3565FE5E-4FA3-11EB-AE93-0242AC130002}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "platform", "build\visual-studio\platform\platform.vcxproj", "{3565FE5E-4FA3-11EB-AE93-0242AC130002}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "slang-cpp-extractor", "build\visual-studio\slang-cpp-extractor\slang-cpp-extractor.vcxproj", "{CA8A30D1-8FA9-4330-B7F7-84709246D8DC}" EndProject diff --git a/source/core/slang-func-ptr.h b/source/core/slang-func-ptr.h new file mode 100644 index 000000000..c861bc6b8 --- /dev/null +++ b/source/core/slang-func-ptr.h @@ -0,0 +1,202 @@ +#ifndef SLANG_CORE_FUNC_PTR_H +#define SLANG_CORE_FUNC_PTR_H + +#include "slang-smart-pointer.h" + +namespace Slang +{ + +template <typename TResult, typename... Arguments> class FuncPtr : public RefObject +{ +public: + virtual TResult operator()(Arguments...) const = 0; + virtual bool operator==(const FuncPtr<TResult, Arguments...>*) { return false; } + virtual FuncPtr<TResult, Arguments...>* clone() = 0; + virtual ~FuncPtr() {} +}; + +template <typename TResult, typename... Arguments> +class CdeclFuncPtr : public FuncPtr<TResult, Arguments...> +{ +public: + typedef TResult (*FuncType)(Arguments...); + +private: + FuncType funcPtr; + +public: + CdeclFuncPtr(FuncType func) + : funcPtr(func) + {} + virtual FuncPtr<TResult, Arguments...>* clone() override + { + auto rs = new CdeclFuncPtr<TResult, Arguments...>(funcPtr); + return rs; + } + + virtual TResult operator()(Arguments... params) const override { return funcPtr(params...); } + + virtual bool operator==(const FuncPtr<TResult, Arguments...>* ptr) override + { + auto cptr = dynamic_cast<const CdeclFuncPtr<TResult, Arguments...>*>(ptr); + if (cptr) + return funcPtr == cptr->funcPtr; + else + return false; + } +}; + +template <typename Class, typename TResult, typename... Arguments> +class MemberFuncPtr : public FuncPtr<TResult, Arguments...> +{ +public: + typedef TResult (Class::*FuncType)(Arguments...); + +private: + FuncType funcPtr; + Class* object; + +public: + MemberFuncPtr(Class* obj, FuncType func) + : funcPtr(func) + , object(obj) + {} + virtual FuncPtr<TResult, Arguments...>* clone() override + { + auto rs = new MemberFuncPtr<Class, TResult, Arguments...>(object, funcPtr); + return rs; + } + virtual TResult operator()(Arguments... params) const override + { + return (object->*funcPtr)(params...); + } + + virtual bool operator==(const FuncPtr<TResult, Arguments...>* ptr) override + { + auto cptr = dynamic_cast<const MemberFuncPtr<Class, TResult, Arguments...>*>(ptr); + if (cptr) + return funcPtr == cptr->funcPtr && object == cptr->object; + else + return false; + } +}; + +template <typename F, typename TResult, typename... Arguments> +class LambdaFuncPtr : public FuncPtr<TResult, Arguments...> +{ +private: + F func; + +public: + LambdaFuncPtr(const F& _func) + : func(_func) + {} + virtual TResult operator()(Arguments... params) const override { return func(params...); } + virtual FuncPtr<TResult, Arguments...>* clone() override + { + auto rs = new LambdaFuncPtr<F, TResult, Arguments...>(func); + return rs; + } + virtual bool operator==(const FuncPtr<TResult, Arguments...>* /*ptr*/) override + { + return false; + } +}; + +template <typename TResult, typename... Arguments> class Func +{ +private: + RefPtr<FuncPtr<TResult, Arguments...>> funcPtr; + +public: + Func() {} + Func(typename CdeclFuncPtr<TResult, Arguments...>::FuncType func) + { + funcPtr = new CdeclFuncPtr<TResult, Arguments...>(func); + } + template <typename Class> + Func(Class* object, typename MemberFuncPtr<Class, TResult, Arguments...>::FuncType func) + { + funcPtr = new MemberFuncPtr<Class, TResult, Arguments...>(object, func); + } + template <typename TFuncObj> Func(const TFuncObj& func) + { + funcPtr = new LambdaFuncPtr<TFuncObj, TResult, Arguments...>(func); + } + Func& operator=(typename CdeclFuncPtr<TResult, Arguments...>::FuncType func) + { + funcPtr = new CdeclFuncPtr<TResult, Arguments...>(func); + return *this; + } + template <typename Class> + Func& operator=(const MemberFuncPtr<Class, TResult, Arguments...>& func) + { + funcPtr = new MemberFuncPtr<Class, TResult, Arguments...>(func); + return *this; + } + template <typename TFuncObj> Func& operator=(const TFuncObj& func) + { + funcPtr = new LambdaFuncPtr<TFuncObj, TResult, Arguments...>(func); + return *this; + } + bool operator==(const Func& f) { return *funcPtr == f.funcPtr.Ptr(); } + bool operator!=(const Func& f) { return !(*this == f); } + TResult operator()(Arguments... params) const { return (*funcPtr)(params...); } +}; + +// template<typename... Arguments> +// using Action = Func<void, Arguments...>; + +template <typename... Arguments> class Action : public Func<void, Arguments...> +{ +private: + RefPtr<FuncPtr<void, Arguments...>> funcPtr; + +public: + Action() {} + Action(const Action& proc) { funcPtr = proc.funcPtr; } + Action(typename CdeclFuncPtr<void, Arguments...>::FuncType func) + { + funcPtr = new CdeclFuncPtr<void, Arguments...>(func); + } + template <typename Class> + Action(Class* object, typename MemberFuncPtr<Class, void, Arguments...>::FuncType func) + { + funcPtr = new MemberFuncPtr<Class, void, Arguments...>(object, func); + } + template <typename TFuncObj> Action(const TFuncObj& func) + { + funcPtr = new LambdaFuncPtr<TFuncObj, void, Arguments...>(func); + } + Action& operator=(typename CdeclFuncPtr<void, Arguments...>::FuncType func) + { + funcPtr = new CdeclFuncPtr<void, Arguments...>(func); + return *this; + } + template <typename Class> + Action& operator=(const MemberFuncPtr<Class, void, Arguments...>& func) + { + funcPtr = new MemberFuncPtr<Class, void, Arguments...>(func); + return *this; + } + template <typename TFuncObj> Action& operator=(const TFuncObj& func) + { + funcPtr = new LambdaFuncPtr<TFuncObj, void, Arguments...>(func); + return *this; + } + Action& operator=(const Action& proc) + { + funcPtr = proc.funcPtr; + return *this; + } + void clear() { funcPtr = nullptr; } + void operator()(Arguments... params) const + { + if (funcPtr) + (*funcPtr)(params...); + } +}; + +} // namespace Slang + +#endif diff --git a/tools/graphics-app-framework/gui.h b/tools/graphics-app-framework/gui.h deleted file mode 100644 index 680cea14b..000000000 --- a/tools/graphics-app-framework/gui.h +++ /dev/null @@ -1,31 +0,0 @@ -// gui.h -#pragma once - -#include "slang-gfx.h" -#include "vector-math.h" -#include "window.h" -#include "slang-com-ptr.h" -#include "external/imgui/imgui.h" -#include "source/core/slang-basic.h" - -namespace gfx { - -struct GUI : Slang::RefObject -{ - GUI(Window* window, IRenderer* renderer, ICommandQueue* queue, IFramebufferLayout* framebufferLayout); - ~GUI(); - - void beginFrame(); - void endFrame(IFramebuffer* framebuffer); - -private: - Slang::ComPtr<IRenderer> renderer; - Slang::ComPtr<ICommandQueue> queue; - Slang::ComPtr<IRenderPassLayout> renderPass; - Slang::ComPtr<IPipelineState> pipelineState; - Slang::ComPtr<IDescriptorSetLayout> descriptorSetLayout; - Slang::ComPtr<IPipelineLayout> pipelineLayout; - Slang::ComPtr<ISamplerState> samplerState; -}; - -} // gfx diff --git a/tools/graphics-app-framework/window.h b/tools/graphics-app-framework/window.h deleted file mode 100644 index 2e216aacf..000000000 --- a/tools/graphics-app-framework/window.h +++ /dev/null @@ -1,133 +0,0 @@ -// window.h -#pragma once - -#include <stdint.h> - -namespace gfx { - -struct Window; - -enum class KeyCode -{ - Unknown, - - // TODO: extend this to cover at least a standard US-English keyboard - - A, B, C, D, E, F, G, H, I, J, - K, L, M, N, O, P, Q, R, S, T, - U, V, W, X, Y, Z, - - Space, -}; - -enum class EventCode : uint32_t -{ - MouseDown, - MouseUp, - MouseMoved, - KeyDown, - KeyUp, -}; - -struct Event -{ - EventCode code; - Window* window; - union - { - struct - { - float x; - float y; - } mouse; - - KeyCode key; - } u; -}; - -typedef void (*EventHandler)(Event const&); - -struct WindowDesc -{ - char const* title = nullptr; - void* userData = nullptr; - int width = 0; - int height = 0; - EventHandler eventHandler = nullptr; -}; - -Window* createWindow(WindowDesc const& desc); -void destroyWindow(Window* window); -void showWindow(Window* window); - -void* getPlatformWindowHandle(Window* window); -void* getUserData(Window* window); - -/// Opaque state provided by platform for a running application. -typedef struct ApplicationContext ApplicationContext; - -/// User-defined application entry-point function. -typedef void(*ApplicationFunc)(ApplicationContext* context); - -/// Dispatch any pending events for application. -/// -/// @returns `true` if application should keep running. -bool dispatchEvents(ApplicationContext* context); - -/// Exit the application with a given result code -void exitApplication(ApplicationContext* context, int resultCode); - -/// Log a message to an appropriate logging destination. -void log(char const* message, ...); - -/// Report an error to an appropriate logging destination. -int reportError(char const* message, ...); - -uint64_t getCurrentTime(); - -uint64_t getTimerFrequency(); - -/// Run an application given the specified callback and command-line arguments. -int runApplication( - ApplicationFunc func, - int argc, - char const* const* argv); - -#define GFX_CONSOLE_MAIN(APPLICATION_ENTRY) \ - int main(int argc, char** argv) { \ - return gfx::runApplication(&(APPLICATION_ENTRY), argc, argv); \ - } - -#ifdef _WIN32 - -int runWindowsApplication( - ApplicationFunc func, - void* instance, - int showCommand); - -#ifdef _MSC_VER -#ifdef _DEBUG -# define GFX_DUMP_LEAK _CrtDumpMemoryLeaks(); -#endif -#endif -#ifndef GFX_DUMP_LEAK -#define GFX_DUMP_LEAK -#endif -#define GFX_UI_MAIN(APPLICATION_ENTRY) \ - int __stdcall WinMain( \ - void* instance, \ - void* /* prevInstance */, \ - void* /* commandLine */, \ - int showCommand) { \ - auto result = gfx::runWindowsApplication(&(APPLICATION_ENTRY), instance, showCommand); \ - GFX_DUMP_LEAK \ - return result; \ - } - -#else - -#define GFX_UI_MAIN(APPLICATION_ENTRY) GFX_CONSOLE_MAIN(APPLICATION_ENTRY) - -#endif - -} // gfx diff --git a/tools/graphics-app-framework/windows/win-window.cpp b/tools/graphics-app-framework/windows/win-window.cpp deleted file mode 100644 index 2beb65d70..000000000 --- a/tools/graphics-app-framework/windows/win-window.cpp +++ /dev/null @@ -1,416 +0,0 @@ -// win-window.cpp -#include "../window.h" - -#include "core/slang-smart-pointer.h" - -#include <stdio.h> - -#ifdef _MSC_VER -#include <stddef.h> -#if (_MSC_VER < 1900) -#define snprintf sprintf_s -#endif -#endif - -#include <stdint.h> - -#if _WIN32 -#include <Windows.h> -#include <Windowsx.h> -#else -#error "The slang-graphics library currently only supports Windows platforms" -#endif - -namespace gfx { - -#if _WIN32 - -struct OSString -{ - OSString(char const* begin, char const* end) - { - _initialize(begin, end - begin); - } - - OSString(char const* begin) - { - _initialize(begin, strlen(begin)); - } - - ~OSString() - { - free(mBegin); - } - - operator WCHAR const*() - { - return mBegin; - } - -private: - WCHAR* mBegin; - WCHAR* mEnd; - - void _initialize(char const* input, size_t inputSize) - { - const DWORD dwFlags = 0; - int outputCodeUnitCount = ::MultiByteToWideChar(CP_UTF8, dwFlags, input, int(inputSize), nullptr, 0); - - WCHAR* buffer = (WCHAR*)malloc(sizeof(WCHAR) * (outputCodeUnitCount + 1)); - - ::MultiByteToWideChar(CP_UTF8, dwFlags, input, int(inputSize), buffer, outputCodeUnitCount); - buffer[outputCodeUnitCount] = 0; - - mBegin = buffer; - mEnd = buffer + outputCodeUnitCount; - } -}; - -struct ApplicationContext : public Slang::RefObject -{ - HINSTANCE instance; - int showCommand = SW_SHOWDEFAULT; - int resultCode = 0; -}; - -static uint64_t gTimerFrequency; - - -static void initApplication(ApplicationContext* context) -{ - LARGE_INTEGER timerFrequency; - QueryPerformanceFrequency(&timerFrequency); - gTimerFrequency = timerFrequency.QuadPart; -} - -/// Run an application given the specified callback and command-line arguments. -int runApplication( - ApplicationFunc func, - int argc, - char const* const* argv) -{ - ApplicationContext context; - context.instance = (HINSTANCE) GetModuleHandle(0); - initApplication(&context); - func(&context); - return context.resultCode; -} - -int runWindowsApplication( - ApplicationFunc func, - void* instance, - int showCommand) -{ - ApplicationContext context; - context.instance = (HINSTANCE) instance; - context.showCommand = showCommand; - initApplication(&context); - func(&context); - return context.resultCode; -} - -struct Window -{ - HWND handle; - WNDPROC nativeHook; - EventHandler eventHandler; - void* userData; -}; - -void setNativeWindowHook(Window* window, WNDPROC proc) -{ - window->nativeHook = proc; -} - -static KeyCode translateKeyCode(int vkey) -{ - switch( vkey ) - { - default: - return KeyCode::Unknown; - -#define CASE(FROM, TO) case FROM: return KeyCode::TO; - CASE('A', A); CASE('B', B); CASE('C', C); CASE('D', D); CASE('E', E); - CASE('F', F); CASE('G', G); CASE('H', H); CASE('I', I); CASE('J', J); - CASE('K', K); CASE('L', M); CASE('M', M); CASE('N', N); CASE('O', O); - CASE('P', P); CASE('Q', Q); CASE('R', R); CASE('S', S); CASE('T', T); - CASE('U', U); CASE('V', V); CASE('W', W); CASE('X', X); CASE('Y', Y); - CASE('Z', Z); -#undef CASE - -#define CASE(FROM, TO) case VK_##FROM: return KeyCode::TO; - CASE(SPACE, Space); -#undef CASE - } -} - -static LRESULT CALLBACK windowProc( - HWND windowHandle, - UINT message, - WPARAM wParam, - LPARAM lParam) -{ - Window* window = (Window*) GetWindowLongPtrW(windowHandle, GWLP_USERDATA); - - // Give the installed filter a chance to intercept messages. - // (This is used for ImGui) - if( window ) - { - if(auto nativeHook = window->nativeHook) - { - auto result = nativeHook(windowHandle, message, wParam, lParam); - if(result) - return result; - } - } - - auto eventHandler = window ? window->eventHandler : nullptr; - - switch (message) - { - case WM_CREATE: - { - auto createInfo = (CREATESTRUCTW*) lParam; - window = (Window*) createInfo->lpCreateParams; - window->handle = windowHandle; - - SetWindowLongPtrW(windowHandle, GWLP_USERDATA, (LONG_PTR) window); - } - break; - - case WM_KEYDOWN: - case WM_KEYUP: - { - int virtualKey = (int) wParam; - auto keyCode = translateKeyCode(virtualKey); - if(eventHandler) - { - Event event; - event.window = window; - event.code = message == WM_KEYDOWN ? EventCode::KeyDown : EventCode::KeyUp; - event.u.key = keyCode; - eventHandler(event); - } - } - break; - - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - { - if(eventHandler) - { - Event event; - event.window = window; - event.code = message == WM_LBUTTONDOWN ? EventCode::MouseDown : EventCode::MouseUp; - event.u.mouse.x = (float) GET_X_LPARAM(lParam); - event.u.mouse.y = (float) GET_Y_LPARAM(lParam); - eventHandler(event); - } - } - break; - - case WM_MOUSEMOVE: - { - if(eventHandler) - { - Event event; - event.window = window; - event.code = EventCode::MouseMoved; - event.u.mouse.x = (float) GET_X_LPARAM(lParam); - event.u.mouse.y = (float) GET_Y_LPARAM(lParam); - eventHandler(event); - } - } - break; - - case WM_CLOSE: - PostQuitMessage(0); - return 0; - } - - - return DefWindowProcW(windowHandle, message, wParam, lParam); -} - - -static ATOM createWindowClassAtom() -{ - WNDCLASSEXW windowClassDesc; - windowClassDesc.cbSize = sizeof(windowClassDesc); - windowClassDesc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; - windowClassDesc.lpfnWndProc = &windowProc; - windowClassDesc.cbClsExtra = 0; - windowClassDesc.cbWndExtra = 0; - windowClassDesc.hInstance = (HINSTANCE) GetModuleHandle(0); - windowClassDesc.hIcon = 0; - windowClassDesc.hCursor = LoadCursorW(NULL, IDC_ARROW); - windowClassDesc.hbrBackground = 0; - windowClassDesc.lpszMenuName = 0; - windowClassDesc.lpszClassName = L"SlangGraphicsWindow"; - windowClassDesc.hIconSm = 0; - ATOM windowClassAtom = RegisterClassExW(&windowClassDesc); - return windowClassAtom; -} - -static ATOM getWindowClassAtom() -{ - static ATOM windowClassAtom = createWindowClassAtom(); - return windowClassAtom; -} - -Window* createWindow(WindowDesc const& desc) -{ - Window* window = new Window(); - window->handle = nullptr; - window->nativeHook = nullptr; - window->eventHandler = desc.eventHandler; - window->userData = desc.userData; - - OSString windowTitle(desc.title); - - DWORD windowExtendedStyle = 0; - DWORD windowStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU; - - HINSTANCE instance = (HINSTANCE) GetModuleHandle(0); - - RECT windowRect; - windowRect.left = 0; - windowRect.top = 0; - windowRect.bottom = desc.height; - windowRect.right = desc.width; - AdjustWindowRect(&windowRect, windowStyle, FALSE); - - HWND windowHandle = CreateWindowExW( - windowExtendedStyle, - (LPWSTR) getWindowClassAtom(), - windowTitle, - windowStyle, - CW_USEDEFAULT, - 0, // x, y - windowRect.right - windowRect.left, - windowRect.bottom - windowRect.top, - NULL, // parent - NULL, // menu - instance, - window); - - - if(!windowHandle) - { - delete window; - return nullptr; - } - - window->handle = windowHandle; - return window; -} - -void destroyWindow(Window* window) -{ - DestroyWindow(window->handle); - delete window; -} - -void showWindow(Window* window) -{ - ShowWindow(window->handle, SW_SHOW); -} - -void* getPlatformWindowHandle(Window* window) -{ - return window->handle; -} - -void* getUserData(Window* window) -{ - return window->userData; -} - -bool dispatchEvents(ApplicationContext* context) -{ - for(;;) - { - MSG message; - - int result = PeekMessageW(&message, NULL, 0, 0, PM_REMOVE); - if (result != 0) - { - if (message.message == WM_QUIT) - { - context->resultCode = (int)message.wParam; - return false; - } - - TranslateMessage(&message); - DispatchMessageW(&message); - } - else - { - return true; - } - } - -} - -void exitApplication(ApplicationContext* context, int resultCode) -{ - ExitProcess(resultCode); -} - -void log(char const* message, ...) -{ - va_list args; - va_start(args, message); - - static const int kBufferSize = 1024; - char messageBuffer[kBufferSize]; - vsnprintf(messageBuffer, kBufferSize - 1, message, args); - messageBuffer[kBufferSize - 1] = 0; - - va_end(args); - - fputs(messageBuffer, stderr); - - OSString wideMessageBuffer(messageBuffer); - OutputDebugStringW(wideMessageBuffer); -} - -int reportError(char const* message, ...) -{ - va_list args; - va_start(args, message); - - static const int kBufferSize = 1024; - char messageBuffer[kBufferSize]; - vsnprintf(messageBuffer, kBufferSize - 1, message, args); - messageBuffer[kBufferSize - 1] = 0; - - va_end(args); - - fputs(messageBuffer, stderr); - - OSString wideMessageBuffer(messageBuffer); - OutputDebugStringW(wideMessageBuffer); - - return 1; -} - -uint64_t getCurrentTime() -{ - LARGE_INTEGER counter; - QueryPerformanceCounter(&counter); - return counter.QuadPart; -} - -uint64_t getTimerFrequency() -{ - return gTimerFrequency; -} - -#else - -// TODO: put an SDL version here - -#endif - -} // gfx diff --git a/tools/graphics-app-framework/gui.cpp b/tools/platform/gui.cpp index 3d4283131..cf7e74acc 100644 --- a/tools/graphics-app-framework/gui.cpp +++ b/tools/platform/gui.cpp @@ -7,8 +7,10 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); #endif +using namespace gfx; -namespace gfx { +namespace platform +{ #ifdef _WIN32 LRESULT CALLBACK guiWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) @@ -48,7 +50,7 @@ GUI::GUI( ImGuiIO& io = ImGui::GetIO(); #ifdef _WIN32 - ImGui_ImplWin32_Init(getPlatformWindowHandle(window)); + ImGui_ImplWin32_Init((HWND)window->getNativeHandle().handleValues[0]); setNativeWindowHook(window, &guiWindowProc); #endif @@ -113,7 +115,7 @@ GUI::GUI( const SlangResult compileRes = spCompile(slangRequest); if(auto diagnostics = spGetDiagnosticOutput(slangRequest)) { - reportError("%s", diagnostics); + printf("%s", diagnostics); } if(SLANG_FAILED(compileRes)) { diff --git a/tools/platform/gui.h b/tools/platform/gui.h new file mode 100644 index 000000000..d22da3299 --- /dev/null +++ b/tools/platform/gui.h @@ -0,0 +1,34 @@ +// gui.h +#pragma once + +#include "slang-gfx.h" +#include "vector-math.h" +#include "window.h" +#include "slang-com-ptr.h" +#include "external/imgui/imgui.h" +#include "source/core/slang-basic.h" + +namespace platform { + +struct GUI : Slang::RefObject +{ + GUI(Window* window, + gfx::IRenderer* renderer, + gfx::ICommandQueue* queue, + gfx::IFramebufferLayout* framebufferLayout); + ~GUI(); + + void beginFrame(); + void endFrame(gfx::IFramebuffer* framebuffer); + +private: + Slang::ComPtr<gfx::IRenderer> renderer; + Slang::ComPtr<gfx::ICommandQueue> queue; + Slang::ComPtr<gfx::IRenderPassLayout> renderPass; + Slang::ComPtr<gfx::IPipelineState> pipelineState; + Slang::ComPtr<gfx::IDescriptorSetLayout> descriptorSetLayout; + Slang::ComPtr<gfx::IPipelineLayout> pipelineLayout; + Slang::ComPtr<gfx::ISamplerState> samplerState; +}; + +} // gfx diff --git a/tools/graphics-app-framework/model.cpp b/tools/platform/model.cpp index 6984a6818..f28577631 100644 --- a/tools/graphics-app-framework/model.cpp +++ b/tools/platform/model.cpp @@ -231,7 +231,7 @@ Result ModelLoader::load( if(!diagnostics.empty()) { - log("%s", diagnostics.c_str()); + printf("%s", diagnostics.c_str()); } if(!success) { diff --git a/tools/graphics-app-framework/model.h b/tools/platform/model.h index 412f10a1d..412f10a1d 100644 --- a/tools/graphics-app-framework/model.h +++ b/tools/platform/model.h diff --git a/tools/platform/performance-counter.h b/tools/platform/performance-counter.h new file mode 100644 index 000000000..e9e990f45 --- /dev/null +++ b/tools/platform/performance-counter.h @@ -0,0 +1,30 @@ +#ifndef PLATFORM_PERFORMANCE_COUNTER_H +#define PLATFORM_PERFORMANCE_COUNTER_H + +#include <chrono> + +namespace platform +{ +typedef std::chrono::high_resolution_clock::time_point TimePoint; +typedef std::chrono::high_resolution_clock::duration Duration; + +class PerformanceCounter +{ +public: + static inline TimePoint now() + { + return std::chrono::high_resolution_clock::now(); + } + static inline Duration getElapsedTime(TimePoint counter) { return now() - counter; } + static inline float getElapsedTimeInSeconds(TimePoint counter) + { + return (float)toSeconds(now() - counter); + } + static inline double toSeconds(Duration duration) + { + return std::chrono::duration<float>(duration).count(); + } +}; +} // namespace platform + +#endif diff --git a/tools/graphics-app-framework/vector-math.h b/tools/platform/vector-math.h index e35cb46ac..e35cb46ac 100644 --- a/tools/graphics-app-framework/vector-math.h +++ b/tools/platform/vector-math.h diff --git a/tools/platform/window.h b/tools/platform/window.h new file mode 100644 index 000000000..c776c3ffa --- /dev/null +++ b/tools/platform/window.h @@ -0,0 +1,235 @@ +// window.h +#pragma once + +#include "slang-com-ptr.h" +#include "source/core/slang-basic.h" +#include "source/core/slang-func-ptr.h" + +namespace platform { + +enum class KeyCode : uint32_t +{ + None = 0, + Left = 0x25, + Up = 0x26, + Down = 0x28, + Right = 0x27, + Escape = 0x1B, + Return = 0x0D, + Space = 0x20, + Shift = 0x10, + Ctrl = 0x11, + Alt = 0x12, + Backspace = 0x08, + Delete = 0x2E, + Home = 0x24, + End = 0x23, + PageUp = 0x21, + PageDown = 0x22, + Insert = 0x2D, + Tab = 0x09, + A = 0x41, + B = 0x42, + C = 0x43, + D = 0x44, + E = 0x45, + F = 0x46, + G = 0x47, + H = 0x48, + I = 0x49, + J = 0x4A, + K = 0x4B, + L = 0x4C, + M = 0x4D, + N = 0x4E, + O = 0x4F, + P = 0x50, + Q = 0x51, + R = 0x52, + S = 0x53, + T = 0x54, + U = 0x55, + V = 0x56, + W = 0x57, + X = 0x58, + Y = 0x59, + Z = 0x5A, + Semicolon = 0xBA, + Comma = 0xBC, + Dot = 0xBE, + Slash = 0xBF, + Quote = 0xDE, + LBracket = 0xDB, + RBracket = 0xDD, + Backslash = 0xDC, + Minus = 0xBD, + Plus = 0xBB, + Tilde = 0xC0, + Key0 = 0x30, + Key1 = 0x31, + Key2 = 0x32, + Key3 = 0x33, + Key4 = 0x34, + Key5 = 0x35, + Key6 = 0x36, + Key7 = 0x37, + Key8 = 0x38, + Key9 = 0x39, + F1 = 0x70, + F2 = 0x71, + F3 = 0x72, + F4 = 0x73, + F5 = 0x74, + F6 = 0x75, + F7 = 0x76, + F8 = 0x77, + F9 = 0x78, + F10 = 0x79, + F11 = 0x7A, + F12 = 0x7B, +}; + +struct WindowHandle +{ + enum class Type + { + Unknown, + Win32Handle, + XLibHandle, + }; + Type type; + intptr_t handleValues[2]; + 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) + { + WindowHandle handle = {}; + handle.type = WindowHandle::Type::XLibHandle; + handle.handleValues[0] = (intptr_t)(xdisplay); + handle.handleValues[1] = xwindow; + return handle; + } +}; + +struct ButtonState +{ + enum Enum + { + None = 0, LeftButton = 1, RightButton = 2, MiddleButton = 4, + Shift = 8, Control = 16, Alt = 32 + }; +}; + +struct KeyEventArgs +{ + KeyCode key; + wchar_t keyChar; // For KeyPress event + ButtonState::Enum buttons; + bool cancelEvent; +}; + +struct MouseEventArgs +{ + int x, y; + int delta; + ButtonState::Enum buttons; +}; + +struct Rect +{ + int x, y; + int width, height; +}; + +struct WindowDesc +{ + char const* title = nullptr; + int width = 0; + int height = 0; +}; + +class Window : public Slang::RefObject +{ +public: + struct Events + { + Slang::Action<> mainLoop; + Slang::Action<> sizeChanged; + Slang::Action<> focus; + Slang::Action<> lostFocus; + Slang::Action<KeyEventArgs&> keyDown; + Slang::Action<KeyEventArgs&> keyUp; + Slang::Action<KeyEventArgs&> keyPress; + Slang::Action<MouseEventArgs> mouseMove; + Slang::Action<MouseEventArgs> mouseUp; + Slang::Action<MouseEventArgs> mouseDown; + }; + + Events events; + + virtual void setClientSize(uint32_t width, uint32_t height) = 0; + virtual Rect getClientRect() = 0; + virtual void centerScreen() = 0; + virtual void close() = 0; + virtual bool getFocused() = 0; + virtual bool getVisible() = 0; + virtual WindowHandle getNativeHandle() = 0; + virtual void setText(Slang::String text) = 0; + virtual void show() = 0; + virtual void hide() = 0; + virtual int getCurrentDpi() = 0; +}; + +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(); +}; + +} // namespace platform + +#ifdef _WIN32 + +# ifdef _MSC_VER +# ifdef _DEBUG +# define GFX_DUMP_LEAK _CrtDumpMemoryLeaks(); +# endif +# endif +# ifndef GFX_DUMP_LEAK +# define GFX_DUMP_LEAK +# endif +# define PLATFORM_UI_MAIN(APPLICATION_ENTRY) \ + int __stdcall WinMain( \ + void* /*instance*/, \ + void* /* prevInstance */, \ + void* /* commandLine */, \ + int /*showCommand*/) \ + { \ + platform::Application::init(); \ + auto result = APPLICATION_ENTRY(); \ + platform::Application::dispose(); \ + GFX_DUMP_LEAK \ + return result; \ + } + +#else + +# define PLATFORM_UI_MAIN(APPLICATION_ENTRY) \ + int main() \ + { \ + platform::Application::init(); \ + auto rs - APPLICATION_ENTRY(); \ + platform::Application::dispose(); \ + } + +#endif diff --git a/tools/platform/windows/win-window.cpp b/tools/platform/windows/win-window.cpp new file mode 100644 index 000000000..0362a6839 --- /dev/null +++ b/tools/platform/windows/win-window.cpp @@ -0,0 +1,442 @@ +#ifdef _WIN32 + +#include "../window.h" + +#define WIN32_LEAN_AND_MEAN +#include <Windows.h> +#include <windowsx.h> +using namespace Slang; + +namespace platform +{ + +static const wchar_t* kWindowClassName = L"slang-platform-window"; + +typedef BOOL(WINAPI* EnableNonClientDpiScalingProc)(_In_ HWND hwnd); + +class Win32AppContext +{ +public: + static EnableNonClientDpiScalingProc enableNonClientDpiScaling; + static RefPtr<Window> mainWindow; + static OrderedDictionary<HWND, Window*> windows; + static HWND mainWindowHandle; + static bool isTerminated; + static bool isWindows81OrGreater; +}; + +EnableNonClientDpiScalingProc Win32AppContext::enableNonClientDpiScaling = nullptr; +HWND Win32AppContext::mainWindowHandle = nullptr; +RefPtr<Window> Win32AppContext::mainWindow; +OrderedDictionary<HWND, Window*> Win32AppContext::windows; +bool Win32AppContext::isTerminated = false; +bool Win32AppContext::isWindows81OrGreater = false; + + +ButtonState::Enum _addButtonState(ButtonState::Enum val, ButtonState::Enum newState) +{ + return (ButtonState::Enum)((int)val | (int)newState); +} + +ButtonState::Enum getModifierState() +{ + ButtonState::Enum result = ButtonState::Enum::None; + if (GetAsyncKeyState(VK_CONTROL)) + result = _addButtonState(result, ButtonState::Enum::Control); + if (GetAsyncKeyState(VK_SHIFT)) + result = _addButtonState(result, ButtonState::Enum::Shift); + if (GetAsyncKeyState(VK_MENU)) + result = _addButtonState(result, ButtonState::Enum::Alt); + return result; +} + +ButtonState::Enum getModifierState(WPARAM wParam) +{ + ButtonState::Enum result = ButtonState::Enum::None; + if (wParam & MK_CONTROL) + result = _addButtonState(result, ButtonState::Enum::Control); + if (wParam & MK_MBUTTON) + result = _addButtonState(result, ButtonState::Enum::MiddleButton); + if (wParam & MK_RBUTTON) + result = _addButtonState(result, ButtonState::Enum::RightButton); + if (wParam & MK_SHIFT) + result = _addButtonState(result, ButtonState::Enum::Shift); + if (GetAsyncKeyState(VK_MENU)) + result = _addButtonState(result, ButtonState::Enum::Alt); + return result; +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + bool useDefProc = true; + Window* window = nullptr; + Win32AppContext::windows.TryGetValue(hWnd, window); + switch (message) + { + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + { + int mx = GET_X_LPARAM(lParam); + int my = GET_Y_LPARAM(lParam); + bool processed = false; + if (window) + { + window->events.mouseUp(MouseEventArgs{ + mx, + my, + 0, getModifierState(wParam)}); + } + } + break; + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + { + int mx = GET_X_LPARAM(lParam); + int my = GET_Y_LPARAM(lParam); + bool processed = false; + if (window) + { + window->events.mouseDown(MouseEventArgs{mx, my, 0, getModifierState(wParam)}); + } + } + break; + case WM_MOUSEMOVE: + { + int mx = GET_X_LPARAM(lParam); + int my = GET_Y_LPARAM(lParam); + if (window) + { + window->events.mouseMove(MouseEventArgs{mx, my, 0, getModifierState(wParam)}); + } + } + break; + case WM_MOUSEWHEEL: + { + int delta = GET_WHEEL_DELTA_WPARAM(wParam); + if (window) + { + window->events.mouseMove(MouseEventArgs{0, 0, delta, getModifierState(wParam)}); + } + } + break; + case WM_CHAR: + { + if (window) + { + KeyEventArgs keyEventArgs = { + KeyCode::None, (wchar_t)(wParam), ButtonState::Enum::None, false}; + window->events.keyPress(keyEventArgs); + if (keyEventArgs.cancelEvent) + useDefProc = false; + } + } + break; + case WM_KEYDOWN: + { + if (window) + { + KeyEventArgs keyEventArgs = {(KeyCode)(wParam), 0, getModifierState(), false}; + window->events.keyDown(keyEventArgs); + if (keyEventArgs.cancelEvent) + useDefProc = false; + } + } + break; + case WM_KEYUP: + { + if (window) + { + KeyEventArgs keyEventArgs = {(KeyCode)(wParam), 0, getModifierState(), false}; + window->events.keyUp(keyEventArgs); + if (keyEventArgs.cancelEvent) + useDefProc = false; + } + } + break; + case WM_SETFOCUS: + { + if (window) + { + window->events.focus(); + } + } + break; + case WM_KILLFOCUS: + { + if (window) + { + window->events.lostFocus(); + } + } + break; + case WM_SIZE: + { + if (window) + { + window->events.sizeChanged(); + } + } + break; + case WM_NCCREATE: + { + if (Win32AppContext::enableNonClientDpiScaling) + Win32AppContext::enableNonClientDpiScaling(hWnd); + return DefWindowProc(hWnd, message, wParam, lParam); + } + break; + default: + break; + } + if (message == WM_DESTROY && hWnd == Win32AppContext::mainWindowHandle) + { + PostQuitMessage(0); + return 0; + } + if (useDefProc) + return DefWindowProc(hWnd, message, wParam, lParam); + return 0; +} + +void registerWindowClass() +{ + WNDCLASSEX wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + + wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; + wcex.lpfnWndProc = WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = GetModuleHandle(NULL); + wcex.hIcon = 0; + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); + wcex.lpszMenuName = 0; + wcex.lpszClassName = kWindowClassName; + wcex.hIconSm = 0; + + RegisterClassExW(&wcex); +} + +void unregisterWindowClass() { UnregisterClassW(kWindowClassName, GetModuleHandle(NULL)); } + +HRESULT(WINAPI* getDpiForMonitor) (void* hmonitor, int dpiType, unsigned int* dpiX, unsigned int* dpiY); + +void Application::init() +{ + *(FARPROC*)&Win32AppContext::enableNonClientDpiScaling = + GetProcAddress(GetModuleHandleA("User32"), "EnableNonClientDpiScaling"); + void*(WINAPI * RtlGetVersion)(LPOSVERSIONINFOEXW); + OSVERSIONINFOEXW osInfo; + *(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion"); + + if (RtlGetVersion) + { + osInfo.dwOSVersionInfoSize = sizeof(osInfo); + RtlGetVersion(&osInfo); + if (osInfo.dwMajorVersion > 8 || (osInfo.dwMajorVersion == 8 && osInfo.dwMinorVersion >= 1)) + Win32AppContext::isWindows81OrGreater = true; + } + HRESULT(WINAPI * setProcessDpiAwareness)(int value); + *(FARPROC*)&setProcessDpiAwareness = + GetProcAddress(GetModuleHandleA("Shcore"), "SetProcessDpiAwareness"); + *(FARPROC*)&getDpiForMonitor = GetProcAddress(GetModuleHandleA("Shcore"), "GetDpiForMonitor"); + if (setProcessDpiAwareness) + { + if (Win32AppContext::isWindows81OrGreater) + setProcessDpiAwareness(2); // PROCESS_PER_MONITOR_DPI_AWARE + else + setProcessDpiAwareness(1); // PROCESS_SYSTEM_DPI_AWARE + } + registerWindowClass(); +} + +void doEventsImpl(bool waitForEvents) +{ + int hasMsg = 0; + do + { + MSG msg = {}; + hasMsg = + (waitForEvents ? GetMessage(&msg, NULL, 0, 0) : PeekMessage(&msg, NULL, 0, 0, TRUE)); + if (hasMsg) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + if (msg.message == WM_QUIT) + Win32AppContext::isTerminated = true; + } while (!Win32AppContext::isTerminated && hasMsg); +} + +void Application::doEvents() { doEventsImpl(false); } + +void Application::quit() { Win32AppContext::isTerminated = true; } + +void Application::dispose() +{ + Win32AppContext::mainWindow = nullptr; + Win32AppContext::windows = decltype(Win32AppContext::windows)(); + unregisterWindowClass(); +} + +void Application::run(Window* mainWindow, bool waitForEvents) +{ + if (mainWindow) + { + Win32AppContext::mainWindow = mainWindow; + Win32AppContext::mainWindowHandle = (HWND)mainWindow->getNativeHandle().handleValues[0]; + ShowWindow(Win32AppContext::mainWindowHandle, SW_SHOW); + UpdateWindow(Win32AppContext::mainWindowHandle); + } + while (!Win32AppContext::isTerminated) + { + doEventsImpl(waitForEvents); + if (mainWindow) + { + mainWindow->events.mainLoop(); + } + } +} + +class Win32PlatformWindow : public Window +{ +public: + HWND handle; + DWORD style; + bool visible = false; + Win32PlatformWindow(const WindowDesc& desc) + { + DWORD windowExtendedStyle = 0; + DWORD style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU; + HINSTANCE instance = (HINSTANCE)GetModuleHandle(0); + + RECT windowRect; + windowRect.left = 0; + windowRect.top = 0; + windowRect.bottom = desc.height; + windowRect.right = desc.width; + AdjustWindowRect(&windowRect, style, FALSE); + + handle = CreateWindowExW( + windowExtendedStyle, + (LPWSTR)kWindowClassName, + String(desc.title).toWString().begin(), + style, + CW_USEDEFAULT, + 0, // x, y + windowRect.right, + windowRect.bottom, + NULL, // parent + NULL, // menu + instance, + NULL); + + if (handle) + Win32AppContext::windows[handle] = this; + } + + ~Win32PlatformWindow() + { + if (handle) + { + Win32AppContext::windows.Remove(handle); + } + DestroyWindow(handle); + } + + virtual void setClientSize(uint32_t width, uint32_t height) override + { + RECT currentRect; + GetWindowRect(handle, ¤tRect); + + RECT windowRect; + windowRect.left = currentRect.left; + windowRect.top = currentRect.top; + windowRect.bottom = height; + windowRect.right = width; + AdjustWindowRect(&windowRect, style, FALSE); + + MoveWindow( + handle, + windowRect.left, + windowRect.top, + windowRect.right - windowRect.left, + windowRect.bottom - windowRect.top, + FALSE); + } + + virtual Rect getClientRect() override + { + RECT currentRect; + GetClientRect(handle, ¤tRect); + Rect rect; + rect.x = currentRect.left; + rect.y = currentRect.top; + rect.width = currentRect.right - currentRect.left; + rect.height = currentRect.bottom - currentRect.top; + return rect; + } + + virtual void centerScreen() override + { + RECT screenRect; + GetClientRect(GetDesktopWindow(), &screenRect); + RECT currentRect; + GetWindowRect(handle, ¤tRect); + + auto width = currentRect.right - currentRect.left; + auto height = currentRect.bottom - currentRect.top; + + auto left = (screenRect.right - width) / 2; + auto top = (screenRect.bottom - height) / 2; + + MoveWindow(handle, left, top, width, height, FALSE); + } + + virtual void close() override {} + virtual bool getFocused() override { return GetFocus() == handle; } + virtual bool getVisible() override { return visible; } + virtual WindowHandle getNativeHandle() override + { + return WindowHandle::FromHwnd(handle); + } + virtual void setText(Slang::String text) override + { + SetWindowText(handle, text.toWString().begin()); + } + virtual void show() override + { + ShowWindow(handle, SW_SHOW); + visible = true; + } + virtual void hide() override + { + ShowWindow(handle, SW_HIDE); + visible = false; + } + virtual int getCurrentDpi() override + { + int dpi = 96; + if (Win32AppContext::isWindows81OrGreater && getDpiForMonitor) + { + getDpiForMonitor( + MonitorFromWindow(handle, MONITOR_DEFAULTTOPRIMARY), + 0, + (UINT*)&dpi, + (UINT*)&dpi); + return dpi; + } + dpi = GetDeviceCaps(NULL, LOGPIXELSY); + return dpi; + } +}; + +Window* Application::createWindow(const WindowDesc& desc) { return new Win32PlatformWindow(desc); } + + +} // namespace gfx + +#endif |
