Path: blob/master/RSDKv5/RSDK/Graphics/DX11/DX11RenderDevice.cpp
1163 views
#include "resource.h"12#if !RETRO_USE_ORIGINAL_CODE3#include <D3Dcompiler.h>4#include "BackupShaders.hpp"5#endif67#include <atlbase.h>89#include "Ks.h" // used for KSCATEGORY_AUDIO10#include "Ksmedia.h" // used for KSCATEGORY_AUDIO1112#define DX11_WINDOWFLAGS_BORDERED (WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_GROUP)13#define DX11_WINDOWFLAGS_BORDERLESS (WS_POPUP)1415HWND RenderDevice::windowHandle;1617HDEVNOTIFY RenderDevice::deviceNotif = 0;18PAINTSTRUCT RenderDevice::Paint;1920ID3D11DeviceContext *RenderDevice::dx11Context;21ID3D11Device *RenderDevice::dx11Device;22UINT RenderDevice::dxAdapter;23ID3D11Buffer *RenderDevice::dx11VertexBuffer;24ID3D11Texture2D *RenderDevice::screenTextures[SCREEN_COUNT];25ID3D11Texture2D *RenderDevice::imageTexture;26ID3D11ShaderResourceView *RenderDevice::screenTextureViews[SCREEN_COUNT];27ID3D11ShaderResourceView *RenderDevice::imageTextureView;28D3D11_VIEWPORT RenderDevice::dx11ViewPort;29IDXGISwapChain *RenderDevice::swapChain;30ID3D11RenderTargetView *RenderDevice::renderView;3132ID3D11RasterizerState *RenderDevice::rasterState;33ID3D11SamplerState *RenderDevice::samplerPoint;34ID3D11SamplerState *RenderDevice::samplerLinear;35ID3D11Buffer *RenderDevice::psConstBuffer = NULL;3637int32 RenderDevice::adapterCount = 0;38RECT RenderDevice::monitorDisplayRect;39LUID RenderDevice::deviceIdentifier;4041D3D_DRIVER_TYPE RenderDevice::driverType = D3D_DRIVER_TYPE_NULL;42D3D_FEATURE_LEVEL RenderDevice::featureLevel = D3D_FEATURE_LEVEL_11_0;4344bool RenderDevice::useFrequency = false;4546LARGE_INTEGER RenderDevice::performanceCount;47LARGE_INTEGER RenderDevice::frequency;48LARGE_INTEGER RenderDevice::initialFrequency;49LARGE_INTEGER RenderDevice::curFrequency;5051// WinMain args52HINSTANCE RenderDevice::hInstance;53HINSTANCE RenderDevice::hPrevInstance;54INT RenderDevice::nShowCmd;5556struct ShaderConstants {57float2 pixelSize;58float2 textureSize;59float2 viewSize;60float2 screenDim;61};6263bool RenderDevice::Init()64{65#if _UNICODE66// shit workaround since windows is BEGGING me to use wide strs67std::string str = gameVerInfo.gameTitle;68std::wstring temp = std::wstring(str.begin(), str.end());69LPCWSTR gameTitle = temp.c_str();70#else71std::string str = gameVerInfo.gameTitle;72LPCSTR gameTitle = str.c_str();73#endif7475HMODULE handle = GetModuleHandle(NULL);7677WNDCLASS wndClass;78wndClass.style = CS_VREDRAW | CS_HREDRAW;79wndClass.lpfnWndProc = WindowEventCallback;80wndClass.cbClsExtra = 0;81wndClass.cbWndExtra = sizeof(LONG);82wndClass.hInstance = hInstance;83wndClass.hIcon = LoadIcon(handle, IDI_APPLICATION);84wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);85wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);86wndClass.lpszMenuName = NULL;87wndClass.lpszClassName = gameTitle;88if (!RegisterClass(&wndClass))89return false;9091ShowCursor(false);9293tagRECT winRect;94if (videoSettings.windowed) {95winRect.left = (GetSystemMetrics(SM_CXSCREEN) - videoSettings.windowWidth) / 2;96winRect.top = (GetSystemMetrics(SM_CYSCREEN) - videoSettings.windowHeight) / 2;97winRect.right = winRect.left + videoSettings.windowWidth;98winRect.bottom = winRect.top + videoSettings.windowHeight;99}100else if (videoSettings.fsWidth <= 0 || videoSettings.fsHeight <= 0) {101winRect.left = 0;102winRect.top = 0;103winRect.right = GetSystemMetrics(SM_CXSCREEN);104winRect.bottom = GetSystemMetrics(SM_CYSCREEN);105}106else {107winRect.left = (GetSystemMetrics(SM_CXSCREEN) - videoSettings.fsWidth) / 2;108winRect.top = (GetSystemMetrics(SM_CYSCREEN) - videoSettings.fsHeight) / 2;109winRect.right = winRect.left + videoSettings.fsWidth;110winRect.bottom = winRect.top + videoSettings.fsHeight;111}112113uint32 windowFlags = 0;114if (videoSettings.bordered && videoSettings.windowed)115windowFlags = DX11_WINDOWFLAGS_BORDERED;116else117windowFlags = DX11_WINDOWFLAGS_BORDERLESS;118119AdjustWindowRect(&winRect, windowFlags, false);120windowHandle = CreateWindowEx(WS_EX_LEFT, gameTitle, gameTitle, windowFlags, winRect.left, winRect.top, winRect.right - winRect.left,121winRect.bottom - winRect.top, NULL, NULL, hInstance, NULL);122123PrintLog(PRINT_NORMAL, "w: %d h: %d windowed: %d\n", winRect.right - winRect.left, winRect.bottom - winRect.top, videoSettings.windowed);124125if (!windowHandle)126return false;127128ShowWindow(windowHandle, nShowCmd);129UpdateWindow(windowHandle);130131if (!SetupRendering() || !AudioDevice::Init())132return false;133134InitInputDevices();135return true;136}137138void RenderDevice::CopyFrameBuffer()139{140for (int32 s = 0; s < videoSettings.screenCount; ++s) {141D3D11_MAPPED_SUBRESOURCE mappedResource;142if (SUCCEEDED(dx11Context->Map(screenTextures[s], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource))) {143WORD *pixels = (WORD *)mappedResource.pData;144uint16 *frameBuffer = screens[s].frameBuffer;145146int32 screenPitch = screens[s].pitch;147int32 pitch = (mappedResource.RowPitch >> 1) - screenPitch;148149for (int32 y = 0; y < SCREEN_YSIZE; ++y) {150int32 pixelCount = screenPitch >> 4;151for (int32 x = 0; x < pixelCount; ++x) {152pixels[0] = frameBuffer[0];153pixels[1] = frameBuffer[1];154pixels[2] = frameBuffer[2];155pixels[3] = frameBuffer[3];156pixels[4] = frameBuffer[4];157pixels[5] = frameBuffer[5];158pixels[6] = frameBuffer[6];159pixels[7] = frameBuffer[7];160pixels[8] = frameBuffer[8];161pixels[9] = frameBuffer[9];162pixels[10] = frameBuffer[10];163pixels[11] = frameBuffer[11];164pixels[12] = frameBuffer[12];165pixels[13] = frameBuffer[13];166pixels[14] = frameBuffer[14];167pixels[15] = frameBuffer[15];168169frameBuffer += 16;170pixels += 16;171}172173pixels += pitch;174}175176dx11Context->Unmap(screenTextures[s], 0);177}178}179}180181void RenderDevice::FlipScreen()182{183if (windowRefreshDelay > 0) {184if (!--windowRefreshDelay)185UpdateGameWindow();186187return;188}189190const FLOAT clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };191192dx11Context->RSSetViewports(1, &displayInfo.viewport);193dx11Context->ClearRenderTargetView(renderView, clearColor);194dx11Context->RSSetViewports(1, &dx11ViewPort);195196dx11Context->OMSetRenderTargets(1, &renderView, nullptr);197dx11Context->RSSetState(rasterState);198199if (true) {200// reload shader if needed201if (lastShaderID != videoSettings.shaderID) {202lastShaderID = videoSettings.shaderID;203204dx11Context->PSSetSamplers(0, 1, shaderList[videoSettings.shaderID].linear ? &samplerLinear : &samplerPoint);205206dx11Context->IASetInputLayout(shaderList[videoSettings.shaderID].vertexDeclare);207if (videoSettings.shaderSupport) {208dx11Context->VSSetShader(shaderList[videoSettings.shaderID].vertexShaderObject, nullptr, 0);209dx11Context->PSSetShader(shaderList[videoSettings.shaderID].pixelShaderObject, nullptr, 0);210}211}212213if (videoSettings.shaderSupport) {214ShaderConstants constants[] = { pixelSize, textureSize, viewSize, { videoSettings.dimMax * videoSettings.dimPercent, 0 } };215216D3D11_MAPPED_SUBRESOURCE mappedResource;217ZeroMemory(&mappedResource, sizeof(mappedResource));218dx11Context->Map(psConstBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);219memcpy(mappedResource.pData, &constants, sizeof(ShaderConstants));220dx11Context->Unmap(psConstBuffer, 0);221222dx11Context->PSSetConstantBuffers(0, 1, &psConstBuffer);223}224225int32 startVert = 0;226ID3D11Texture2D *const tex = screenTextures[0];227228switch (videoSettings.screenCount) {229default:230case 0:231#if RETRO_REV02232startVert = 54;233#else234startVert = 18;235#endif236dx11Context->PSSetShaderResources(0, 1, &imageTextureView);237dx11Context->Draw(6, startVert);238break;239240case 1:241dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[0]);242dx11Context->Draw(6, 0);243break;244245case 2:246#if RETRO_REV02247startVert = startVertex_2P[0];248#else249startVert = 6;250#endif251dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[0]);252dx11Context->Draw(6, startVert);253254#if RETRO_REV02255startVert = startVertex_2P[1];256#else257startVert = 12;258#endif259dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[1]);260dx11Context->Draw(6, startVert);261break;262263#if RETRO_REV02264case 3:265dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[0]);266dx11Context->Draw(6, startVertex_3P[0]);267268dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[1]);269dx11Context->Draw(6, startVertex_3P[1]);270271dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[2]);272dx11Context->Draw(6, startVertex_3P[2]);273break;274275case 4:276dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[0]);277dx11Context->Draw(startVert, 30);278279dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[1]);280dx11Context->Draw(startVert, 36);281282dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[2]);283dx11Context->Draw(startVert, 42);284285dx11Context->PSSetShaderResources(0, 1, &screenTextureViews[3]);286dx11Context->Draw(startVert, 48);287break;288#endif289}290}291292if (FAILED(swapChain->Present(videoSettings.vsync ? 1 : 0, 0)))293windowRefreshDelay = 8;294}295296void RenderDevice::Release(bool32 isRefresh)297{298if (dx11Context)299dx11Context->ClearState();300301if (videoSettings.shaderSupport) {302for (int32 i = 0; i < shaderCount; ++i) {303if (shaderList[i].vertexShaderObject)304shaderList[i].vertexShaderObject->Release();305shaderList[i].vertexShaderObject = NULL;306307if (shaderList[i].pixelShaderObject)308shaderList[i].pixelShaderObject->Release();309shaderList[i].pixelShaderObject = NULL;310311if (shaderList[i].vertexDeclare)312shaderList[i].vertexDeclare->Release();313shaderList[i].vertexDeclare = NULL;314}315316shaderCount = 0;317#if RETRO_USE_MOD_LOADER318userShaderCount = 0;319#endif320}321322if (imageTexture) {323imageTexture->Release();324imageTexture = NULL;325}326327if (imageTextureView) {328imageTextureView->Release();329imageTextureView = NULL;330}331332for (int32 i = 0; i < SCREEN_COUNT; ++i) {333if (screenTextures[i])334screenTextures[i]->Release();335336screenTextures[i] = NULL;337338if (screenTextureViews[i])339screenTextureViews[i]->Release();340341screenTextureViews[i] = NULL;342}343344if (renderView) {345renderView->Release();346renderView = NULL;347}348349if (psConstBuffer) {350psConstBuffer->Release();351psConstBuffer = NULL;352}353354if (samplerPoint) {355samplerPoint->Release();356samplerPoint = NULL;357}358359if (samplerLinear) {360samplerLinear->Release();361samplerLinear = NULL;362}363364if (rasterState) {365rasterState->Release();366rasterState = NULL;367}368369if (!isRefresh && displayInfo.displays) {370free(displayInfo.displays);371displayInfo.displays = NULL;372}373374if (dx11VertexBuffer) {375dx11VertexBuffer->Release();376dx11VertexBuffer = NULL;377}378379if (swapChain) {380DXGI_SWAP_CHAIN_DESC desc;381swapChain->GetDesc(&desc);382// it's not a good idea to release it while in fullscreen so, lets not!383if (!desc.Windowed)384swapChain->SetFullscreenState(FALSE, NULL);385386swapChain->Release();387swapChain = NULL;388}389390if (!isRefresh && dx11Device) {391dx11Device->Release();392dx11Device = NULL;393}394395if (!isRefresh && dx11Context) {396dx11Context->Release();397dx11Context = NULL;398}399400if (!isRefresh && scanlines) {401free(scanlines);402scanlines = NULL;403}404}405406void RenderDevice::RefreshWindow()407{408videoSettings.windowState = WINDOWSTATE_UNINITIALIZED;409410Release(true);411412ShowWindow(windowHandle, SW_HIDE);413414if (videoSettings.windowed && videoSettings.bordered)415SetWindowLong(windowHandle, GWL_STYLE, DX11_WINDOWFLAGS_BORDERED);416else417SetWindowLong(windowHandle, GWL_STYLE, DX11_WINDOWFLAGS_BORDERLESS);418419Sleep(250); // zzzz.. mimimimi..420421GetDisplays();422423tagRECT rect;424if (videoSettings.windowed || !videoSettings.exclusiveFS) {425tagRECT winRect;426GetClientRect(windowHandle, &winRect);427428tagPOINT topLeft, bottomRight;429topLeft.x = winRect.left;430topLeft.y = winRect.top;431bottomRight.x = winRect.right;432bottomRight.y = winRect.bottom;433434ClientToScreen(windowHandle, &topLeft);435ClientToScreen(windowHandle, &bottomRight);436437if (videoSettings.windowed) {438std::vector<IDXGIAdapter *> adapterList = GetAdapterList();439440IDXGIOutput *pOutput;441if (SUCCEEDED(adapterList[dxAdapter]->EnumOutputs(0, &pOutput))) {442DXGI_OUTPUT_DESC outputDesc;443pOutput->GetDesc(&outputDesc);444445int32 displayWidth = outputDesc.DesktopCoordinates.right - outputDesc.DesktopCoordinates.left;446int32 displayHeight = outputDesc.DesktopCoordinates.bottom - outputDesc.DesktopCoordinates.top;447448if (videoSettings.windowWidth >= displayWidth || videoSettings.windowHeight >= displayHeight) {449videoSettings.windowWidth = (displayHeight / 480 * videoSettings.pixWidth);450videoSettings.windowHeight = displayHeight / 480 * videoSettings.pixHeight;451}452}453454rect.left = (bottomRight.x + topLeft.x) / 2 - videoSettings.windowWidth / 2;455rect.top = (bottomRight.y + topLeft.y) / 2 - videoSettings.windowHeight / 2;456rect.right = (bottomRight.x + topLeft.x) / 2 + videoSettings.windowWidth / 2;457rect.bottom = (bottomRight.y + topLeft.y) / 2 + videoSettings.windowHeight / 2;458459if (videoSettings.bordered)460AdjustWindowRect(&rect, DX11_WINDOWFLAGS_BORDERED, false);461else462AdjustWindowRect(&rect, DX11_WINDOWFLAGS_BORDERLESS, false);463464if (rect.left < monitorDisplayRect.left || rect.right > monitorDisplayRect.right || rect.top < monitorDisplayRect.top465|| rect.bottom > monitorDisplayRect.bottom) {466rect.left = (monitorDisplayRect.right + monitorDisplayRect.left) / 2 - videoSettings.windowWidth / 2;467rect.top = (monitorDisplayRect.top + monitorDisplayRect.bottom) / 2 - videoSettings.windowHeight / 2;468rect.right = (monitorDisplayRect.right + monitorDisplayRect.left) / 2 + videoSettings.windowWidth / 2;469rect.bottom = (monitorDisplayRect.top + monitorDisplayRect.bottom) / 2 + videoSettings.windowHeight / 2;470471if (videoSettings.bordered)472AdjustWindowRect(&rect, DX11_WINDOWFLAGS_BORDERED, false);473else474AdjustWindowRect(&rect, DX11_WINDOWFLAGS_BORDERLESS, false);475}476}477else {478rect = monitorDisplayRect;479AdjustWindowRect(&monitorDisplayRect, DX11_WINDOWFLAGS_BORDERLESS, 0);480}481482SetWindowPos(windowHandle, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_SHOWWINDOW);483}484485ShowWindow(windowHandle, SW_SHOW);486RedrawWindow(windowHandle, NULL, NULL, RDW_UPDATENOW | RDW_INVALIDATE);487488if (!InitGraphicsAPI() || !InitShaders())489return;490491videoSettings.windowState = WINDOWSTATE_ACTIVE;492}493494void RenderDevice::InitFPSCap()495{496if (QueryPerformanceFrequency(&frequency)) {497useFrequency = true;498initialFrequency.QuadPart = frequency.QuadPart / videoSettings.refreshRate;499QueryPerformanceCounter(&performanceCount);500}501else {502useFrequency = false;503performanceCount.QuadPart = timeGetTime();504}505}506bool RenderDevice::CheckFPSCap()507{508if (useFrequency)509QueryPerformanceCounter(&curFrequency);510else511curFrequency.QuadPart = timeGetTime();512513if (curFrequency.QuadPart > performanceCount.QuadPart)514return true;515516return false;517}518void RenderDevice::UpdateFPSCap() { performanceCount.QuadPart = curFrequency.QuadPart + initialFrequency.LowPart; }519520void RenderDevice::InitVertexBuffer()521{522RenderVertex vertBuffer[sizeof(rsdkVertexBuffer) / sizeof(RenderVertex)];523memcpy(vertBuffer, rsdkVertexBuffer, sizeof(rsdkVertexBuffer));524525float x = 0.5 / (float)viewSize.x;526float y = 0.5 / (float)viewSize.y;527528// ignore the last 6 verts, they're scaled to the 1024x512 textures already!529int32 vertCount = (RETRO_REV02 ? 60 : 24) - 6;530for (int32 v = 0; v < vertCount; ++v) {531RenderVertex *vertex = &vertBuffer[v];532vertex->pos.x = vertex->pos.x - x;533vertex->pos.y = vertex->pos.y + y;534535if (vertex->tex.x)536vertex->tex.x = screens[0].size.x * (1.0 / textureSize.x);537538if (vertex->tex.y)539vertex->tex.y = screens[0].size.y * (1.0 / textureSize.y);540}541542D3D11_MAPPED_SUBRESOURCE resource;543if (SUCCEEDED(dx11Context->Map(dx11VertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource))) {544memcpy(resource.pData, vertBuffer, sizeof(vertBuffer));545dx11Context->Unmap(dx11VertexBuffer, 0);546}547548// Set/Update vertex buffer549UINT stride = sizeof(RenderVertex);550UINT offset = 0;551dx11Context->IASetVertexBuffers(0, 1, &dx11VertexBuffer, &stride, &offset);552553// Init pixel shader constants554D3D11_BUFFER_DESC cbDesc = {};555cbDesc.Usage = D3D11_USAGE_DYNAMIC;556cbDesc.ByteWidth = sizeof(ShaderConstants);557cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;558cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;559cbDesc.MiscFlags = 0;560cbDesc.StructureByteStride = 0;561562dx11Device->CreateBuffer(&cbDesc, NULL, &psConstBuffer);563}564565bool RenderDevice::InitGraphicsAPI()566{567videoSettings.shaderSupport = false;568if (featureLevel >= D3D_FEATURE_LEVEL_11_0) {569videoSettings.shaderSupport = true;570}571else {572PrintLog(PRINT_NORMAL, "ERROR: HLSL shader model 5 support not detected. shader support is required for the DX11 backend!\nIf this issue "573"persists, try using the DX9 backend instead?");574return false; // unlike DX9, DX11 doesn't support shaderless rendering, so just kill it here575}576577HRESULT hr = 0;578579// Obtain DXGI factory from device (since we used nullptr for pAdapter above)580IDXGIFactory1 *dxgiFactory = nullptr;581{582IDXGIDevice *dxgiDevice = nullptr;583hr = dx11Device->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);584if (SUCCEEDED(hr)) {585IDXGIAdapter *adapter = nullptr;586hr = dxgiDevice->GetAdapter(&adapter);587if (SUCCEEDED(hr)) {588hr = adapter->GetParent(__uuidof(IDXGIFactory1), (void **)&dxgiFactory);589adapter->Release();590}591dxgiDevice->Release();592}593}594595if (FAILED(hr))596return false;597598if (videoSettings.windowed || !videoSettings.exclusiveFS) {599if (videoSettings.windowed) {600viewSize.x = videoSettings.windowWidth;601viewSize.y = videoSettings.windowHeight;602}603else {604viewSize.x = displayWidth[dxAdapter];605viewSize.y = displayHeight[dxAdapter];606}607}608else {609int32 bufferWidth = videoSettings.fsWidth;610int32 bufferHeight = videoSettings.fsHeight;611if (videoSettings.fsWidth <= 0 || videoSettings.fsHeight <= 0) {612bufferWidth = displayWidth[dxAdapter];613bufferHeight = displayHeight[dxAdapter];614}615616viewSize.x = bufferWidth;617viewSize.y = bufferHeight;618}619620// Create swap chain621IDXGIFactory2 *dxgiFactory2 = nullptr;622hr = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), (void **)&dxgiFactory2);623if (dxgiFactory2) {624// DirectX 11.1 or later625hr = dx11Device->QueryInterface(__uuidof(ID3D11Device1), (void **)&dx11Device);626if (SUCCEEDED(hr))627dx11Context->QueryInterface(__uuidof(ID3D11DeviceContext1), (void **)&dx11Context);628629DXGI_SWAP_CHAIN_DESC1 swapDesc = {};630swapDesc.Width = viewSize.x;631swapDesc.Height = viewSize.y;632swapDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;633swapDesc.Stereo = FALSE;634swapDesc.SampleDesc.Count = 1;635swapDesc.SampleDesc.Quality = 0;636swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;637swapDesc.BufferCount = 2;638swapDesc.Scaling = DXGI_SCALING_STRETCH;639swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;640swapDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;641swapDesc.Flags = 0;642643DXGI_SWAP_CHAIN_FULLSCREEN_DESC fsDesc = {};644645fsDesc.RefreshRate.Numerator = videoSettings.refreshRate;646fsDesc.RefreshRate.Denominator = 1;647fsDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;648fsDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;649fsDesc.Windowed = videoSettings.windowed || !videoSettings.exclusiveFS;650651CComPtr<IDXGISwapChain1> swapChain1;652hr = dxgiFactory2->CreateSwapChainForHwnd(dx11Device, windowHandle, &swapDesc, &fsDesc, nullptr, &swapChain1);653if (SUCCEEDED(hr))654hr = swapChain1->QueryInterface(__uuidof(IDXGISwapChain), (void **)&swapChain);655656dxgiFactory2->Release();657}658else {659// DirectX 11.0 systems660DXGI_SWAP_CHAIN_DESC swapDesc = {};661swapDesc.BufferCount = 1;662swapDesc.BufferDesc.Width = viewSize.x;663swapDesc.BufferDesc.Height = viewSize.y;664swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;665swapDesc.BufferDesc.RefreshRate.Numerator = videoSettings.refreshRate;666swapDesc.BufferDesc.RefreshRate.Denominator = 1;667swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;668swapDesc.OutputWindow = windowHandle;669swapDesc.SampleDesc.Count = 2;670swapDesc.SampleDesc.Quality = 0;671swapDesc.Windowed = videoSettings.windowed || !videoSettings.exclusiveFS;672swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;673674hr = dxgiFactory->CreateSwapChain(dx11Device, &swapDesc, &swapChain);675}676677dxgiFactory->Release();678679// disable the api handling ALT+Return (we handle it ourselves)680IDXGIFactory1 *pFactory = NULL;681if (SUCCEEDED(swapChain->GetParent(__uuidof(IDXGIFactory1), (void **)&pFactory))) {682pFactory->MakeWindowAssociation(windowHandle, DXGI_MWA_NO_ALT_ENTER);683pFactory->Release();684}685686// Create a render target view687ID3D11Texture2D *pBackBuffer = nullptr;688hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void **)&pBackBuffer);689if (FAILED(hr))690return false;691692hr = dx11Device->CreateRenderTargetView(pBackBuffer, nullptr, &renderView);693pBackBuffer->Release();694if (FAILED(hr))695return false;696697dx11Context->OMSetRenderTargets(1, &renderView, nullptr);698699dx11Context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);700701{702D3D11_BUFFER_DESC desc = {};703desc.Usage = D3D11_USAGE_DYNAMIC;704desc.ByteWidth = sizeof(RenderVertex) * ARRAYSIZE(rsdkVertexBuffer);705desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;706desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;707708hr = dx11Device->CreateBuffer(&desc, NULL, &dx11VertexBuffer);709if (FAILED(hr))710return false;711}712713int32 maxPixHeight = 0;714#if !RETRO_USE_ORIGINAL_CODE715int32 screenWidth = 0;716#endif717for (int32 s = 0; s < SCREEN_COUNT; ++s) {718if (videoSettings.pixHeight > maxPixHeight)719maxPixHeight = videoSettings.pixHeight;720721screens[s].size.y = videoSettings.pixHeight;722723float viewAspect = viewSize.x / viewSize.y;724#if !RETRO_USE_ORIGINAL_CODE725screenWidth = (int32)((viewAspect * videoSettings.pixHeight) + 3) & 0xFFFFFFFC;726#else727int32 screenWidth = (int32)((viewAspect * videoSettings.pixHeight) + 3) & 0xFFFFFFFC;728#endif729if (screenWidth < videoSettings.pixWidth)730screenWidth = videoSettings.pixWidth;731732#if !RETRO_USE_ORIGINAL_CODE733if (customSettings.maxPixWidth && screenWidth > customSettings.maxPixWidth)734screenWidth = customSettings.maxPixWidth;735#else736if (screenWidth > DEFAULT_PIXWIDTH)737screenWidth = DEFAULT_PIXWIDTH;738#endif739740memset(&screens[s].frameBuffer, 0, sizeof(screens[s].frameBuffer));741SetScreenSize(s, screenWidth, screens[s].size.y);742}743744pixelSize.x = screens[0].size.x;745pixelSize.y = screens[0].size.y;746float pixAspect = pixelSize.x / pixelSize.y;747748UINT viewportCount = 0;749dx11Context->RSGetViewports(&viewportCount, NULL);750if (viewportCount) {751D3D11_VIEWPORT *viewports = new D3D11_VIEWPORT[viewportCount];752dx11Context->RSGetViewports(&viewportCount, viewports);753displayInfo.viewport = viewports[0];754dx11ViewPort = displayInfo.viewport;755756delete[] viewports;757}758else {759displayInfo.viewport.TopLeftX = 0;760displayInfo.viewport.TopLeftY = 0;761displayInfo.viewport.Width = viewSize.x;762displayInfo.viewport.Height = viewSize.y;763displayInfo.viewport.MinDepth = 0;764displayInfo.viewport.MaxDepth = 1;765766dx11ViewPort = displayInfo.viewport;767768dx11Context->RSSetViewports(1, &dx11ViewPort);769}770771if ((viewSize.x / viewSize.y) <= ((pixelSize.x / pixelSize.y) + 0.1)) {772if ((pixAspect - 0.1) > (viewSize.x / viewSize.y)) {773viewSize.y = (pixelSize.y / pixelSize.x) * viewSize.x;774dx11ViewPort.TopLeftY = (displayInfo.viewport.Height * 0.5) - (viewSize.y * 0.5);775dx11ViewPort.Height = viewSize.y;776777dx11Context->RSSetViewports(1, &dx11ViewPort);778}779}780else {781viewSize.x = pixAspect * viewSize.y;782dx11ViewPort.TopLeftX = (displayInfo.viewport.Width * 0.5) - (viewSize.x * 0.5);783dx11ViewPort.Width = viewSize.x;784785dx11Context->RSSetViewports(1, &dx11ViewPort);786}787788#if !RETRO_USE_ORIGINAL_CODE789if (screenWidth <= 512 && maxPixHeight <= 256) {790#else791if (maxPixHeight <= 256) {792#endif793textureSize.x = 512.0;794textureSize.y = 256.0;795}796else {797textureSize.x = 1024.0;798textureSize.y = 512.0;799}800801for (int32 s = 0; s < SCREEN_COUNT; ++s) {802D3D11_TEXTURE2D_DESC desc = {};803desc.Width = textureSize.x;804desc.Height = textureSize.y;805desc.MipLevels = desc.ArraySize = 1;806desc.Format = DXGI_FORMAT_B5G6R5_UNORM;807desc.SampleDesc.Quality = 0;808desc.SampleDesc.Count = 1;809desc.Usage = D3D11_USAGE_DYNAMIC;810desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;811desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;812desc.MiscFlags = 0;813814if (FAILED(dx11Device->CreateTexture2D(&desc, NULL, &screenTextures[s])))815return false;816817D3D11_SHADER_RESOURCE_VIEW_DESC resDesc;818resDesc.Format = desc.Format;819resDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;820resDesc.Texture2D.MostDetailedMip = 0;821resDesc.Texture2D.MipLevels = 1;822823if (FAILED(dx11Device->CreateShaderResourceView(screenTextures[s], &resDesc, &screenTextureViews[s])))824return false;825}826827D3D11_TEXTURE2D_DESC desc = {};828desc.Width = RETRO_VIDEO_TEXTURE_W;829desc.Height = RETRO_VIDEO_TEXTURE_H;830desc.MipLevels = desc.ArraySize = 1;831desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;832desc.SampleDesc.Quality = 0;833desc.SampleDesc.Count = 1;834desc.Usage = D3D11_USAGE_DYNAMIC;835desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;836desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;837desc.MiscFlags = 0;838if (FAILED(dx11Device->CreateTexture2D(&desc, NULL, &imageTexture)))839return false;840841D3D11_SHADER_RESOURCE_VIEW_DESC resDesc;842resDesc.Format = desc.Format;843resDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;844resDesc.Texture2D.MostDetailedMip = 0;845resDesc.Texture2D.MipLevels = 1;846847if (FAILED(dx11Device->CreateShaderResourceView(imageTexture, &resDesc, &imageTextureView)))848return false;849850lastShaderID = -1;851InitVertexBuffer();852engine.inFocus = 1;853videoSettings.viewportX = dx11ViewPort.TopLeftX;854videoSettings.viewportY = dx11ViewPort.TopLeftY;855videoSettings.viewportW = 1.0 / viewSize.x;856videoSettings.viewportH = 1.0 / viewSize.y;857858return true;859}860861void RenderDevice::LoadShader(const char *fileName, bool32 linear)862{863char fullFilePath[0x100];864FileInfo info;865866for (int32 i = 0; i < shaderCount; ++i) {867if (strcmp(shaderList[i].name, fileName) == 0)868return;869}870871if (shaderCount == SHADER_COUNT)872return;873874ShaderEntry *shader = &shaderList[shaderCount];875shader->linear = linear;876sprintf_s(shader->name, sizeof(shader->name), "%s", fileName);877878const D3D_SHADER_MACRO defines[] = {879#if RETRO_REV02880"RETRO_REV02",881"1",882#endif883NULL,884NULL885};886887#if !RETRO_USE_ORIGINAL_CODE888void *bytecode = NULL;889size_t bytecodeSize = 0;890891// Try to compile the vertex shader source if it exists892sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Shaders/DX11/%s.hlsl", fileName);893InitFileInfo(&info);894if (LoadFile(&info, fullFilePath, FMODE_RB)) {895uint8 *fileData = NULL;896AllocateStorage((void **)&fileData, info.fileSize, DATASET_TMP, false);897ReadBytes(&info, fileData, info.fileSize);898CloseFile(&info);899900UINT flags = D3DCOMPILE_ENABLE_STRICTNESS;901if (engine.devMenu) {902flags |= D3DCOMPILE_DEBUG;903flags |= D3DCOMPILE_OPTIMIZATION_LEVEL0;904flags |= D3DCOMPILE_WARNINGS_ARE_ERRORS;905}906else {907flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;908}909910ID3DBlob *shaderBlob = nullptr;911ID3DBlob *errorBlob = nullptr;912HRESULT result = D3DCompile(fileData, info.fileSize, fullFilePath, defines, NULL, "VSMain", "vs_5_0", flags, 0, &shaderBlob, &errorBlob);913914RemoveStorageEntry((void **)&fileData);915916if (FAILED(result)) {917if (errorBlob) {918PrintLog(PRINT_NORMAL, "ERROR COMPILING VERTEX SHADER: %s", (char *)errorBlob->GetBufferPointer());919errorBlob->Release();920}921922if (shaderBlob)923shaderBlob->Release();924925return;926}927else {928PrintLog(PRINT_NORMAL, "Successfully compiled vertex shader!");929if (errorBlob)930PrintLog(PRINT_NORMAL, "Vertex shader warnings:\n%s", (char *)errorBlob->GetBufferPointer());931932if (FAILED(dx11Device->CreateVertexShader((DWORD *)shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), NULL,933&shader->vertexShaderObject))) {934if (shader->vertexShaderObject) {935shader->vertexShaderObject->Release();936shader->vertexShaderObject = NULL;937}938939return;940}941#pragma comment( lib, "dxguid.lib")942shader->vertexShaderObject->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(fileName), fileName);943}944945bytecode = shaderBlob->GetBufferPointer();946bytecodeSize = shaderBlob->GetBufferSize();947}948else {949#endif950// if the vertex shader source doesn't exist, fall back and try to load the vertex shader bytecode951sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Shaders/CSO-DX11/%s.vso", fileName);952InitFileInfo(&info);953if (LoadFile(&info, fullFilePath, FMODE_RB)) {954uint8 *fileData = NULL;955AllocateStorage((void **)&fileData, info.fileSize, DATASET_TMP, false);956ReadBytes(&info, fileData, info.fileSize);957CloseFile(&info);958959if (FAILED(dx11Device->CreateVertexShader((DWORD *)fileData, info.fileSize, NULL, &shader->vertexShaderObject))) {960if (shader->vertexShaderObject) {961shader->vertexShaderObject->Release();962shader->vertexShaderObject = NULL;963}964965RemoveStorageEntry((void **)&fileData);966return;967}968969bytecode = fileData;970bytecodeSize = info.fileSize;971RemoveStorageEntry((void **)&fileData);972}973974#if !RETRO_USE_ORIGINAL_CODE975else {976PrintLog(PRINT_NORMAL, "Could not find vertex shader for '%s', aborting", fileName);977return;978}979}980#endif981982// create the vertex layout stuff using the vertex shader983{984D3D11_INPUT_ELEMENT_DESC elements[2];985986elements[0].SemanticName = "SV_POSITION";987elements[0].SemanticIndex = 0;988elements[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;989elements[0].InputSlot = 0;990elements[0].AlignedByteOffset = offsetof(RenderVertex, pos);991elements[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;992elements[0].InstanceDataStepRate = 0;993994elements[1].SemanticName = "TEXCOORD";995elements[1].SemanticIndex = 0;996elements[1].Format = DXGI_FORMAT_R32G32_FLOAT;997elements[1].InputSlot = 0;998elements[1].AlignedByteOffset = offsetof(RenderVertex, tex);999elements[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;1000elements[1].InstanceDataStepRate = 0;10011002// elements[2].SemanticName = "COLOR";1003// elements[2].SemanticIndex = 0;1004// elements[2].Format = DXGI_FORMAT_R32G32B32_UINT;1005// elements[2].InputSlot = 0;1006// elements[2].AlignedByteOffset = offsetof(RenderVertex, color);1007// elements[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;1008// elements[2].InstanceDataStepRate = 0;10091010HRESULT res = dx11Device->CreateInputLayout(elements, ARRAYSIZE(elements), bytecode, bytecodeSize, &shader->vertexDeclare);1011if (FAILED(res))1012return;1013}10141015#if !RETRO_USE_ORIGINAL_CODE1016// Try to compile the pixel shader source if it exists1017sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Shaders/DX11/%s.hlsl", fileName);1018InitFileInfo(&info);1019if (LoadFile(&info, fullFilePath, FMODE_RB)) {1020uint8 *fileData = NULL;1021AllocateStorage((void **)&fileData, info.fileSize, DATASET_TMP, false);1022ReadBytes(&info, fileData, info.fileSize);1023CloseFile(&info);10241025UINT flags = D3DCOMPILE_ENABLE_STRICTNESS;1026if (engine.devMenu) {1027flags |= D3DCOMPILE_DEBUG;1028flags |= D3DCOMPILE_OPTIMIZATION_LEVEL0;1029flags |= D3DCOMPILE_WARNINGS_ARE_ERRORS;1030}1031else {1032flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;1033}10341035ID3DBlob *shaderBlob = nullptr;1036ID3DBlob *errorBlob = nullptr;1037HRESULT result = D3DCompile(fileData, info.fileSize, fullFilePath, defines, NULL, "PSMain", "ps_5_0", flags, 0, &shaderBlob, &errorBlob);10381039if (FAILED(result)) {1040if (errorBlob) {1041PrintLog(PRINT_NORMAL, "ERROR COMPILING PIXEL SHADER:\n%s", (char *)errorBlob->GetBufferPointer());1042errorBlob->Release();1043}10441045if (shaderBlob)1046shaderBlob->Release();1047}1048else {1049PrintLog(PRINT_NORMAL, "Successfully compiled pixel shader!");1050if (errorBlob)1051PrintLog(PRINT_NORMAL, "Pixel shader warnings:\n%s", (char *)errorBlob->GetBufferPointer());10521053if (FAILED(dx11Device->CreatePixelShader((DWORD *)shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), NULL,1054&shader->pixelShaderObject))) {1055if (shader->vertexShaderObject) {1056shader->vertexShaderObject->Release();1057shader->vertexShaderObject = NULL;1058}10591060RemoveStorageEntry((void **)&fileData);1061return;1062}1063}10641065RemoveStorageEntry((void **)&fileData);1066}1067else {1068#endif1069// if the pixel shader source doesn't exist, fall back and try to load the pixel shader bytecode1070sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Shaders/CSO-DX11/%s.fso", fileName);1071InitFileInfo(&info);1072if (LoadFile(&info, fullFilePath, FMODE_RB)) {1073uint8 *fileData = NULL;1074AllocateStorage((void **)&fileData, info.fileSize, DATASET_TMP, false);1075ReadBytes(&info, fileData, info.fileSize);1076CloseFile(&info);10771078if (FAILED(dx11Device->CreatePixelShader((DWORD *)fileData, info.fileSize, NULL, &shader->pixelShaderObject))) {1079if (shader->pixelShaderObject) {1080shader->pixelShaderObject->Release();1081shader->pixelShaderObject = NULL;1082}10831084RemoveStorageEntry((void **)&fileData);1085return;1086}10871088RemoveStorageEntry((void **)&fileData);1089}10901091#if !RETRO_USE_ORIGINAL_CODE1092}1093#endif10941095shaderCount++;1096}10971098bool RenderDevice::LoadBackupShader()1099{1100ShaderEntry *shader = &shaderList[0];1101sprintf_s(shader->name, sizeof(shader->name), "%s", "BACKUP");11021103const D3D_SHADER_MACRO defines[] = {1104#if RETRO_REV021105"RETRO_REV02", "1",1106#endif1107NULL, NULL1108};11091110void *bytecode = NULL;1111size_t bytecodeSize = 0;11121113// Try to compile the vertex shader source1114UINT flags = D3DCOMPILE_ENABLE_STRICTNESS;1115if (engine.devMenu) {1116flags |= D3DCOMPILE_DEBUG;1117flags |= D3DCOMPILE_OPTIMIZATION_LEVEL0;1118flags |= D3DCOMPILE_WARNINGS_ARE_ERRORS;1119}1120else {1121flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;1122}11231124ID3DBlob *shaderBlob = nullptr;1125ID3DBlob *errorBlob = nullptr;1126HRESULT result = D3DCompile(backupHLSL, strlen(backupHLSL), "BACKUP", defines, NULL, "VSMain", "vs_5_0", flags, 0, &shaderBlob, &errorBlob);11271128if (FAILED(result)) {1129if (errorBlob) {1130PrintLog(PRINT_NORMAL, "ERROR COMPILING VERTEX SHADER: %s", (char *)errorBlob->GetBufferPointer());1131errorBlob->Release();1132}11331134if (shaderBlob)1135shaderBlob->Release();11361137return false;1138}1139else {1140PrintLog(PRINT_NORMAL, "Successfully compiled vertex shader!");1141if (errorBlob)1142PrintLog(PRINT_NORMAL, "Vertex shader warnings:\n%s", (char *)errorBlob->GetBufferPointer());11431144if (FAILED(dx11Device->CreateVertexShader((DWORD *)shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), NULL,1145&shader->vertexShaderObject))) {1146if (shader->vertexShaderObject) {1147shader->vertexShaderObject->Release();1148shader->vertexShaderObject = NULL;1149}11501151return false;1152}1153#pragma comment(lib, "dxguid.lib")1154shader->vertexShaderObject->SetPrivateData(WKPDID_D3DDebugObjectName, strlen("BACKUP"), "BACKUP");1155}11561157bytecode = shaderBlob->GetBufferPointer();1158bytecodeSize = shaderBlob->GetBufferSize();11591160// create the vertex layout stuff using the vertex shader1161{1162D3D11_INPUT_ELEMENT_DESC elements[2];11631164elements[0].SemanticName = "SV_POSITION";1165elements[0].SemanticIndex = 0;1166elements[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;1167elements[0].InputSlot = 0;1168elements[0].AlignedByteOffset = offsetof(RenderVertex, pos);1169elements[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;1170elements[0].InstanceDataStepRate = 0;11711172elements[1].SemanticName = "TEXCOORD";1173elements[1].SemanticIndex = 0;1174elements[1].Format = DXGI_FORMAT_R32G32_FLOAT;1175elements[1].InputSlot = 0;1176elements[1].AlignedByteOffset = offsetof(RenderVertex, tex);1177elements[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;1178elements[1].InstanceDataStepRate = 0;11791180// elements[2].SemanticName = "COLOR";1181// elements[2].SemanticIndex = 0;1182// elements[2].Format = DXGI_FORMAT_R32G32B32_UINT;1183// elements[2].InputSlot = 0;1184// elements[2].AlignedByteOffset = offsetof(RenderVertex, color);1185// elements[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;1186// elements[2].InstanceDataStepRate = 0;11871188HRESULT res = dx11Device->CreateInputLayout(elements, ARRAYSIZE(elements), bytecode, bytecodeSize, &shader->vertexDeclare);1189if (FAILED(res))1190return false;1191}11921193// Try to compile the pixel shader source1194{1195UINT flags = D3DCOMPILE_ENABLE_STRICTNESS;1196if (engine.devMenu) {1197flags |= D3DCOMPILE_DEBUG;1198flags |= D3DCOMPILE_OPTIMIZATION_LEVEL0;1199flags |= D3DCOMPILE_WARNINGS_ARE_ERRORS;1200}1201else {1202flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;1203}12041205ID3DBlob *shaderBlob = nullptr;1206ID3DBlob *errorBlob = nullptr;1207HRESULT result = D3DCompile(backupHLSL, strlen(backupHLSL), "BACKUP", defines, NULL, "PSMain", "ps_5_0", flags, 0, &shaderBlob, &errorBlob);12081209if (FAILED(result)) {1210if (errorBlob) {1211PrintLog(PRINT_NORMAL, "ERROR COMPILING PIXEL SHADER:\n%s", (char *)errorBlob->GetBufferPointer());1212errorBlob->Release();1213}12141215if (shaderBlob)1216shaderBlob->Release();1217}1218else {1219PrintLog(PRINT_NORMAL, "Successfully compiled pixel shader!");1220if (errorBlob)1221PrintLog(PRINT_NORMAL, "Pixel shader warnings:\n%s", (char *)errorBlob->GetBufferPointer());12221223if (FAILED(dx11Device->CreatePixelShader((DWORD *)shaderBlob->GetBufferPointer(), shaderBlob->GetBufferSize(), NULL,1224&shader->pixelShaderObject))) {1225if (shader->vertexShaderObject) {1226shader->vertexShaderObject->Release();1227shader->vertexShaderObject = NULL;1228}12291230return false;1231}1232}1233}12341235shader->linear = videoSettings.windowed ? false : shader->linear;1236return true;1237}12381239bool RenderDevice::InitShaders()1240{1241D3D11_RASTERIZER_DESC rDesc = {};12421243D3D11_SAMPLER_DESC sPointDesc = {};1244D3D11_SAMPLER_DESC sLinearDesc = {};12451246// init1247rDesc.FillMode = D3D11_FILL_SOLID;1248rDesc.CullMode = D3D11_CULL_NONE;1249rDesc.FrontCounterClockwise = FALSE;1250rDesc.DepthBias = D3D11_DEFAULT_DEPTH_BIAS;1251rDesc.DepthBiasClamp = D3D11_DEFAULT_DEPTH_BIAS_CLAMP;1252rDesc.SlopeScaledDepthBias = D3D11_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;1253rDesc.DepthClipEnable = TRUE;1254rDesc.ScissorEnable = FALSE;1255rDesc.MultisampleEnable = FALSE;1256rDesc.AntialiasedLineEnable = FALSE;12571258// init1259sPointDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;1260sPointDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;1261sPointDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;1262sPointDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;1263sPointDesc.MipLODBias = 0;1264sPointDesc.MaxAnisotropy = 1;1265sPointDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;1266sPointDesc.BorderColor[0] = 1.0f;1267sPointDesc.BorderColor[1] = 1.0f;1268sPointDesc.BorderColor[2] = 1.0f;1269sPointDesc.BorderColor[3] = 1.0f;1270sPointDesc.MinLOD = -FLT_MAX;1271sPointDesc.MaxLOD = FLT_MAX;12721273sLinearDesc = sPointDesc;1274sLinearDesc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;12751276if (FAILED(dx11Device->CreateRasterizerState(&rDesc, &rasterState))) {1277// uh oh...1278}12791280if (FAILED(dx11Device->CreateSamplerState(&sPointDesc, &samplerPoint))) {1281// uh oh...1282}12831284if (FAILED(dx11Device->CreateSamplerState(&sLinearDesc, &samplerLinear))) {1285// uh oh...1286}12871288int32 maxShaders = 0;1289#if RETRO_USE_MOD_LOADER1290shaderCount = 0;1291#endif12921293if (videoSettings.shaderSupport) {1294LoadShader("None", false);1295LoadShader("Clean", true);1296LoadShader("CRT-Yeetron", true);1297LoadShader("CRT-Yee64", true);12981299#if RETRO_USE_MOD_LOADER1300// a place for mods to load custom shaders1301RunModCallbacks(MODCB_ONSHADERLOAD, NULL);1302userShaderCount = shaderCount;1303#endif13041305LoadShader("YUV-420", true);1306LoadShader("YUV-422", true);1307LoadShader("YUV-444", true);1308LoadShader("RGB-Image", true);1309maxShaders = shaderCount;1310}1311else {1312for (int32 s = 0; s < SHADER_COUNT; ++s) shaderList[s].linear = true;13131314shaderList[0].linear = videoSettings.windowed ? false : shaderList[0].linear;1315maxShaders = 1;1316shaderCount = 1;1317}13181319// Load backup shader if no shaders have been found1320if (!maxShaders) {1321PrintLog(PRINT_NORMAL, "[DX11] No shaders loaded correctly, attempting backup");1322maxShaders = 1;1323shaderCount = 1;1324if (!LoadBackupShader())1325PrintLog(PRINT_NORMAL, "[DX11] Failed to load backup shaders!");13261327}13281329videoSettings.shaderID = videoSettings.shaderID >= maxShaders ? 0 : videoSettings.shaderID;13301331return true;1332}13331334bool RenderDevice::SetupRendering()1335{1336// Init DX11 context & device1337UINT createDeviceFlags = 0;1338#ifdef _DEBUG1339createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;1340#endif13411342D3D_DRIVER_TYPE driverTypes[] = {1343D3D_DRIVER_TYPE_HARDWARE,1344D3D_DRIVER_TYPE_WARP,1345D3D_DRIVER_TYPE_REFERENCE,1346};1347UINT numDriverTypes = ARRAYSIZE(driverTypes);13481349D3D_FEATURE_LEVEL featureLevels[] = {1350D3D_FEATURE_LEVEL_11_1,1351D3D_FEATURE_LEVEL_11_0,1352D3D_FEATURE_LEVEL_10_1,1353D3D_FEATURE_LEVEL_10_0,1354};1355UINT numFeatureLevels = ARRAYSIZE(featureLevels);13561357HRESULT hr = 0;1358for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++) {1359driverType = driverTypes[driverTypeIndex];1360hr = D3D11CreateDevice(nullptr, driverType, nullptr, createDeviceFlags, featureLevels, ARRAYSIZE(featureLevels), D3D11_SDK_VERSION,1361&dx11Device, &featureLevel, &dx11Context);13621363if (hr == E_INVALIDARG) {1364// DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it1365hr = D3D11CreateDevice(nullptr, driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1, D3D11_SDK_VERSION,1366&dx11Device, &featureLevel, &dx11Context);1367}13681369if (SUCCEEDED(hr))1370break;1371}13721373if (FAILED(hr))1374return false;13751376ZeroMemory(&deviceIdentifier, sizeof(deviceIdentifier));13771378GetDisplays();13791380if (!InitGraphicsAPI() || !InitShaders())1381return false;13821383int32 size = videoSettings.pixWidth >= SCREEN_YSIZE ? videoSettings.pixWidth : SCREEN_YSIZE;1384scanlines = (ScanlineInfo *)malloc(size * sizeof(ScanlineInfo));1385memset(scanlines, 0, size * sizeof(ScanlineInfo));13861387videoSettings.windowState = WINDOWSTATE_ACTIVE;1388videoSettings.dimMax = 1.0;1389videoSettings.dimPercent = 1.0;13901391return true;1392}13931394void RenderDevice::GetDisplays()1395{1396std::vector<IDXGIAdapter *> adapterList = GetAdapterList();1397adapterCount = (int32)adapterList.size();13981399uint32 prevAdapter = dxAdapter;14001401HMONITOR windowMonitor = MonitorFromWindow(windowHandle, MONITOR_DEFAULTTOPRIMARY);1402for (int32 a = 0; a < adapterCount; ++a) {1403IDXGIOutput *pOutput;1404if (SUCCEEDED(adapterList[a]->EnumOutputs(0, &pOutput))) {1405DXGI_OUTPUT_DESC outputDesc;1406pOutput->GetDesc(&outputDesc);1407HMONITOR monitor = outputDesc.Monitor;14081409UINT modeCount;1410pOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &modeCount, nullptr);14111412DXGI_MODE_DESC *descArr = new DXGI_MODE_DESC[modeCount];1413pOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &modeCount, descArr);14141415std::vector<DXGI_MODE_DESC> adapterModeList;1416for (UINT i = 0; i < modeCount; i++) adapterModeList.push_back(descArr[i]);1417pOutput->Release();14181419displayWidth[a] = outputDesc.DesktopCoordinates.right - outputDesc.DesktopCoordinates.left;1420displayHeight[a] = outputDesc.DesktopCoordinates.bottom - outputDesc.DesktopCoordinates.top;14211422if (windowMonitor == monitor) {1423MONITORINFO lpmi;1424ZeroMemory(&lpmi, sizeof(lpmi));1425lpmi.cbSize = sizeof(MONITORINFO);14261427GetMonitorInfo(windowMonitor, &lpmi);1428dxAdapter = a;1429monitorDisplayRect = lpmi.rcMonitor;1430}14311432delete[] descArr;1433}1434}14351436DXGI_ADAPTER_DESC adapterIdentifier;1437ZeroMemory(&adapterIdentifier, sizeof(adapterIdentifier));1438adapterList[dxAdapter]->GetDesc(&adapterIdentifier);14391440// no change, don't reload anything1441if (memcmp(&deviceIdentifier, &adapterIdentifier.AdapterLuid, sizeof(deviceIdentifier)) == 0 && dxAdapter == prevAdapter)1442return;14431444deviceIdentifier = adapterIdentifier.AdapterLuid;14451446IDXGIOutput *pOutput;1447adapterList[dxAdapter]->EnumOutputs(0, &pOutput);14481449pOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, (UINT *)&displayCount, nullptr);1450if (displayInfo.displays)1451free(displayInfo.displays);14521453DXGI_MODE_DESC *descArr = new DXGI_MODE_DESC[displayCount];1454pOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, (UINT *)&displayCount, descArr);14551456displayInfo.displays = (decltype(displayInfo.displays))malloc(sizeof(DXGI_MODE_DESC) * displayCount);1457int32 newDisplayCount = 0;1458bool32 foundFullScreenDisplay = false;14591460for (int32 d = 0; d < displayCount; ++d) {1461memcpy(&displayInfo.displays[newDisplayCount].internal, &descArr[d], sizeof(DXGI_MODE_DESC));14621463int32 refreshRate = 0;14641465DXGI_RATIONAL *rate = &displayInfo.displays[newDisplayCount].refresh_rate;1466if (rate->Numerator > 0 && rate->Denominator > 0)1467refreshRate = rate->Numerator / rate->Denominator;14681469if (refreshRate >= 59 && (refreshRate <= 60 || refreshRate >= 120) && displayInfo.displays[newDisplayCount].height >= (SCREEN_YSIZE * 2)) {1470int32 prevRefreshRate = 0;1471if (d) {1472rate = &displayInfo.displays[newDisplayCount - 1].refresh_rate;14731474if (rate->Numerator > 0 && rate->Denominator > 0)1475prevRefreshRate = rate->Numerator / rate->Denominator;1476}14771478// remove duplicates1479if (d && displayInfo.displays[newDisplayCount].width == displayInfo.displays[newDisplayCount - 1].width1480&& displayInfo.displays[newDisplayCount].height == displayInfo.displays[newDisplayCount - 1].height1481&& refreshRate == prevRefreshRate) {1482memcpy(&displayInfo.displays[newDisplayCount - 1], &displayInfo.displays[newDisplayCount], sizeof(displayInfo.displays[0]));1483--newDisplayCount;1484}1485// remove "duds"1486else if (d && refreshRate == 60 && prevRefreshRate == 59) {1487memcpy(&displayInfo.displays[newDisplayCount - 1], &displayInfo.displays[newDisplayCount], sizeof(displayInfo.displays[0]));1488--newDisplayCount;1489}14901491if (videoSettings.fsWidth == displayInfo.displays[newDisplayCount].width1492&& videoSettings.fsHeight == displayInfo.displays[newDisplayCount].height)1493foundFullScreenDisplay = true;14941495++newDisplayCount;1496}1497}14981499delete[] descArr;15001501displayCount = newDisplayCount;1502if (!foundFullScreenDisplay) {1503videoSettings.fsWidth = 0;1504videoSettings.fsHeight = 0;1505videoSettings.refreshRate = 60; // 0;1506}1507}15081509void RenderDevice::GetWindowSize(int32 *width, int32 *height)1510{1511std::vector<IDXGIAdapter *> adapterList = GetAdapterList();15121513IDXGIOutput *pOutput;1514if (FAILED(adapterList[dxAdapter]->EnumOutputs(0, &pOutput))) {1515if (width)1516*width = 0;15171518if (height)1519*height = 0;15201521return;1522}15231524DXGI_OUTPUT_DESC outputDesc;1525pOutput->GetDesc(&outputDesc);15261527if (width)1528*width = outputDesc.DesktopCoordinates.right - outputDesc.DesktopCoordinates.left;15291530if (height)1531*height = outputDesc.DesktopCoordinates.bottom - outputDesc.DesktopCoordinates.top;1532}15331534void RenderDevice::ProcessEvent(MSG Msg)1535{1536bool handledMsg = false;15371538switch (Msg.message) {1539case WM_QUIT: isRunning = false; break;15401541// called when holding "ALT" down1542case WM_SYSKEYDOWN: {1543WPARAM activeButtons = Msg.wParam;1544switch (Msg.wParam) {1545// shift key1546case VK_SHIFT:1547activeButtons = MapVirtualKey(((Msg.lParam >> 16) & 0xFF), MAPVK_VSC_TO_VK_EX);1548break;15491550// CTRL key1551case VK_CONTROL:1552activeButtons = VK_LCONTROL + (((Msg.lParam >> 24) & 0xFF) & 1);1553break;15541555// ALT key1556case VK_MENU: activeButtons = VK_LMENU + (((Msg.lParam >> 24) & 0xFF) & 1); break;1557}15581559switch (Msg.wParam) {1560default:1561#if RETRO_INPUTDEVICE_KEYBOARD1562SKU::UpdateKeyState(activeButtons);1563handledMsg = true;1564#endif1565break;15661567case VK_RETURN: // alt + enter1568if (GetAsyncKeyState(VK_MENU)) {1569videoSettings.windowed ^= 1;1570UpdateGameWindow();1571changedVideoSettings = false;1572handledMsg = true;1573}15741575#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD1576RSDK::SKU::specialKeyStates[1] = true;1577#endif1578break;15791580case VK_F4: // alt + f41581if (GetAsyncKeyState(VK_MENU))1582isRunning = false;1583handledMsg = true;1584break;15851586case VK_F10:1587if (engine.devMenu)1588engine.showPaletteOverlay ^= 1;1589handledMsg = true;1590break;1591}15921593break;1594}15951596// regular keydown1597case WM_KEYDOWN: {1598WPARAM activeButtons = Msg.wParam;1599switch (Msg.wParam) {1600// shift key1601case VK_SHIFT:1602activeButtons = MapVirtualKey(((Msg.lParam >> 16) & 0xFF), MAPVK_VSC_TO_VK_EX);1603break;16041605// CTRL key1606case VK_CONTROL:1607activeButtons = VK_LCONTROL + (((Msg.lParam >> 24) & 0xFF) & 1);1608break;16091610// ALT key1611case VK_MENU: activeButtons = VK_LMENU + (((Msg.lParam >> 24) & 0xFF) & 1); break;1612}16131614// handledMsg = true;1615switch (Msg.wParam) {1616default:1617#if RETRO_INPUTDEVICE_KEYBOARD1618SKU::UpdateKeyState(activeButtons);1619handledMsg = false;1620#endif1621break;16221623case VK_BACK:1624if (engine.devMenu) {1625engine.gameSpeed = engine.fastForwardSpeed;1626handledMsg = true;1627}1628break;16291630case VK_ESCAPE:1631if (engine.devMenu) {1632#if RETRO_REV0U1633if (sceneInfo.state == ENGINESTATE_DEVMENU || RSDK::Legacy::gameMode == RSDK::Legacy::ENGINE_DEVMENU)1634#else1635if (sceneInfo.state == ENGINESTATE_DEVMENU)1636#endif1637CloseDevMenu();1638else1639OpenDevMenu();1640}1641else {1642#if RETRO_INPUTDEVICE_KEYBOARD1643SKU::UpdateKeyState(activeButtons);1644handledMsg = false;1645#endif1646}16471648#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD1649RSDK::SKU::specialKeyStates[0] = true;1650#endif1651break;16521653#if !RETRO_USE_ORIGINAL_CODE1654case VK_F1:1655if (engine.devMenu) {1656sceneInfo.listPos--;1657while (sceneInfo.listPos < sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart1658|| sceneInfo.listPos > sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd1659|| !sceneInfo.listCategory[sceneInfo.activeCategory].sceneCount) {1660sceneInfo.activeCategory--;1661if (sceneInfo.activeCategory >= sceneInfo.categoryCount) {1662sceneInfo.activeCategory = sceneInfo.categoryCount - 1;1663}1664sceneInfo.listPos = sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd - 1;1665}16661667#if RETRO_REV0U1668switch (engine.version) {1669default: break;1670case 5: LoadScene(); break;1671case 4:1672case 3: RSDK::Legacy::stageMode = RSDK::Legacy::STAGEMODE_LOAD; break;1673}1674#else1675LoadScene();1676#endif1677}1678break;16791680case VK_F2:1681if (engine.devMenu) {1682sceneInfo.listPos++;1683while (sceneInfo.listPos < sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart1684|| sceneInfo.listPos > sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetEnd1685|| !sceneInfo.listCategory[sceneInfo.activeCategory].sceneCount) {1686sceneInfo.activeCategory++;1687if (sceneInfo.activeCategory >= sceneInfo.categoryCount) {1688sceneInfo.activeCategory = 0;1689}1690sceneInfo.listPos = sceneInfo.listCategory[sceneInfo.activeCategory].sceneOffsetStart;1691}16921693#if RETRO_REV0U1694switch (engine.version) {1695default: break;1696case 5: LoadScene(); break;1697case 4:1698case 3: RSDK::Legacy::stageMode = RSDK::Legacy::STAGEMODE_LOAD; break;1699}1700#else1701LoadScene();1702#endif1703}1704break;1705#endif17061707case VK_F3:1708if (userShaderCount) {1709videoSettings.shaderID = (videoSettings.shaderID + 1) % userShaderCount;1710handledMsg = true;1711}1712break;17131714#if !RETRO_USE_ORIGINAL_CODE1715case VK_F4:1716if (engine.devMenu) {1717engine.showEntityInfo ^= 1;17181719handledMsg = true;1720}1721break;17221723case VK_F5:1724if (engine.devMenu) {1725// Quick-Reload1726#if RETRO_USE_MOD_LOADER1727if (GetAsyncKeyState(VK_CONTROL))1728RefreshModFolders();1729#endif17301731#if RETRO_REV0U1732switch (engine.version) {1733default: break;1734case 5: LoadScene(); break;1735case 4:1736case 3: RSDK::Legacy::stageMode = RSDK::Legacy::STAGEMODE_LOAD; break;1737}1738#else1739LoadScene();1740#endif1741}1742break;17431744case VK_F6:1745if (engine.devMenu && videoSettings.screenCount > 1)1746videoSettings.screenCount--;1747break;17481749case VK_F7:1750if (engine.devMenu && videoSettings.screenCount < SCREEN_COUNT)1751videoSettings.screenCount++;1752break;17531754case VK_F8:1755if (engine.devMenu) {1756engine.showUpdateRanges ^= 1;17571758handledMsg = true;1759}1760break;17611762case VK_F9:1763if (engine.devMenu) {1764showHitboxes ^= 1;17651766handledMsg = true;1767}1768break;17691770case VK_F10:1771if (engine.devMenu)1772engine.showPaletteOverlay ^= 1;1773break;1774#endif17751776case VK_INSERT:1777case VK_F11:1778if (engine.devMenu) {1779engine.frameStep = true;1780handledMsg = true;1781}1782break;17831784case VK_PAUSE:1785case VK_F12:1786if (engine.devMenu) {1787#if RETRO_REV0U1788switch (engine.version) {1789default: break;1790case 5:1791if (sceneInfo.state != ENGINESTATE_NONE)1792sceneInfo.state ^= ENGINESTATE_STEPOVER;1793break;1794case 4:1795case 3:1796if (RSDK::Legacy::stageMode != ENGINESTATE_NONE)1797RSDK::Legacy::stageMode ^= RSDK::Legacy::STAGEMODE_STEPOVER;1798break;1799}1800#else1801if (sceneInfo.state != ENGINESTATE_NONE)1802sceneInfo.state ^= ENGINESTATE_STEPOVER;1803#endif1804}1805break;1806}1807break;1808}18091810case WM_KEYUP:1811case WM_SYSKEYUP: {1812WPARAM activeButtons = Msg.wParam;1813switch (Msg.wParam) {1814case VK_SHIFT: activeButtons = MapVirtualKey(((Msg.lParam >> 16) & 0xFF), MAPVK_VSC_TO_VK_EX); break;18151816case VK_CONTROL: activeButtons = VK_LCONTROL + ((Msg.lParam >> 24) & 1); break;18171818case VK_MENU: // ALT key1819activeButtons = VK_LMENU + ((Msg.lParam >> 24) & 1);1820break;1821}18221823switch (Msg.wParam) {1824default:1825#if RETRO_INPUTDEVICE_KEYBOARD1826SKU::ClearKeyState(activeButtons);1827#endif1828break;18291830#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD1831case VK_ESCAPE:1832RSDK::SKU::specialKeyStates[0] = false;1833SKU::ClearKeyState(activeButtons);1834break;18351836case VK_RETURN:1837RSDK::SKU::specialKeyStates[1] = false;1838SKU::ClearKeyState(activeButtons);1839break;1840#endif18411842case VK_BACK:1843engine.gameSpeed = 1;1844handledMsg = true;1845break;1846}18471848break;1849}18501851case WM_LBUTTONDOWN: touchInfo.down[0] = 1; touchInfo.count = 1;18521853#if !RETRO_REV021854RSDK::SKU::buttonDownCount++;1855#endif18561857handledMsg = true;1858break;18591860case WM_LBUTTONUP: touchInfo.down[0] = 0; touchInfo.count = 0;18611862#if !RETRO_REV021863RSDK::SKU::buttonDownCount--;1864#endif18651866handledMsg = true;1867break;18681869case WM_MBUTTONDOWN: handledMsg = true; break;18701871case WM_RBUTTONDOWN: handledMsg = true;1872#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD1873RSDK::SKU::specialKeyStates[3] = true;1874RSDK::SKU::buttonDownCount++;1875#endif1876break;18771878case WM_RBUTTONUP: handledMsg = true;1879#if !RETRO_REV02 && RETRO_INPUTDEVICE_KEYBOARD1880RSDK::SKU::specialKeyStates[3] = false;1881RSDK::SKU::buttonDownCount--;1882#endif1883break;1884}18851886if (!handledMsg)1887DispatchMessage(&Msg);1888}18891890bool RenderDevice::ProcessEvents()1891{1892MSG Msg = {};1893while (PeekMessage(&Msg, NULL, 0, 0, true)) {1894ProcessEvent(Msg);18951896if (!isRunning)1897return false;1898}18991900return isRunning;1901}19021903LRESULT CALLBACK RenderDevice::WindowEventCallback(HWND hRecipient, UINT message, WPARAM wParam, LPARAM lParam)1904{1905bool32 forceExit = false;1906GUID deviceGUID = KSCATEGORY_AUDIO;19071908switch (message) {1909case WM_CREATE: {1910if (deviceNotif)1911return 0;19121913DEV_BROADCAST_DEVICEINTERFACE filter;1914filter.dbcc_name[0] = 0;1915filter.dbcc_reserved = 0;1916filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);1917filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;1918filter.dbcc_classguid = deviceGUID;19191920deviceNotif = RegisterDeviceNotification(hRecipient, &filter, DEVICE_NOTIFY_WINDOW_HANDLE);19211922forceExit = true;1923break;1924}19251926case WM_DESTROY:1927if (deviceNotif) {1928UnregisterDeviceNotification(deviceNotif);1929deviceNotif = 0;1930}19311932isRunning = false;1933forceExit = true;1934break;19351936case WM_MOVE:1937case WM_SIZE: forceExit = true; break;19381939case WM_ACTIVATE:1940if (wParam) {1941if (!videoSettings.windowState)1942return 0;19431944if (AudioDevice::audioFocus == 1) {1945AudioDevice::audioFocus = 0;1946if (AudioDevice::sourceVoice)1947AudioDevice::sourceVoice->Start(0, 0);1948}19491950GetDisplays();1951videoSettings.windowState = WINDOWSTATE_ACTIVE;1952}1953else {1954touchInfo.down[0] = false;1955touchInfo.count = 0;1956if (!videoSettings.windowState)1957return 0;1958#if !RETRO_USE_ORIGINAL_CODE1959if (customSettings.disableFocusPause)1960return 0;1961#endif19621963if (!AudioDevice::audioFocus) {1964AudioDevice::audioFocus = 1;1965if (AudioDevice::sourceVoice)1966AudioDevice::sourceVoice->Stop(0, 0);1967}19681969videoSettings.windowState = WINDOWSTATE_INACTIVE;1970}19711972forceExit = true;1973break;19741975case WM_PAINT:1976BeginPaint(hRecipient, &Paint);1977EndPaint(hRecipient, &Paint);19781979forceExit = true;1980break;19811982case WM_DEVICECHANGE: {1983DEV_BROADCAST_DEVICEINTERFACE *deviceInterace = (DEV_BROADCAST_DEVICEINTERFACE *)lParam;19841985if ((wParam == DBT_DEVICEARRIVAL || wParam == DBT_DEVICEREMOVECOMPLETE) && deviceInterace1986&& deviceInterace->dbcc_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {19871988if (memcmp(&deviceInterace->dbcc_classguid, &deviceGUID, sizeof(deviceGUID)) == 0) {1989AudioDevice::audioState = 30;1990}1991}19921993#if RETRO_INPUTDEVICE_XINPUT1994SKU::UpdateXInputDevices();1995#endif19961997#if RETRO_INPUTDEVICE_RAWINPUT1998SKU::InitHIDAPI();1999#endif20002001#if RETRO_INPUTDEVICE_XINPUT2002SKU::InitXInputAPI();2003#endif20042005forceExit = true;2006break;2007}20082009#if RETRO_INPUTDEVICE_RAWINPUT2010case WM_INPUT:2011SKU::UpdateHIDButtonStates((HRAWINPUT)lParam);20122013forceExit = true;2014break;2015#endif20162017case WM_SYSCOMMAND: {2018int32 param = wParam & 0xFFF0;2019if (param == SC_MINIMIZE) {2020touchInfo.down[0] = 0;2021touchInfo.count = 0;2022if (videoSettings.windowState) {2023PauseSound();2024videoSettings.windowState = WINDOWSTATE_INACTIVE;2025}2026}2027else if (param == SC_MAXIMIZE && videoSettings.windowState != WINDOWSTATE_UNINITIALIZED) {2028ResumeSound();2029videoSettings.windowState = WINDOWSTATE_ACTIVE;2030}20312032break;2033}20342035case WM_MENUSELECT:2036case WM_ENTERSIZEMOVE:2037touchInfo.down[0] = 0;2038touchInfo.count = 0;20392040forceExit = true;2041break;20422043case WM_EXITSIZEMOVE:2044GetDisplays();20452046forceExit = true;2047break;20482049default: break;2050}20512052if (forceExit)2053return 0;2054else2055return DefWindowProc(hRecipient, message, wParam, lParam);2056}20572058void RenderDevice::SetupImageTexture(int32 width, int32 height, uint8 *imagePixels)2059{2060if (!imagePixels)2061return;20622063D3D11_MAPPED_SUBRESOURCE mappedResource;2064if (SUCCEEDED(dx11Context->Map(imageTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource))) {2065DWORD *pixels = (DWORD *)mappedResource.pData;2066int32 pitch = (mappedResource.RowPitch >> 2) - width;20672068uint32 *imagePixels32 = (uint32 *)imagePixels;2069for (int32 y = 0; y < height; ++y) {2070for (int32 x = 0; x < width; ++x) {2071*pixels++ = *imagePixels32++;2072}20732074pixels += pitch;2075}20762077dx11Context->Unmap(imageTexture, 0);2078}2079}20802081void RenderDevice::SetupVideoTexture_YUV420(int32 width, int32 height, uint8 *yPlane, uint8 *uPlane, uint8 *vPlane, int32 strideY, int32 strideU,2082int32 strideV)2083{2084D3D11_MAPPED_SUBRESOURCE mappedResource;2085if (SUCCEEDED(dx11Context->Map(imageTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource))) {2086DWORD *pixels = (DWORD *)mappedResource.pData;2087int32 pitch = (mappedResource.RowPitch >> 2) - width;20882089if (videoSettings.shaderSupport) {2090// Shaders are supported! lets watch this video in full color!2091for (int32 y = 0; y < height; ++y) {2092for (int32 x = 0; x < width; ++x) {2093*pixels++ = (yPlane[x] << 16) | 0xFF000000;2094}20952096pixels += pitch;2097yPlane += strideY;2098}20992100pixels = (DWORD *)mappedResource.pData;2101pitch = (mappedResource.RowPitch >> 2) - (width >> 1);2102for (int32 y = 0; y < (height >> 1); ++y) {2103for (int32 x = 0; x < (width >> 1); ++x) {2104*pixels++ |= (vPlane[x] << 0) | (uPlane[x] << 8) | 0xFF000000;2105}21062107pixels += pitch;2108uPlane += strideU;2109vPlane += strideV;2110}2111}2112else {2113// No shader support means no YUV support! at least use the brightness to show it in grayscale!2114for (int32 y = 0; y < height; ++y) {2115for (int32 x = 0; x < width; ++x) {2116int32 brightness = yPlane[x];2117*pixels++ = (brightness << 0) | (brightness << 8) | (brightness << 16) | 0xFF000000;2118}21192120pixels += pitch;2121yPlane += strideY;2122}2123}21242125dx11Context->Unmap(imageTexture, 0);2126}2127}2128void RenderDevice::SetupVideoTexture_YUV422(int32 width, int32 height, uint8 *yPlane, uint8 *uPlane, uint8 *vPlane, int32 strideY, int32 strideU,2129int32 strideV)2130{2131D3D11_MAPPED_SUBRESOURCE mappedResource;2132if (SUCCEEDED(dx11Context->Map(imageTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource))) {2133DWORD *pixels = (DWORD *)mappedResource.pData;2134int32 pitch = (mappedResource.RowPitch >> 2) - width;21352136if (videoSettings.shaderSupport) {2137// Shaders are supported! lets watch this video in full color!2138for (int32 y = 0; y < height; ++y) {2139for (int32 x = 0; x < width; ++x) {2140*pixels++ = (yPlane[x] << 16) | 0xFF000000;2141}21422143pixels += pitch;2144yPlane += strideY;2145}21462147pixels = (DWORD *)mappedResource.pData;2148pitch = (mappedResource.RowPitch >> 2) - (width >> 1);2149for (int32 y = 0; y < height; ++y) {2150for (int32 x = 0; x < (width >> 1); ++x) {2151*pixels++ |= (vPlane[x] << 0) | (uPlane[x] << 8) | 0xFF000000;2152}21532154pixels += pitch;2155uPlane += strideU;2156vPlane += strideV;2157}2158}2159else {2160// No shader support means no YUV support! at least use the brightness to show it in grayscale!2161for (int32 y = 0; y < height; ++y) {2162for (int32 x = 0; x < width; ++x) {2163int32 brightness = yPlane[x];2164*pixels++ = (brightness << 0) | (brightness << 8) | (brightness << 16) | 0xFF000000;2165}21662167pixels += pitch;2168yPlane += strideY;2169}2170}21712172dx11Context->Unmap(imageTexture, 0);2173}2174}2175void RenderDevice::SetupVideoTexture_YUV444(int32 width, int32 height, uint8 *yPlane, uint8 *uPlane, uint8 *vPlane, int32 strideY, int32 strideU,2176int32 strideV)2177{2178D3D11_MAPPED_SUBRESOURCE mappedResource;2179if (SUCCEEDED(dx11Context->Map(imageTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource))) {2180DWORD *pixels = (DWORD *)mappedResource.pData;2181int32 pitch = (mappedResource.RowPitch >> 2) - width;21822183if (videoSettings.shaderSupport) {2184// Shaders are supported! lets watch this video in full color!2185for (int32 y = 0; y < height; ++y) {2186int32 pos1 = yPlane - vPlane;2187int32 pos2 = uPlane - vPlane;2188uint8 *pixV = vPlane;2189for (int32 x = 0; x < width; ++x) {2190*pixels++ = pixV[0] | (pixV[pos2] << 8) | (pixV[pos1] << 16) | 0xFF000000;2191pixV++;2192}21932194pixels += pitch;2195yPlane += strideY;2196uPlane += strideU;2197vPlane += strideV;2198}2199}2200else {2201// No shader support means no YUV support! at least use the brightness to show it in grayscale!2202for (int32 y = 0; y < height; ++y) {2203for (int32 x = 0; x < width; ++x) {2204int32 brightness = yPlane[x];2205*pixels++ = (brightness << 0) | (brightness << 8) | (brightness << 16) | 0xFF000000;2206}22072208pixels += pitch;2209yPlane += strideY;2210}2211}22122213dx11Context->Unmap(imageTexture, 0);2214}2215}221622172218