summaryrefslogtreecommitdiff
path: root/tools/slang-graphics/window.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2018-06-28 11:14:48 -0700
committerGitHub <noreply@github.com>2018-06-28 11:14:48 -0700
commitdfe13b54286b27dd15f591455bbb86b7798285c2 (patch)
tree4a11f01feaae059b6c11bdfbe12a614228af6dd5 /tools/slang-graphics/window.cpp
parent22033f06573f900dc030c487b2c30feddf3d8f16 (diff)
Share graphics API layer between tests/examples (#603)
The `render-test` project has an in-progress graphics API abstraction layer, and it makes sense to share this code with our examples rather than write a bunch of redundant code between examples and tests. Most of this change is just moving files from `tools/render-test/*` to a new library project at `tools/slang-graphics/`. The most complicated code change there is renaming from `render_test` to `slang_graphics`. The existing `hello` example was ported to use the graphics API layer instead of raw D3D11 API calls. It is still hard-coded to use the D3D11 back-end and the `SLANG_DXBC` target, so more work is needed if we want to actually support multiple APIs in the examples. I also went ahead and implemented an extremely rudimentary set of APIs to abstract over the Windows platform calls that were being made in the example, so that we could potentially run that same example on other platforms. I did *not* port `render-test` to use those APIs, and I also did not implement them for anything but Windows (my assumption is that for most other platforms we would just use SDL2, and require people to ensure it is installed to their machine before building Slang examples).
Diffstat (limited to 'tools/slang-graphics/window.cpp')
-rw-r--r--tools/slang-graphics/window.cpp245
1 files changed, 245 insertions, 0 deletions
diff --git a/tools/slang-graphics/window.cpp b/tools/slang-graphics/window.cpp
new file mode 100644
index 000000000..7aef88c12
--- /dev/null
+++ b/tools/slang-graphics/window.cpp
@@ -0,0 +1,245 @@
+// window.cpp
+#include "window.h"
+#pragma once
+
+#include <stdio.h>
+
+#ifdef _MSC_VER
+#include <stddef.h>
+#if (_MSC_VER < 1900)
+#define snprintf sprintf_s
+#endif
+#endif
+
+
+#if _WIN32
+#include <Windows.h>
+#else
+#error "The slang-graphics library currently only supports Windows platforms"
+#endif
+
+namespace slang_graphics {
+
+#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
+{
+ HINSTANCE instance;
+ int showCommand = SW_SHOWDEFAULT;
+ int resultCode = 0;
+};
+
+/// 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);
+ func(&context);
+ return context.resultCode;
+}
+
+int runWindowsApplication(
+ ApplicationFunc func,
+ void* instance,
+ int showCommand)
+{
+ ApplicationContext context;
+ context.instance = (HINSTANCE) instance;
+ context.showCommand = showCommand;
+ func(&context);
+ return context.resultCode;
+}
+
+struct Window
+{
+ HWND handle;
+};
+
+static LRESULT CALLBACK windowProc(
+ HWND windowHandle,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ // TODO: Actually implement some reasonable logic here.
+ switch (message)
+ {
+ 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 = 0;
+ 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();
+
+ OSString windowTitle(desc.title);
+
+ DWORD windowExtendedStyle = 0;
+ DWORD windowStyle = 0;
+
+ HINSTANCE instance = (HINSTANCE) GetModuleHandle(0);
+
+ HWND windowHandle = CreateWindowExW(
+ windowExtendedStyle,
+ (LPWSTR) getWindowClassAtom(),
+ windowTitle,
+ windowStyle,
+ 0, 0, // x, y
+ desc.width, desc.height,
+ NULL, // parent
+ NULL, // menu
+ instance,
+ window);
+
+ if(!windowHandle)
+ {
+ delete window;
+ return nullptr;
+ }
+
+ window->handle = windowHandle;
+ return window;
+}
+
+void showWindow(Window* window)
+{
+ ShowWindow(window->handle, SW_SHOW);
+}
+
+void* getPlatformWindowHandle(Window* window)
+{
+ return window->handle;
+}
+
+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);
+}
+
+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;
+}
+
+#else
+
+// TODO: put an SDL version here
+
+#endif
+
+} // slang_graphics