diff --git a/src/xenia/core.h b/src/xenia/core.h index b06653a0b..0aab007fb 100644 --- a/src/xenia/core.h +++ b/src/xenia/core.h @@ -18,7 +18,13 @@ #include #include #include +#include #include #include +#include + +#if XE_PLATFORM(WIN32) +#include +#endif // WIN32 #endif // XENIA_CORE_H_ diff --git a/src/xenia/core/run_loop.h b/src/xenia/core/run_loop.h new file mode 100644 index 000000000..7df516726 --- /dev/null +++ b/src/xenia/core/run_loop.h @@ -0,0 +1,33 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_CORE_RUN_LOOP_H_ +#define XENIA_CORE_RUN_LOOP_H_ + +#include +#include + + +struct xe_run_loop; +typedef struct xe_run_loop* xe_run_loop_ref; + + +xe_run_loop_ref xe_run_loop_create(); +xe_run_loop_ref xe_run_loop_retain(xe_run_loop_ref run_loop); +void xe_run_loop_release(xe_run_loop_ref run_loop); + +int xe_run_loop_pump(xe_run_loop_ref run_loop); +void xe_run_loop_quit(xe_run_loop_ref run_loop); + +typedef void (*xe_run_loop_callback)(void* data); +void xe_run_loop_call(xe_run_loop_ref run_loop, + xe_run_loop_callback callback, void* data); + + +#endif // XENIA_CORE_RUN_LOOP_H_ diff --git a/src/xenia/core/run_loop_win.cc b/src/xenia/core/run_loop_win.cc new file mode 100644 index 000000000..bd00b3674 --- /dev/null +++ b/src/xenia/core/run_loop_win.cc @@ -0,0 +1,83 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include + +#include +#include + + +typedef struct xe_run_loop { + xe_ref_t ref; +} xe_run_loop_t; + + +#define WM_XE_RUN_LOOP_QUIT (WM_APP + 0x100) +#define WM_XE_RUN_LOOP_CALL (WM_APP + 0x101) + +typedef struct xe_run_loop_call { + xe_run_loop_callback callback; + void* data; +} xe_run_loop_call_t; + + +xe_run_loop_ref xe_run_loop_create() { + xe_run_loop_ref run_loop = (xe_run_loop_ref)xe_calloc(sizeof(xe_run_loop_t)); + xe_ref_init((xe_ref)run_loop); + return run_loop; +} + +void xe_run_loop_dealloc(xe_run_loop_ref run_loop) { +} + +xe_run_loop_ref xe_run_loop_retain(xe_run_loop_ref run_loop) { + xe_ref_retain((xe_ref)run_loop); + return run_loop; +} + +void xe_run_loop_release(xe_run_loop_ref run_loop) { + xe_ref_release((xe_ref)run_loop, (xe_ref_dealloc_t)xe_run_loop_dealloc); +} + +int xe_run_loop_pump(xe_run_loop_ref run_loop) { + MSG msg; + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + switch (msg.message) { + case WM_XE_RUN_LOOP_CALL: + if (msg.wParam == (WPARAM)run_loop) { + xe_run_loop_call_t* call = (xe_run_loop_call_t*)msg.lParam; + call->callback(call->data); + xe_free(call); + } + break; + case WM_XE_RUN_LOOP_QUIT: + if (msg.lParam == (WPARAM)run_loop) { + // Done! + return 1; + } + break; + } + } + return 0; +} + +void xe_run_loop_quit(xe_run_loop_ref run_loop) { + PostMessage(NULL, WM_XE_RUN_LOOP_QUIT, 0, (WPARAM)run_loop); +} + +void xe_run_loop_call(xe_run_loop_ref run_loop, + xe_run_loop_callback callback, void* data) { + xe_run_loop_call_t* call = + (xe_run_loop_call_t*)xe_calloc(sizeof(xe_run_loop_call_t)); + call->callback = callback; + call->data = data; + PostMessage(NULL, WM_XE_RUN_LOOP_CALL, (WPARAM)run_loop, (LPARAM)call); +} diff --git a/src/xenia/core/sources.gypi b/src/xenia/core/sources.gypi index 65c0051e4..6854fb4fe 100644 --- a/src/xenia/core/sources.gypi +++ b/src/xenia/core/sources.gypi @@ -12,9 +12,12 @@ 'path.h', 'ref.cc', 'ref.h', + 'run_loop.h', 'socket.h', 'thread.cc', 'thread.h', + 'window.cc', + 'window.h', ], 'conditions': [ @@ -42,7 +45,10 @@ 'mutex_win.cc', 'pal_win.cc', 'path_win.cc', + 'run_loop_win.cc', 'socket_win.cc', + 'win32_window.cc', + 'win32_window.h', ], }], ], diff --git a/src/xenia/core/win32_window.cc b/src/xenia/core/win32_window.cc new file mode 100644 index 000000000..41210c1c2 --- /dev/null +++ b/src/xenia/core/win32_window.cc @@ -0,0 +1,244 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include + +#include +#include + + +using namespace xe; +using namespace xe::core; + + +namespace { + +static LRESULT CALLBACK Win32WindowWndProc( + HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + Win32Window* window = 0; + if (message == WM_NCCREATE) { + LPCREATESTRUCT create_struct = (LPCREATESTRUCT)lParam; + window = (Win32Window*)create_struct->lpCreateParams; + SetWindowLongPtr(hWnd, GWLP_USERDATA, (__int3264)(LONG_PTR)window); + } else { + window = (Win32Window*)GetWindowLongPtr(hWnd, GWLP_USERDATA); + } + if (window) { + return window->WndProc(hWnd, message, wParam, lParam); + } else { + return DefWindowProc(hWnd, message, wParam, lParam); + } +} + +} + + +Win32Window::Win32Window(xe_run_loop_ref run_loop) : + handle_(0), + Window(run_loop) { + Create(); +} + +Win32Window::~Win32Window() { + if (handle_) { + CloseWindow(handle_); + } +} + +void Win32Window::Create() { + HINSTANCE hInstance = GetModuleHandle(NULL); + + width_ = 1280; + height_ = 720; + + WNDCLASSEX wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = Win32WindowWndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = NULL; // LoadIcon(hInstance, (LPCTSTR)IDI_TUTORIAL1); + wcex.hIconSm = NULL; // LoadIcon(hInstance, (LPCTSTR)IDI_TUTORIAL1); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 ); + wcex.lpszMenuName = NULL; + wcex.lpszClassName = L"XeniaWindowClass"; + if (!RegisterClassEx(&wcex)) { + XELOGE("RegisterClassEx failed"); + exit(1); + return; + } + + // Setup initial size. + DWORD window_style = WS_OVERLAPPEDWINDOW; + DWORD window_ex_style = WS_EX_APPWINDOW; + RECT rc = { + 0, 0, + width_, height_ + }; + AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); + + // Create window. + handle_ = CreateWindowEx( + window_ex_style, + L"XeniaWindowClass", + L"Xenia", + window_style, + CW_USEDEFAULT, CW_USEDEFAULT, + rc.right - rc.left, rc.bottom - rc.top, + NULL, + NULL, + hInstance, + this); + if (!handle_) { + XELOGE("CreateWindow failed"); + exit(1); + return; + } + + // Disable flicks. + ATOM atom = GlobalAddAtom(L"MicrosoftTabletPenServiceProperty"); + const DWORD_PTR dwHwndTabletProperty = + TABLET_DISABLE_PRESSANDHOLD | // disables press and hold (right-click) gesture + TABLET_DISABLE_PENTAPFEEDBACK | // disables UI feedback on pen up (waves) + TABLET_DISABLE_PENBARRELFEEDBACK | // disables UI feedback on pen button down (circle) + TABLET_DISABLE_FLICKS | // disables pen flicks (back, forward, drag down, drag up) + TABLET_DISABLE_TOUCHSWITCH | + TABLET_DISABLE_SMOOTHSCROLLING | + TABLET_DISABLE_TOUCHUIFORCEON | + TABLET_ENABLE_MULTITOUCHDATA; + SetProp( + handle_, + L"MicrosoftTabletPenServiceProperty", + reinterpret_cast(dwHwndTabletProperty)); + GlobalDeleteAtom(atom); + + // Enable DWM elevation. + EnableMMCSS(); + + ShowWindow(handle_, SW_SHOWNORMAL); + UpdateWindow(handle_); +} + +void Win32Window::EnableMMCSS() { + HMODULE hLibrary = LoadLibrary(L"DWMAPI.DLL"); + if (!hLibrary) { + return; + } + + typedef HRESULT (__stdcall *PDwmEnableMMCSS)(BOOL); + PDwmEnableMMCSS pDwmEnableMMCSS = + (PDwmEnableMMCSS)GetProcAddress( + hLibrary, "DwmEnableMMCSS"); + if (pDwmEnableMMCSS) { + pDwmEnableMMCSS(TRUE); + } + + typedef HRESULT (__stdcall *PDwmSetPresentParameters)(HWND, DWM_PRESENT_PARAMETERS*); + PDwmSetPresentParameters pDwmSetPresentParameters = + (PDwmSetPresentParameters)GetProcAddress( + hLibrary, "DwmSetPresentParameters"); + if (pDwmSetPresentParameters) { + DWM_PRESENT_PARAMETERS pp; + memset(&pp, 0, sizeof(DWM_PRESENT_PARAMETERS)); + pp.cbSize = sizeof(DWM_PRESENT_PARAMETERS); + pp.fQueue = FALSE; + pp.cBuffer = 2; + pp.fUseSourceRate = FALSE; + pp.cRefreshesPerFrame = 1; + pp.eSampling = DWM_SOURCE_FRAME_SAMPLING_POINT; + pDwmSetPresentParameters(handle_, &pp); + } + + FreeLibrary( hLibrary ); +} + +void Win32Window::set_title(const xechar_t* title) { + XEIGNORE(SetWindowText(handle_, title)); +} + +void Win32Window::Resize(uint32_t width, uint32_t height) { + if (width == width_ && height == height_) { + return; + } + width_ = width; + height_ = height; + + RECT rc = { + 0, 0, + width_, height_ + }; + AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); + // TODO(benvanik): center. + MoveWindow(handle_, 0, 0, rc.right - rc.left, rc.bottom - rc.top, TRUE); + + OnResize(width_, height_); +} + +void Win32Window::ShowError(const xechar_t* message) { + XEIGNORE(MessageBox(handle_, message, L"Xenia Error", MB_ICONERROR | MB_OK)); +} + +LRESULT Win32Window::WndProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_NCCREATE: + handle_ = hWnd; + return DefWindowProc(hWnd, message, wParam, lParam); + case WM_ACTIVATEAPP: + if (wParam) { + // Made active. + } else { + // Made inactive. + } + return DefWindowProc(hWnd, message, wParam, lParam); + case WM_CLOSE: + OnClose(); + return DefWindowProc(hWnd, message, wParam, lParam); + case WM_DESTROY: + PostQuitMessage(0); + return 0; + + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hWnd, &ps); + EndPaint(hWnd, &ps); + } + return 0; + case WM_ERASEBKGND: + return 0; // ignore + case WM_DISPLAYCHANGE: + return DefWindowProc(hWnd, message, wParam, lParam); + + case WM_MOVE: + return DefWindowProc(hWnd, message, wParam, lParam); + case WM_SIZE: + { + RECT frame; + GetClientRect(handle_, &frame); + OnResize(frame.right - frame.left, frame.bottom - frame.top); + } + return DefWindowProc(hWnd, message, wParam, lParam); + + case WM_TABLET_QUERYSYSTEMGESTURESTATUS: + return + TABLET_DISABLE_PRESSANDHOLD | // disables press and hold (right-click) gesture + TABLET_DISABLE_PENTAPFEEDBACK | // disables UI feedback on pen up (waves) + TABLET_DISABLE_PENBARRELFEEDBACK | // disables UI feedback on pen button down (circle) + TABLET_DISABLE_FLICKS | // disables pen flicks (back, forward, drag down, drag up) + TABLET_DISABLE_TOUCHSWITCH | + TABLET_DISABLE_SMOOTHSCROLLING | + TABLET_DISABLE_TOUCHUIFORCEON | + TABLET_ENABLE_MULTITOUCHDATA; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } +} diff --git a/src/xenia/core/win32_window.h b/src/xenia/core/win32_window.h new file mode 100644 index 000000000..a5b038ee0 --- /dev/null +++ b/src/xenia/core/win32_window.h @@ -0,0 +1,49 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_CORE_WIN32_WINDOW_H_ +#define XENIA_CORE_WIN32_WINDOW_H_ + +#include +#include + + +namespace xe { +namespace core { + + +class Win32Window : public Window { +public: + Win32Window(xe_run_loop_ref run_loop); + virtual ~Win32Window(); + + HWND handle() const { return handle_; } + + virtual void set_title(const xechar_t* title); + + virtual void Resize(uint32_t width, uint32_t height); + + virtual void ShowError(const xechar_t* message); + + LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + +protected: + HWND handle_; + +private: + void Create(); + void EnableMMCSS(); +}; + + +} // namespace core +} // namespace xe + + +#endif // XENIA_CORE_WIN32_WINDOW_H_ diff --git a/src/xenia/core/window.cc b/src/xenia/core/window.cc new file mode 100644 index 000000000..b259ea10e --- /dev/null +++ b/src/xenia/core/window.cc @@ -0,0 +1,23 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include + + +using namespace xe; +using namespace xe::core; + + +Window::Window(xe_run_loop_ref run_loop) { + run_loop_ = xe_run_loop_retain(run_loop); +} + +Window::~Window() { + xe_run_loop_release(run_loop_); +} diff --git a/src/xenia/core/window.h b/src/xenia/core/window.h new file mode 100644 index 000000000..535f2d82b --- /dev/null +++ b/src/xenia/core/window.h @@ -0,0 +1,51 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_CORE_WINDOW_H_ +#define XENIA_CORE_WINDOW_H_ + +#include +#include +#include +#include + + +namespace xe { +namespace core { + + +class Window { +public: + Window(xe_run_loop_ref run_loop); + virtual ~Window(); + + virtual void set_title(const xechar_t* title) = 0; + + uint32_t width() const { return width_; } + uint32_t height() const { return height_; } + virtual void Resize(uint32_t width, uint32_t height) = 0; + + virtual void ShowError(const xechar_t* message) = 0; + +protected: + virtual void OnResize(uint32_t width, uint32_t height) {} + virtual void OnClose() {} + + xe_run_loop_ref run_loop_; + + uint32_t width_; + uint32_t height_; +}; + + +} // namespace core +} // namespace xe + + +#endif // XENIA_CORE_WINDOW_H_ diff --git a/src/xenia/gpu/d3d11/d3d11_graphics_driver.cc b/src/xenia/gpu/d3d11/d3d11_graphics_driver.cc index 4d8021e07..d17889237 100644 --- a/src/xenia/gpu/d3d11/d3d11_graphics_driver.cc +++ b/src/xenia/gpu/d3d11/d3d11_graphics_driver.cc @@ -19,11 +19,15 @@ using namespace xe::gpu::d3d11; using namespace xe::gpu::xenos; -D3D11GraphicsDriver::D3D11GraphicsDriver(xe_memory_ref memory) : +D3D11GraphicsDriver::D3D11GraphicsDriver( + xe_memory_ref memory, ID3D11Device* device) : GraphicsDriver(memory) { + device_ = device; + device_->AddRef(); } D3D11GraphicsDriver::~D3D11GraphicsDriver() { + device_->Release(); } void D3D11GraphicsDriver::Initialize() { diff --git a/src/xenia/gpu/d3d11/d3d11_graphics_driver.h b/src/xenia/gpu/d3d11/d3d11_graphics_driver.h index 12529dbed..b14f76791 100644 --- a/src/xenia/gpu/d3d11/d3d11_graphics_driver.h +++ b/src/xenia/gpu/d3d11/d3d11_graphics_driver.h @@ -16,6 +16,8 @@ #include #include +#include + namespace xe { namespace gpu { @@ -24,7 +26,7 @@ namespace d3d11 { class D3D11GraphicsDriver : public GraphicsDriver { public: - D3D11GraphicsDriver(xe_memory_ref memory); + D3D11GraphicsDriver(xe_memory_ref memory, ID3D11Device* device); virtual ~D3D11GraphicsDriver(); virtual void Initialize(); @@ -40,7 +42,8 @@ public: xenos::XE_GPU_PRIMITIVE_TYPE prim_type, uint32_t index_count); -protected: +private: + ID3D11Device* device_; }; diff --git a/src/xenia/gpu/d3d11/d3d11_graphics_system.cc b/src/xenia/gpu/d3d11/d3d11_graphics_system.cc index 210ea7bc4..2aeb79607 100644 --- a/src/xenia/gpu/d3d11/d3d11_graphics_system.cc +++ b/src/xenia/gpu/d3d11/d3d11_graphics_system.cc @@ -11,6 +11,7 @@ #include #include +#include using namespace xe; @@ -18,14 +19,120 @@ using namespace xe::gpu; using namespace xe::gpu::d3d11; +namespace { + +} + + D3D11GraphicsSystem::D3D11GraphicsSystem(const CreationParams* params) : + window_(0), dxgi_factory_(0), device_(0), GraphicsSystem(params) { } D3D11GraphicsSystem::~D3D11GraphicsSystem() { + if (device_) device_->Release(); + if (dxgi_factory_) dxgi_factory_->Release(); + delete window_; } void D3D11GraphicsSystem::Initialize() { + GraphicsSystem::Initialize(); + + // Create DXGI factory so we can get a swap chain/etc. + HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), + (void**)&dxgi_factory_); + if (FAILED(hr)) { + XELOGE("CreateDXGIFactory1 failed with %.8X", hr); + exit(1); + return; + } + + // Find the best adapter. + // TODO(benvanik): enable nvperfhud/etc. + IDXGIAdapter1* adapter = 0; + UINT n = 0; + while (dxgi_factory_->EnumAdapters1(n, &adapter) != DXGI_ERROR_NOT_FOUND) { + DXGI_ADAPTER_DESC1 desc; + adapter->GetDesc1(&desc); + adapter->Release(); + n++; + } + // Just go with the default for now. + adapter = 0; + + D3D_DRIVER_TYPE driver_type = + adapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE; + + UINT flags = 0; + // TODO(benvanik): runtime flag + flags |= D3D11_CREATE_DEVICE_DEBUG; + + // Feature level 11.0+ only. + D3D_FEATURE_LEVEL feature_levels[] = { + D3D_FEATURE_LEVEL_11_0, + }; + + // Create device. + D3D_FEATURE_LEVEL actual_feature_level; + ID3D11DeviceContext* immediate_context; + hr = D3D11CreateDevice( + adapter, + driver_type, + 0, // software driver HMODULE + flags, + feature_levels, + XECOUNT(feature_levels), + D3D11_SDK_VERSION, + &device_, + &actual_feature_level, + &immediate_context); + if (adapter) { + adapter->Release(); + adapter = 0; + } + if (immediate_context) { + immediate_context->Release(); + immediate_context = 0; + } + if (FAILED(hr)) { + XELOGE("D3D11CreateDevice failed with %.8X", hr); + exit(1); + return; + } + + // Create the window. + // This will pump through the run-loop and and be where our swapping + // will take place. + XEASSERTNULL(window_); + window_ = new D3D11Window(run_loop_, dxgi_factory_, device_); + window_->set_title(XETEXT("Xenia D3D11")); + + // Listen for alt-enter/etc. + dxgi_factory_->MakeWindowAssociation(window_->handle(), 0); + + // Create the driver. + // This runs in the worker thread and builds command lines to present + // in the window. XEASSERTNULL(driver_); - driver_ = new D3D11GraphicsDriver(memory_); + driver_ = new D3D11GraphicsDriver(memory_, device_); + + // Initial vsync kick. + DispatchInterruptCallback(); +} + +void D3D11GraphicsSystem::Pump() { + if (swap_pending_) { + swap_pending_ = false; + + // Swap window. + // If we are set to vsync this will block. + window_->Swap(); + + // Dispatch interrupt callback to let the game know it can keep drawing. + DispatchInterruptCallback(); + } +} + +void D3D11GraphicsSystem::Shutdown() { + GraphicsSystem::Shutdown(); } diff --git a/src/xenia/gpu/d3d11/d3d11_graphics_system.h b/src/xenia/gpu/d3d11/d3d11_graphics_system.h index 6684c7960..0bb8a50d1 100644 --- a/src/xenia/gpu/d3d11/d3d11_graphics_system.h +++ b/src/xenia/gpu/d3d11/d3d11_graphics_system.h @@ -15,11 +15,15 @@ #include #include +#include + namespace xe { namespace gpu { namespace d3d11 { +class D3D11Window; + GraphicsSystem* Create(const CreationParams* params); @@ -29,7 +33,15 @@ public: D3D11GraphicsSystem(const CreationParams* params); virtual ~D3D11GraphicsSystem(); +protected: virtual void Initialize(); + virtual void Pump(); + virtual void Shutdown(); + +private: + IDXGIFactory1* dxgi_factory_; + ID3D11Device* device_; + D3D11Window* window_; }; diff --git a/src/xenia/gpu/d3d11/d3d11_shader.cc b/src/xenia/gpu/d3d11/d3d11_shader.cc new file mode 100644 index 000000000..ca51ec0aa --- /dev/null +++ b/src/xenia/gpu/d3d11/d3d11_shader.cc @@ -0,0 +1,22 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include + + +using namespace xe; +using namespace xe::gpu; +using namespace xe::gpu::d3d11; + + +D3D11Shader::D3D11Shader() { +} + +D3D11Shader::~D3D11Shader() { +} diff --git a/src/xenia/gpu/d3d11/d3d11_shader.h b/src/xenia/gpu/d3d11/d3d11_shader.h new file mode 100644 index 000000000..170e156fe --- /dev/null +++ b/src/xenia/gpu/d3d11/d3d11_shader.h @@ -0,0 +1,35 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_GPU_D3D11_D3D11_SHADER_H_ +#define XENIA_GPU_D3D11_D3D11_SHADER_H_ + +#include + +#include + + +namespace xe { +namespace gpu { +namespace d3d11 { + + +class D3D11Shader : public Shader { +public: + D3D11Shader(); + virtual ~D3D11Shader(); +}; + + +} // namespace d3d11 +} // namespace gpu +} // namespace xe + + +#endif // XENIA_GPU_D3D11_D3D11_SHADER_H_ diff --git a/src/xenia/gpu/d3d11/d3d11_shader_cache.cc b/src/xenia/gpu/d3d11/d3d11_shader_cache.cc new file mode 100644 index 000000000..da7d021ee --- /dev/null +++ b/src/xenia/gpu/d3d11/d3d11_shader_cache.cc @@ -0,0 +1,22 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include + + +using namespace xe; +using namespace xe::gpu; +using namespace xe::gpu::d3d11; + + +D3D11ShaderCache::D3D11ShaderCache() { +} + +D3D11ShaderCache::~D3D11ShaderCache() { +} diff --git a/src/xenia/gpu/d3d11/d3d11_shader_cache.h b/src/xenia/gpu/d3d11/d3d11_shader_cache.h new file mode 100644 index 000000000..c74ac133e --- /dev/null +++ b/src/xenia/gpu/d3d11/d3d11_shader_cache.h @@ -0,0 +1,35 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_GPU_D3D11_D3D11_SHADER_CACHE_H_ +#define XENIA_GPU_D3D11_D3D11_SHADER_CACHE_H_ + +#include + +#include + + +namespace xe { +namespace gpu { +namespace d3d11 { + + +class D3D11ShaderCache : public ShaderCache { +public: + D3D11ShaderCache(); + virtual ~D3D11ShaderCache(); +}; + + +} // namespace d3d11 +} // namespace gpu +} // namespace xe + + +#endif // XENIA_GPU_D3D11_D3D11_SHADER_CACHE_H_ diff --git a/src/xenia/gpu/d3d11/d3d11_window.cc b/src/xenia/gpu/d3d11/d3d11_window.cc new file mode 100644 index 000000000..18ec13e4a --- /dev/null +++ b/src/xenia/gpu/d3d11/d3d11_window.cc @@ -0,0 +1,124 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include + + +using namespace xe; +using namespace xe::core; +using namespace xe::gpu; +using namespace xe::gpu::d3d11; + + +D3D11Window::D3D11Window( + xe_run_loop_ref run_loop, + IDXGIFactory1* dxgi_factory, ID3D11Device* device) : + Win32Window(run_loop) { + dxgi_factory_ = dxgi_factory; + dxgi_factory_->AddRef(); + device_ = device; + device_->AddRef(); + device_->GetImmediateContext(&context_); + + swap_chain_ = 0; + render_target_view_ = 0; + + // Setup swap chain. + DXGI_SWAP_CHAIN_DESC desc; + xe_zero_struct(&desc, sizeof(desc)); + desc.OutputWindow = handle_; + desc.Windowed = TRUE; + desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + + // Setup buffers. + desc.BufferCount = 2; + desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + desc.BufferDesc.Width = width_; + desc.BufferDesc.Height = height_; + desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.BufferDesc.RefreshRate.Numerator = 60; + desc.BufferDesc.RefreshRate.Denominator = 1; + + // Disable multisampling. + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + + // Create! + HRESULT hr = dxgi_factory_->CreateSwapChain( + device_, + &desc, + &swap_chain_); + if (FAILED(hr)) { + XELOGE("CreateSwapChain failed with %.8X", hr); + exit(1); + return; + } + + // Create a render target view to draw into. + ID3D11Texture2D* back_buffer = 0; + hr = swap_chain_->GetBuffer( + 0, __uuidof(ID3D11Texture2D), (void**)&back_buffer); + if (FAILED(hr)) { + XELOGE("GetBuffer (back_buffer) failed with %.8X", hr); + exit(1); + return; + } + hr = device_->CreateRenderTargetView( + back_buffer, NULL, &render_target_view_); + back_buffer->Release(); + if (FAILED(hr)) { + XELOGE("CreateRenderTargetView (back_buffer) failed with %.8X", hr); + exit(1); + return; + } + context_->OMSetRenderTargets(1, &render_target_view_, NULL); +} + +D3D11Window::~D3D11Window() { + if (render_target_view_) render_target_view_->Release(); + if (context_) { + context_->ClearState(); + context_->Release(); + } + if (swap_chain_) swap_chain_->Release(); + if (device_) device_->Release(); + if (dxgi_factory_) dxgi_factory_->Release(); +} + +void D3D11Window::Swap() { + // Setup the viewport. + //D3D11_VIEWPORT viewport; + //viewport.MinDepth = 0.0f; + //viewport.MaxDepth = 1.0f; + //viewport.TopLeftX = 0; + //viewport.TopLeftY = 0; + //viewport.Width = (FLOAT)width_; + //viewport.Height = (FLOAT)height_; + //context_->RSSetViewports(1, &viewport); + + // Swap buffers. + // TODO(benvanik): control vsync with flag. + bool vsync = true; + HRESULT hr = swap_chain_->Present(vsync ? 1 : 0, 0); + if (FAILED(hr)) { + XELOGE("Present failed with %.8X", hr); + } +} + +void D3D11Window::OnResize(uint32_t width, uint32_t height) { + Win32Window::OnResize(width, height); + + // TODO(benvanik): resize swap buffers? +} + +void D3D11Window::OnClose() { + // We are the master window - if they close us, quit! + xe_run_loop_quit(run_loop_); +} diff --git a/src/xenia/gpu/d3d11/d3d11_window.h b/src/xenia/gpu/d3d11/d3d11_window.h new file mode 100644 index 000000000..a90f1643e --- /dev/null +++ b/src/xenia/gpu/d3d11/d3d11_window.h @@ -0,0 +1,50 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_GPU_D3D11_D3D11_WINDOW_H_ +#define XENIA_GPU_D3D11_D3D11_WINDOW_H_ + +#include + +#include + + +namespace xe { +namespace gpu { +namespace d3d11 { + + +class D3D11Window : public xe::core::Win32Window { +public: + D3D11Window( + xe_run_loop_ref run_loop, + IDXGIFactory1* dxgi_factory, ID3D11Device* device); + virtual ~D3D11Window(); + + void Swap(); + +protected: + virtual void OnResize(uint32_t width, uint32_t height); + virtual void OnClose(); + +private: + IDXGIFactory1* dxgi_factory_; + ID3D11Device* device_; + IDXGISwapChain* swap_chain_; + ID3D11DeviceContext* context_; + ID3D11RenderTargetView* render_target_view_; +}; + + +} // namespace d3d11 +} // namespace gpu +} // namespace xe + + +#endif // XENIA_GPU_D3D11_D3D11_WINDOW_H_ diff --git a/src/xenia/gpu/d3d11/sources.gypi b/src/xenia/gpu/d3d11/sources.gypi index 4a87b9e54..b6a9052b7 100644 --- a/src/xenia/gpu/d3d11/sources.gypi +++ b/src/xenia/gpu/d3d11/sources.gypi @@ -8,5 +8,11 @@ 'd3d11_graphics_driver.h', 'd3d11_graphics_system.cc', 'd3d11_graphics_system.h', + 'd3d11_shader.cc', + 'd3d11_shader.h', + 'd3d11_shader_cache.cc', + 'd3d11_shader_cache.h', + 'd3d11_window.cc', + 'd3d11_window.h', ], } diff --git a/src/xenia/gpu/graphics_system.cc b/src/xenia/gpu/graphics_system.cc index 4ee216da4..cf2ea7be4 100644 --- a/src/xenia/gpu/graphics_system.cc +++ b/src/xenia/gpu/graphics_system.cc @@ -21,19 +21,39 @@ using namespace xe::gpu::xenos; GraphicsSystem::GraphicsSystem(const CreationParams* params) : - interrupt_callback_(0), interrupt_callback_data_(0) { + interrupt_callback_(0), interrupt_callback_data_(0), + swap_pending_(false) { memory_ = xe_memory_retain(params->memory); worker_ = new RingBufferWorker(memory_); // Set during Initialize(); driver_ = 0; + + // Create the run loop used for any windows/etc. + // This must be done on the thread we create the driver. + run_loop_ = xe_run_loop_create(); + + // Create worker thread. + // This will initialize the graphics system. + // Init needs to happen there so that any thread-local stuff + // is created on the right thread. + running_ = true; + thread_ = xe_thread_create( + "GraphicsSystem", + (xe_thread_callback)ThreadStartThunk, this); + xe_thread_start(thread_); } GraphicsSystem::~GraphicsSystem() { + // TODO(benvanik): thread join. + running_ = false; + xe_thread_release(thread_); + // TODO(benvanik): worker join/etc. delete worker_; + xe_run_loop_release(run_loop_); xe_memory_release(memory_); } @@ -49,6 +69,44 @@ void GraphicsSystem::set_processor(shared_ptr processor) { processor_ = processor; } +void GraphicsSystem::ThreadStart() { + xe_run_loop_ref run_loop = xe_run_loop_retain(run_loop_); + + // Initialize driver and ringbuffer. + Initialize(); + XEASSERTNOTNULL(driver_); + + // Main run loop. + while (running_) { + // Peek main run loop. + if (xe_run_loop_pump(run_loop)) { + break; + } + if (!running_) { + break; + } + + // Pump worker. + worker_->Pump(); + + // Pump graphics system. + Pump(); + } + running_ = false; + + Shutdown(); + + xe_run_loop_release(run_loop); + + // TODO(benvanik): call module API to kill? +} + +void GraphicsSystem::Initialize() { +} + +void GraphicsSystem::Shutdown() { +} + void GraphicsSystem::SetInterruptCallback(uint32_t callback, uint32_t user_data) { interrupt_callback_ = callback; diff --git a/src/xenia/gpu/graphics_system.h b/src/xenia/gpu/graphics_system.h index 3c3bf58be..6491461f8 100644 --- a/src/xenia/gpu/graphics_system.h +++ b/src/xenia/gpu/graphics_system.h @@ -29,9 +29,11 @@ class RingBufferWorker; class CreationParams { public: - xe_memory_ref memory; + xe_memory_ref memory; - CreationParams() : memory(NULL) {} + CreationParams() : + memory(0) { + } }; @@ -43,7 +45,6 @@ public: shared_ptr processor(); void set_processor(shared_ptr processor); - virtual void Initialize() = 0; void SetInterruptCallback(uint32_t callback, uint32_t user_data); void InitializeRingBuffer(uint32_t ptr, uint32_t page_count); void EnableReadPointerWriteBack(uint32_t ptr, uint32_t block_size); @@ -52,6 +53,8 @@ public: virtual void WriteRegister(uint32_t r, uint64_t value); void DispatchInterruptCallback(); + bool swap_pending() const { return swap_pending_; } + void set_swap_pending(bool value) { swap_pending_ = value; } public: // TODO(benvanik): have an HasRegisterHandler() so that the JIT can @@ -64,17 +67,33 @@ public: this_ptr->WriteRegister(r, value); } +protected: + virtual void Initialize(); + virtual void Pump() = 0; + virtual void Shutdown(); + +private: + static void ThreadStartThunk(GraphicsSystem* this_ptr) { + this_ptr->ThreadStart(); + } + void ThreadStart(); + protected: GraphicsSystem(const CreationParams* params); xe_memory_ref memory_; shared_ptr processor_; + + xe_run_loop_ref run_loop_; + xe_thread_ref thread_; + bool running_; GraphicsDriver* driver_; RingBufferWorker* worker_; uint32_t interrupt_callback_; uint32_t interrupt_callback_data_; + bool swap_pending_; }; diff --git a/src/xenia/gpu/nop/nop_graphics_system.cc b/src/xenia/gpu/nop/nop_graphics_system.cc index 010e04067..b96ab2bd3 100644 --- a/src/xenia/gpu/nop/nop_graphics_system.cc +++ b/src/xenia/gpu/nop/nop_graphics_system.cc @@ -34,15 +34,11 @@ NopGraphicsSystem::NopGraphicsSystem(const CreationParams* params) : } NopGraphicsSystem::~NopGraphicsSystem() { - if (vsync_timer_) { - DeleteTimerQueueTimer(timer_queue_, vsync_timer_, NULL); - } - if (timer_queue_) { - DeleteTimerQueueEx(timer_queue_, NULL); - } } void NopGraphicsSystem::Initialize() { + GraphicsSystem::Initialize(); + XEASSERTNULL(driver_); driver_ = new NopGraphicsDriver(memory_); @@ -59,3 +55,17 @@ void NopGraphicsSystem::Initialize() { 100, WT_EXECUTEINTIMERTHREAD); } + +void NopGraphicsSystem::Pump() { +} + +void NopGraphicsSystem::Shutdown() { + if (vsync_timer_) { + DeleteTimerQueueTimer(timer_queue_, vsync_timer_, NULL); + } + if (timer_queue_) { + DeleteTimerQueueEx(timer_queue_, NULL); + } + + GraphicsSystem::Shutdown(); +} diff --git a/src/xenia/gpu/nop/nop_graphics_system.h b/src/xenia/gpu/nop/nop_graphics_system.h index 45dd05b7e..c0f6ac614 100644 --- a/src/xenia/gpu/nop/nop_graphics_system.h +++ b/src/xenia/gpu/nop/nop_graphics_system.h @@ -26,7 +26,10 @@ public: NopGraphicsSystem(const CreationParams* params); virtual ~NopGraphicsSystem(); +protected: virtual void Initialize(); + virtual void Pump(); + virtual void Shutdown(); private: HANDLE timer_queue_; diff --git a/src/xenia/gpu/ring_buffer_worker.cc b/src/xenia/gpu/ring_buffer_worker.cc index 15fefe1dd..669102048 100644 --- a/src/xenia/gpu/ring_buffer_worker.cc +++ b/src/xenia/gpu/ring_buffer_worker.cc @@ -21,20 +21,12 @@ using namespace xe::gpu::xenos; RingBufferWorker::RingBufferWorker(xe_memory_ref memory) : memory_(memory), driver_(0) { - running_ = true; write_ptr_index_event_ = CreateEvent( NULL, FALSE, FALSE, NULL); - - thread_ = xe_thread_create( - "RingBufferWorker", - (xe_thread_callback)ThreadStartThunk, this); } RingBufferWorker::~RingBufferWorker() { - // TODO(benvanik): thread join. - running_ = false; SetEvent(write_ptr_index_event_); - xe_thread_release(thread_); CloseHandle(write_ptr_index_event_); } @@ -44,8 +36,6 @@ void RingBufferWorker::Initialize(GraphicsDriver* driver, primary_buffer_ptr_ = ptr; primary_buffer_size_ = page_count * 4 * 1024; read_ptr_index_ = 0; - - xe_thread_start(thread_); } void RingBufferWorker::EnableReadPointerWriteBack(uint32_t ptr, @@ -64,40 +54,40 @@ void RingBufferWorker::UpdateWritePointer(uint32_t value) { SetEvent(write_ptr_index_event_); } -void RingBufferWorker::ThreadStart() { +void RingBufferWorker::Pump() { uint8_t* p = xe_memory_addr(memory_); - while (running_) { - if (write_ptr_index_ == 0xBAADF00D || - read_ptr_index_ == write_ptr_index_) { - // Wait for the command buffer pointer to move. - // TODO(benvanik): only wait for a bit and check running_. - WaitForSingleObject(write_ptr_index_event_, INFINITE); - if (!running_) { - break; - } - } - if (read_ptr_index_ == write_ptr_index_) { - continue; + if (write_ptr_index_ == 0xBAADF00D || + read_ptr_index_ == write_ptr_index_) { + // Check if the pointer has moved. + // We wait a short bit here to yield time. Since we are also running the + // main window display we don't want to pause too long, though. + const int wait_time_ms = 1; + if (WaitForSingleObject(write_ptr_index_event_, + wait_time_ms) == WAIT_TIMEOUT) { + return; } + } + if (read_ptr_index_ == write_ptr_index_) { + return; + } - // Process the new commands. - XELOGGPU("Ring buffer thread work"); + // Process the new commands. + XELOGGPU("Ring buffer thread work"); - // TODO(benvanik): handle wrapping around - // read_ptr_index_ = (read_ptr_index_ + 1) % (primary_buffer_size_ / 4); - XEASSERT(write_ptr_index_ >= read_ptr_index_); - uint32_t length = write_ptr_index_ - read_ptr_index_; - if (length) { - ExecuteSegment(primary_buffer_ptr_ + read_ptr_index_ * 4, length); - read_ptr_index_ = write_ptr_index_; - } + // TODO(benvanik): handle wrapping around + // read_ptr_index_ = (read_ptr_index_ + 1) % (primary_buffer_size_ / 4); + XEASSERT(write_ptr_index_ >= read_ptr_index_); + uint32_t length = write_ptr_index_ - read_ptr_index_; + if (length) { + ExecuteSegment(primary_buffer_ptr_ + read_ptr_index_ * 4, length); + read_ptr_index_ = write_ptr_index_; + } - // TODO(benvanik): use read_ptr_update_freq_ and only issue after moving - // that many indices. - if (read_ptr_writeback_ptr_) { - XESETUINT32BE(p + read_ptr_writeback_ptr_, read_ptr_index_); - } + // TODO(benvanik): use read_ptr_update_freq_ and only issue after moving + // that many indices. + if (read_ptr_writeback_ptr_) { + XESETUINT32BE(p + read_ptr_writeback_ptr_, read_ptr_index_); } } diff --git a/src/xenia/gpu/ring_buffer_worker.h b/src/xenia/gpu/ring_buffer_worker.h index d4d19c5a1..0477028c3 100644 --- a/src/xenia/gpu/ring_buffer_worker.h +++ b/src/xenia/gpu/ring_buffer_worker.h @@ -33,17 +33,13 @@ public: void UpdateWritePointer(uint32_t value); + void Pump(); + protected: - static void ThreadStartThunk(RingBufferWorker* this_ptr) { - this_ptr->ThreadStart(); - } - void ThreadStart(); void ExecuteSegment(uint32_t ptr, uint32_t length); protected: xe_memory_ref memory_; - xe_thread_ref thread_; - bool running_; GraphicsDriver* driver_; diff --git a/src/xenia/gpu/shader.cc b/src/xenia/gpu/shader.cc new file mode 100644 index 000000000..aca2d4901 --- /dev/null +++ b/src/xenia/gpu/shader.cc @@ -0,0 +1,21 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include + + +using namespace xe; +using namespace xe::gpu; + + +Shader::Shader() { +} + +Shader::~Shader() { +} diff --git a/src/xenia/gpu/shader.h b/src/xenia/gpu/shader.h new file mode 100644 index 000000000..bafcbfe33 --- /dev/null +++ b/src/xenia/gpu/shader.h @@ -0,0 +1,31 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_GPU_SHADER_H_ +#define XENIA_GPU_SHADER_H_ + +#include + + +namespace xe { +namespace gpu { + + +class Shader { +public: + Shader(); + virtual ~Shader(); +}; + + +} // namespace gpu +} // namespace xe + + +#endif // XENIA_GPU_SHADER_H_ diff --git a/src/xenia/gpu/shader_cache.cc b/src/xenia/gpu/shader_cache.cc new file mode 100644 index 000000000..8817b7809 --- /dev/null +++ b/src/xenia/gpu/shader_cache.cc @@ -0,0 +1,21 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include + + +using namespace xe; +using namespace xe::gpu; + + +ShaderCache::ShaderCache() { +} + +ShaderCache::~ShaderCache() { +} diff --git a/src/xenia/gpu/shader_cache.h b/src/xenia/gpu/shader_cache.h new file mode 100644 index 000000000..ec09d19be --- /dev/null +++ b/src/xenia/gpu/shader_cache.h @@ -0,0 +1,31 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_GPU_SHADER_CACHE_H_ +#define XENIA_GPU_SHADER_CACHE_H_ + +#include + + +namespace xe { +namespace gpu { + + +class ShaderCache { +public: + ShaderCache(); + virtual ~ShaderCache(); +}; + + +} // namespace gpu +} // namespace xe + + +#endif // XENIA_GPU_SHADER_CACHE_H_ diff --git a/src/xenia/gpu/sources.gypi b/src/xenia/gpu/sources.gypi index 8d0443eb2..3d3ced141 100644 --- a/src/xenia/gpu/sources.gypi +++ b/src/xenia/gpu/sources.gypi @@ -11,6 +11,10 @@ 'graphics_system.h', 'ring_buffer_worker.cc', 'ring_buffer_worker.h', + 'shader.cc', + 'shader.h', + 'shader_cache.cc', + 'shader_cache.h', ], 'includes': [ diff --git a/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_video.cc b/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_video.cc index 81390d879..fc62b85f5 100644 --- a/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_video.cc +++ b/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_video.cc @@ -154,8 +154,6 @@ void xeVdInitializeEngines(uint32_t unk0, uint32_t callback, uint32_t unk1, // r4 = function ptr (cleanup callback?) // r5 = 0 // r6/r7 = some binary data in .data - - gs->Initialize(); } @@ -366,6 +364,24 @@ SHIM_CALL VdRetrainEDRAM_shim( } +SHIM_CALL VdSwap_shim( + xe_ppc_state_t* ppc_state, KernelState* state) { + XELOGD( + "VdSwap(?)"); + + KernelState* kernel_state = shared_kernel_state_; + XEASSERTNOTNULL(kernel_state); + GraphicsSystem* gs = kernel_state->processor()->graphics_system().get(); + if (!gs) { + return; + } + + gs->set_swap_pending(true); + + SHIM_SET_RETURN(0); +} + + } // namespace xboxkrnl } // namespace kernel } // namespace xe @@ -387,6 +403,7 @@ void xe::kernel::xboxkrnl::RegisterVideoExports( SHIM_SET_MAPPING("xboxkrnl.exe", VdPersistDisplay, state); SHIM_SET_MAPPING("xboxkrnl.exe", VdRetrainEDRAMWorker, state); SHIM_SET_MAPPING("xboxkrnl.exe", VdRetrainEDRAM, state); + SHIM_SET_MAPPING("xboxkrnl.exe", VdSwap, state); xe_memory_ref memory = state->memory(); uint8_t* mem = xe_memory_addr(memory); diff --git a/tools/xenia-run/xenia-run.cc b/tools/xenia-run/xenia-run.cc index b3a67139a..8bd7dcb9a 100644 --- a/tools/xenia-run/xenia-run.cc +++ b/tools/xenia-run/xenia-run.cc @@ -33,6 +33,7 @@ public: private: xe_memory_ref memory_; + xe_run_loop_ref run_loop_; shared_ptr backend_; shared_ptr graphics_system_; shared_ptr processor_; @@ -40,10 +41,12 @@ private: shared_ptr debugger_; }; -Run::Run() { +Run::Run() : + memory_(0), run_loop_(0) { } Run::~Run() { + xe_run_loop_release(run_loop_); xe_memory_release(memory_); } @@ -62,7 +65,7 @@ int Run::Setup() { backend_ = shared_ptr(new xe::cpu::x64::X64Backend()); params.memory = memory_; - graphics_system_ = shared_ptr(xe::gpu::CreateNop(¶ms)); + graphics_system_ = shared_ptr(xe::gpu::Create(¶ms)); debugger_ = shared_ptr(new Debugger()); diff --git a/xenia.gyp b/xenia.gyp index d4bb65d77..66e55cd8e 100644 --- a/xenia.gyp +++ b/xenia.gyp @@ -40,6 +40,9 @@ ['OS == "win"', { 'libraries': [ 'wsock32', + 'dxgi', + 'd3d11', + 'd3dx11', ], }], ['OS == "mac"', {