boo/lib/win/WindowWin32.cpp

519 lines
15 KiB
C++
Raw Normal View History

2015-11-03 04:19:41 +00:00
#include "Win32Common.hpp"
#include <Windowsx.h>
2015-08-31 03:40:58 +00:00
#include "boo/IWindow.hpp"
#include "boo/IGraphicsContext.hpp"
2015-11-03 04:19:41 +00:00
#include <LogVisor/LogVisor.hpp>
#include "boo/graphicsdev/D3D11.hpp"
#include "boo/graphicsdev/D3D12.hpp"
2015-05-06 00:50:57 +00:00
namespace boo
{
2015-11-03 04:19:41 +00:00
static LogVisor::LogModule Log("WindowWin32");
class WindowWin32;
2015-11-04 00:27:32 +00:00
IGraphicsCommandQueue* _NewD3D12CommandQueue(D3D12Context* ctx, D3D12Context::Window* windowCtx, IGraphicsContext* parent);
IGraphicsCommandQueue* _NewD3D11CommandQueue(D3D11Context* ctx, D3D11Context::Window* windowCtx, IGraphicsContext* parent);
2015-11-03 04:19:41 +00:00
2015-08-31 03:40:58 +00:00
struct GraphicsContextWin32 : IGraphicsContext
{
EGraphicsAPI m_api;
EPixelFormat m_pf;
2015-11-03 04:19:41 +00:00
WindowWin32* m_parentWindow;
D3DAppContext& m_d3dCtx;
ComPtr<IDXGISwapChain1> m_swapChain;
ComPtr<IDXGIOutput> m_output;
IGraphicsCommandQueue* m_commandQueue = nullptr;
IGraphicsDataFactory* m_dataFactory = nullptr;
2015-08-31 03:40:58 +00:00
public:
IWindowCallback* m_callback;
2015-11-03 04:19:41 +00:00
GraphicsContextWin32(EGraphicsAPI api, WindowWin32* parentWindow, D3DAppContext& d3dCtx)
: m_api(api),
m_pf(PF_RGBA8),
m_parentWindow(parentWindow),
m_d3dCtx(d3dCtx)
{
/* Create Swap Chain */
DXGI_SWAP_CHAIN_DESC1 scDesc = {};
scDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
scDesc.SampleDesc.Count = 1;
scDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scDesc.BufferCount = 2;
scDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
scDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
#if _WIN32_WINNT_WIN10
2015-11-04 00:27:32 +00:00
IUnknown* dev;
if (d3dCtx.m_ctx12.m_dev)
{
scDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
dev = static_cast<IUnknown*>(d3dCtx.m_ctx12.m_dev.Get());
}
else
dev = static_cast<IUnknown*>(d3dCtx.m_ctx11.m_dev.Get());
2015-11-03 04:19:41 +00:00
#else
IUnknown* dev = static_cast<IUnknown*>(d3dCtx.m_ctx11.m_dev.Get());
#endif
if (FAILED(d3dCtx.m_dxFactory->CreateSwapChainForHwnd(dev,
parentWindow->m_hwnd, &scDesc, nullptr, nullptr, &m_swapChain)))
Log.report(LogVisor::FatalError, "unable to create swap chain");
if (FAILED(m_swapChain->GetContainingOutput(&m_output)))
Log.report(LogVisor::FatalError, "unable to get DXGI output");
#if _WIN32_WINNT_WIN10
if (d3dCtx.m_ctx12.m_dev)
{
2015-11-04 00:27:32 +00:00
auto insIt = d3dCtx.m_ctx12.m_windows.emplace(std::make_pair(parentWindow, D3D12Context::Window()));
D3D12Context::Window& w = insIt.first->second;
m_swapChain.As<IDXGISwapChain3>(&w.m_swapChain);
m_swapChain->GetBuffer(0, __uuidof(ID3D12Resource), &w.m_fb[0]);
m_swapChain->GetBuffer(1, __uuidof(ID3D12Resource), &w.m_fb[1]);
w.m_backBuf = w.m_swapChain->GetCurrentBackBufferIndex();
D3D12_RESOURCE_DESC resDesc = w.m_fb[0]->GetDesc();
w.width = resDesc.Width;
w.height = resDesc.Height;
2015-11-03 04:19:41 +00:00
m_dataFactory = new D3D12DataFactory(this, &d3dCtx.m_ctx12);
2015-11-04 00:27:32 +00:00
m_commandQueue = _NewD3D12CommandQueue(&d3dCtx.m_ctx12, &w, this);
2015-11-03 04:19:41 +00:00
}
else
#endif
{
2015-11-04 00:27:32 +00:00
auto insIt = d3dCtx.m_ctx11.m_windows.emplace(std::make_pair(parentWindow, D3D11Context::Window()));
D3D11Context::Window& w = insIt.first->second;
ComPtr<ID3D11Texture2D> fbRes;
m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), &fbRes);
D3D11_TEXTURE2D_DESC resDesc;
fbRes->GetDesc(&resDesc);
w.width = resDesc.Width;
w.height = resDesc.Height;
2015-11-03 04:19:41 +00:00
m_dataFactory = new D3D11DataFactory(this, &d3dCtx.m_ctx11);
2015-11-04 00:27:32 +00:00
m_commandQueue = _NewD3D11CommandQueue(&d3dCtx.m_ctx11, &insIt.first->second, this);
2015-11-03 04:19:41 +00:00
}
}
2015-08-31 03:40:58 +00:00
~GraphicsContextWin32()
{
2015-11-04 00:27:32 +00:00
#if _WIN32_WINNT_WIN10
if (m_d3dCtx.m_ctx12.m_dev)
{
m_d3dCtx.m_ctx12.m_windows.erase(m_parentWindow);
}
else
#endif
{
}
2015-08-31 03:40:58 +00:00
}
void _setCallback(IWindowCallback* cb)
{
m_callback = cb;
}
EGraphicsAPI getAPI() const
{
return m_api;
}
EPixelFormat getPixelFormat() const
{
return m_pf;
}
void setPixelFormat(EPixelFormat pf)
{
if (pf > PF_RGBAF32_Z24)
return;
m_pf = pf;
}
2015-11-03 04:19:41 +00:00
void initializeContext() {}
2015-08-31 03:40:58 +00:00
2015-11-03 04:19:41 +00:00
void makeCurrent() {}
2015-08-31 03:40:58 +00:00
2015-11-03 04:19:41 +00:00
void postInit() {}
2015-08-31 03:40:58 +00:00
2015-11-03 04:19:41 +00:00
void present() {}
2015-08-31 03:40:58 +00:00
2015-11-03 04:19:41 +00:00
IGraphicsCommandQueue* getCommandQueue()
2015-08-31 03:40:58 +00:00
{
}
2015-11-03 04:19:41 +00:00
IGraphicsDataFactory* getDataFactory()
2015-08-31 03:40:58 +00:00
{
}
2015-11-03 04:19:41 +00:00
/* Creates a new context on current thread!! Call from client loading thread */
IGraphicsDataFactory* getLoadContextDataFactory()
2015-08-31 03:40:58 +00:00
{
}
};
2015-11-03 04:19:41 +00:00
static void genFrameDefault(MONITORINFO* screen, int& xOut, int& yOut, int& wOut, int& hOut)
{
float width = screen->rcMonitor.right * 2.0 / 3.0;
float height = screen->rcMonitor.bottom * 2.0 / 3.0;
xOut = (screen->rcMonitor.right - width) / 2.0;
yOut = (screen->rcMonitor.bottom - height) / 2.0;
wOut = width;
hOut = height;
}
static uint32_t translateKeysym(WPARAM sym, int& specialSym, int& modifierSym)
{
specialSym = KEY_NONE;
modifierSym = MKEY_NONE;
if (sym >= VK_F1 && sym <= VK_F12)
specialSym = KEY_F1 + sym - VK_F1;
else if (sym == VK_ESCAPE)
specialSym = KEY_ESC;
else if (sym == VK_RETURN)
specialSym = KEY_ENTER;
else if (sym == VK_BACK)
specialSym = KEY_BACKSPACE;
else if (sym == VK_INSERT)
specialSym = KEY_INSERT;
else if (sym == VK_DELETE)
specialSym = KEY_DELETE;
else if (sym == VK_HOME)
specialSym = KEY_HOME;
else if (sym == VK_END)
specialSym = KEY_END;
else if (sym == VK_PRIOR)
specialSym = KEY_PGUP;
else if (sym == VK_NEXT)
specialSym = KEY_PGDOWN;
else if (sym == VK_LEFT)
specialSym = KEY_LEFT;
else if (sym == VK_RIGHT)
specialSym = KEY_RIGHT;
else if (sym == VK_UP)
specialSym = KEY_UP;
else if (sym == VK_DOWN)
specialSym = KEY_DOWN;
else if (sym == VK_LSHIFT || sym == VK_RSHIFT)
modifierSym = MKEY_SHIFT;
else if (sym == VK_LCONTROL || sym == VK_RCONTROL)
modifierSym = MKEY_CTRL;
else if (sym == VK_MENU)
modifierSym = MKEY_ALT;
else
return MapVirtualKey(sym, MAPVK_VK_TO_CHAR);
return 0;
}
static int translateModifiers()
{
int retval = 0;
if (GetKeyState(VK_LSHIFT) & 0x8000 != 0 || GetKeyState(VK_RSHIFT) & 0x8000 != 0)
retval |= MKEY_SHIFT;
if (GetKeyState(VK_LCONTROL) & 0x8000 != 0 || GetKeyState(VK_RCONTROL) & 0x8000 != 0)
retval |= MKEY_CTRL;
if (GetKeyState(VK_MENU) & 0x8000 != 0)
retval |= MKEY_ALT;
return retval;
}
2015-05-06 00:50:57 +00:00
2015-08-31 03:40:58 +00:00
class WindowWin32 : public IWindow
2015-05-06 00:50:57 +00:00
{
2015-11-03 04:19:41 +00:00
friend GraphicsContextWin32;
2015-05-06 00:50:57 +00:00
HWND m_hwnd;
2015-11-03 04:19:41 +00:00
std::unique_ptr<GraphicsContextWin32> m_gfxCtx;
IWindowCallback* m_callback = nullptr;
2015-05-06 00:50:57 +00:00
public:
2015-11-03 04:19:41 +00:00
WindowWin32(const SystemString& title, D3DAppContext& d3dCtx)
2015-05-06 00:50:57 +00:00
{
2015-08-31 03:40:58 +00:00
m_hwnd = CreateWindowW(L"BooWindow", title.c_str(), WS_OVERLAPPEDWINDOW,
2015-05-06 00:50:57 +00:00
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
2015-08-31 03:40:58 +00:00
NULL, NULL, NULL, NULL);
2015-11-03 04:19:41 +00:00
m_gfxCtx.reset(new GraphicsContextWin32(IGraphicsContext::API_D3D11, this, d3dCtx));
2015-05-06 00:50:57 +00:00
}
2015-08-31 03:40:58 +00:00
~WindowWin32()
2015-05-06 00:50:57 +00:00
{
}
void setCallback(IWindowCallback* cb)
{
2015-11-03 04:19:41 +00:00
m_callback = cb;
2015-05-06 00:50:57 +00:00
}
void showWindow()
{
2015-11-03 04:19:41 +00:00
ShowWindow(m_hwnd, SW_SHOW);
2015-05-06 00:50:57 +00:00
}
void hideWindow()
{
2015-11-03 04:19:41 +00:00
ShowWindow(m_hwnd, SW_HIDE);
2015-05-06 00:50:57 +00:00
}
2015-08-31 03:40:58 +00:00
SystemString getTitle()
2015-05-06 00:50:57 +00:00
{
2015-08-31 03:40:58 +00:00
wchar_t title[256];
int c = GetWindowTextW(m_hwnd, title, 256);
return SystemString(title, c);
2015-05-06 00:50:57 +00:00
}
2015-08-31 03:40:58 +00:00
void setTitle(const SystemString& title)
2015-05-06 00:50:57 +00:00
{
2015-08-31 03:40:58 +00:00
SetWindowTextW(m_hwnd, title.c_str());
2015-05-06 00:50:57 +00:00
}
void setWindowFrameDefault()
{
2015-11-03 04:19:41 +00:00
MONITORINFO monInfo;
GetMonitorInfo(MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTOPRIMARY), &monInfo);
int x, y, w, h;
genFrameDefault(&monInfo, x, y, w, h);
setWindowFrame(x, y, w, h);
2015-05-06 00:50:57 +00:00
}
void getWindowFrame(float& xOut, float& yOut, float& wOut, float& hOut) const
{
2015-11-03 04:19:41 +00:00
RECT rct;
GetWindowRect(m_hwnd, &rct);
xOut = rct.left;
yOut = rct.top;
wOut = rct.right;
hOut = rct.bottom;
}
void getWindowFrame(int& xOut, int& yOut, int& wOut, int& hOut) const
{
RECT rct;
GetWindowRect(m_hwnd, &rct);
xOut = rct.left;
yOut = rct.top;
wOut = rct.right;
hOut = rct.bottom;
2015-05-06 00:50:57 +00:00
}
void setWindowFrame(float x, float y, float w, float h)
{
2015-11-03 04:19:41 +00:00
MoveWindow(m_hwnd, x, y, w, h, true);
}
void setWindowFrame(int x, int y, int w, int h)
{
MoveWindow(m_hwnd, x, y, w, h, true);
2015-05-06 00:50:57 +00:00
}
float getVirtualPixelFactor() const
{
2015-08-31 03:40:58 +00:00
return 1.0;
2015-05-06 00:50:57 +00:00
}
bool isFullscreen() const
{
2015-08-31 03:40:58 +00:00
return false;
2015-05-06 00:50:57 +00:00
}
void setFullscreen(bool fs)
{
}
2015-08-31 03:40:58 +00:00
void waitForRetrace()
{
2015-11-03 04:19:41 +00:00
m_gfxCtx->m_output->WaitForVBlank();
2015-08-31 03:40:58 +00:00
}
uintptr_t getPlatformHandle() const
{
return uintptr_t(m_hwnd);
}
2015-11-03 04:19:41 +00:00
void buttonDown(HWNDEvent& e, EMouseButton button)
{
if (m_callback)
{
int x, y, w, h;
getWindowFrame(x, y, w, h);
int modifierMask = translateModifiers();
SWindowCoord coord =
{
{(unsigned)GET_X_LPARAM(e.lParam), (unsigned)GET_Y_LPARAM(e.lParam)},
{(unsigned)GET_X_LPARAM(e.lParam), (unsigned)GET_Y_LPARAM(e.lParam)},
{float(GET_X_LPARAM(e.lParam)) / float(w), float(GET_Y_LPARAM(e.lParam)) / float(h)}
};
m_callback->mouseDown(coord, button, EModifierKey(modifierMask));
}
}
void buttonUp(HWNDEvent& e, EMouseButton button)
{
if (m_callback)
{
int x, y, w, h;
getWindowFrame(x, y, w, h);
int modifierMask = translateModifiers();
SWindowCoord coord =
{
{(unsigned)GET_X_LPARAM(e.lParam), (unsigned)GET_Y_LPARAM(e.lParam)},
{(unsigned)GET_X_LPARAM(e.lParam), (unsigned)GET_Y_LPARAM(e.lParam)},
{float(GET_X_LPARAM(e.lParam)) / float(w), float(GET_Y_LPARAM(e.lParam)) / float(h)}
};
m_callback->mouseUp(coord, button, EModifierKey(modifierMask));
}
}
2015-05-06 00:50:57 +00:00
2015-11-03 04:19:41 +00:00
void _incomingEvent(void* ev)
{
HWNDEvent& e = *static_cast<HWNDEvent*>(ev);
switch (e.uMsg)
{
case WM_SIZE:
{
if (m_callback)
{
SWindowRect rect;
int x, y, w, h;
getWindowFrame(x, y, w, h);
rect.location[0] = x;
rect.location[1] = y;
rect.size[0] = LOWORD(e.lParam);
rect.size[1] = HIWORD(e.lParam);
m_callback->resized(rect);
}
return;
}
case WM_KEYDOWN:
{
if (m_callback)
{
int specialKey;
int modifierKey;
uint32_t charCode = translateKeysym(e.wParam, specialKey, modifierKey);
int modifierMask = translateModifiers();
if (charCode)
m_callback->charKeyDown(charCode, EModifierKey(modifierMask), e.lParam & 0xffff != 0);
else if (specialKey)
m_callback->specialKeyDown(ESpecialKey(specialKey), EModifierKey(modifierMask), e.lParam & 0xffff != 0);
else if (modifierKey)
m_callback->modKeyDown(EModifierKey(modifierKey), e.lParam & 0xffff != 0);
}
return;
}
case WM_KEYUP:
{
if (m_callback)
{
int specialKey;
int modifierKey;
uint32_t charCode = translateKeysym(e.wParam, specialKey, modifierKey);
int modifierMask = translateModifiers();
if (charCode)
m_callback->charKeyUp(charCode, EModifierKey(modifierMask));
else if (specialKey)
m_callback->specialKeyUp(ESpecialKey(specialKey), EModifierKey(modifierMask));
else if (modifierKey)
m_callback->modKeyUp(EModifierKey(modifierKey));
}
return;
}
case WM_LBUTTONDOWN:
{
buttonDown(e, BUTTON_PRIMARY);
return;
}
case WM_LBUTTONUP:
{
buttonUp(e, BUTTON_PRIMARY);
return;
}
case WM_RBUTTONDOWN:
{
buttonDown(e, BUTTON_SECONDARY);
return;
}
case WM_RBUTTONUP:
{
buttonUp(e, BUTTON_SECONDARY);
return;
}
case WM_MBUTTONDOWN:
{
buttonDown(e, BUTTON_MIDDLE);
return;
}
case WM_MBUTTONUP:
{
buttonUp(e, BUTTON_MIDDLE);
return;
}
case WM_XBUTTONDOWN:
{
if (HIWORD(e.wParam) == XBUTTON1)
buttonDown(e, BUTTON_AUX1);
else if (HIWORD(e.wParam) == XBUTTON2)
buttonDown(e, BUTTON_AUX2);
return;
}
case WM_XBUTTONUP:
{
if (HIWORD(e.wParam) == XBUTTON1)
buttonUp(e, BUTTON_AUX1);
else if (HIWORD(e.wParam) == XBUTTON2)
buttonUp(e, BUTTON_AUX2);
return;
}
case WM_MOUSEMOVE:
{
if (m_callback)
{
int x, y, w, h;
getWindowFrame(x, y, w, h);
SWindowCoord coord =
{
{(unsigned)GET_X_LPARAM(e.lParam), (unsigned)GET_Y_LPARAM(e.lParam)},
{(unsigned)GET_X_LPARAM(e.lParam), (unsigned)GET_Y_LPARAM(e.lParam)},
{float(GET_X_LPARAM(e.lParam)) / float(w), float(GET_Y_LPARAM(e.lParam)) / float(h)}
};
m_callback->mouseMove(coord);
}
return;
}
default: break;
}
}
2015-05-06 00:50:57 +00:00
ETouchType getTouchType() const
{
2015-08-31 03:40:58 +00:00
return TOUCH_NONE;
2015-05-06 00:50:57 +00:00
}
2015-11-03 04:19:41 +00:00
IGraphicsCommandQueue* getCommandQueue()
{
return m_gfxCtx->getCommandQueue();
}
IGraphicsDataFactory* getDataFactory()
{
return m_gfxCtx->getDataFactory();
}
/* Creates a new context on current thread!! Call from client loading thread */
IGraphicsDataFactory* getLoadContextDataFactory()
{
return m_gfxCtx->getLoadContextDataFactory();
}
2015-05-06 00:50:57 +00:00
};
2015-11-03 04:19:41 +00:00
IWindow* _WindowWin32New(const SystemString& title, D3DAppContext& d3dCtx)
2015-05-06 00:50:57 +00:00
{
2015-11-03 04:19:41 +00:00
return new WindowWin32(title, d3dCtx);
2015-05-06 00:50:57 +00:00
}
}