17ec681f3Smrg/**************************************************************************
27ec681f3Smrg *
37ec681f3Smrg * Copyright 2012-2021 VMware, Inc.
47ec681f3Smrg * All Rights Reserved.
57ec681f3Smrg *
67ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a copy
77ec681f3Smrg * of this software and associated documentation files (the "Software"), to deal
87ec681f3Smrg * in the Software without restriction, including without limitation the rights
97ec681f3Smrg * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
107ec681f3Smrg * copies of the Software, and to permit persons to whom the Software is
117ec681f3Smrg * furnished to do so, subject to the following conditions:
127ec681f3Smrg *
137ec681f3Smrg * The above copyright notice and this permission notice shall be included in
147ec681f3Smrg * all copies or substantial portions of the Software.
157ec681f3Smrg *
167ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
177ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
187ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
197ec681f3Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
207ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
217ec681f3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
227ec681f3Smrg * THE SOFTWARE.
237ec681f3Smrg *
247ec681f3Smrg **************************************************************************/
257ec681f3Smrg
267ec681f3Smrg
277ec681f3Smrg#include <stdio.h>
287ec681f3Smrg#include <stddef.h>
297ec681f3Smrg#include <string.h>
307ec681f3Smrg
317ec681f3Smrg#include <initguid.h>
327ec681f3Smrg#include <windows.h>
337ec681f3Smrg
347ec681f3Smrg#include <d3d11.h>
357ec681f3Smrg
367ec681f3Smrg#include <wrl/client.h>
377ec681f3Smrg
387ec681f3Smrgusing Microsoft::WRL::ComPtr;
397ec681f3Smrg
407ec681f3Smrg#include "tri_vs_4_0.h"
417ec681f3Smrg#include "tri_ps_4_0.h"
427ec681f3Smrg
437ec681f3Smrg
447ec681f3Smrgint
457ec681f3Smrgmain(int argc, char *argv[])
467ec681f3Smrg{
477ec681f3Smrg    HRESULT hr;
487ec681f3Smrg
497ec681f3Smrg    HINSTANCE hInstance = GetModuleHandle(nullptr);
507ec681f3Smrg
517ec681f3Smrg    WNDCLASSEX wc = {
527ec681f3Smrg        sizeof(WNDCLASSEX),
537ec681f3Smrg        CS_CLASSDC,
547ec681f3Smrg        DefWindowProc,
557ec681f3Smrg        0,
567ec681f3Smrg        0,
577ec681f3Smrg        hInstance,
587ec681f3Smrg        nullptr,
597ec681f3Smrg        nullptr,
607ec681f3Smrg        nullptr,
617ec681f3Smrg        nullptr,
627ec681f3Smrg        "tri",
637ec681f3Smrg        nullptr
647ec681f3Smrg    };
657ec681f3Smrg    RegisterClassEx(&wc);
667ec681f3Smrg
677ec681f3Smrg    const int WindowWidth = 250;
687ec681f3Smrg    const int WindowHeight = 250;
697ec681f3Smrg
707ec681f3Smrg    DWORD dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW | WS_VISIBLE;
717ec681f3Smrg
727ec681f3Smrg    RECT rect = {0, 0, WindowWidth, WindowHeight};
737ec681f3Smrg    AdjustWindowRect(&rect, dwStyle, FALSE);
747ec681f3Smrg
757ec681f3Smrg    HWND hWnd = CreateWindow(wc.lpszClassName,
767ec681f3Smrg                             "Simple example using DirectX10",
777ec681f3Smrg                             dwStyle,
787ec681f3Smrg                             CW_USEDEFAULT, CW_USEDEFAULT,
797ec681f3Smrg                             rect.right - rect.left,
807ec681f3Smrg                             rect.bottom - rect.top,
817ec681f3Smrg                             nullptr,
827ec681f3Smrg                             nullptr,
837ec681f3Smrg                             hInstance,
847ec681f3Smrg                             nullptr);
857ec681f3Smrg    if (!hWnd) {
867ec681f3Smrg        return EXIT_FAILURE;
877ec681f3Smrg    }
887ec681f3Smrg
897ec681f3Smrg    UINT Flags = 0;
907ec681f3Smrg    hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_NULL, 0, D3D11_CREATE_DEVICE_DEBUG, nullptr, 0, D3D11_SDK_VERSION, nullptr, nullptr, nullptr);
917ec681f3Smrg    if (SUCCEEDED(hr)) {
927ec681f3Smrg        Flags |= D3D11_CREATE_DEVICE_DEBUG;
937ec681f3Smrg    }
947ec681f3Smrg
957ec681f3Smrg    static const D3D_FEATURE_LEVEL FeatureLevels[] = {
967ec681f3Smrg        D3D_FEATURE_LEVEL_10_0
977ec681f3Smrg    };
987ec681f3Smrg
997ec681f3Smrg    HMODULE hSoftware = LoadLibraryA("d3d10sw.dll");
1007ec681f3Smrg    if (!hSoftware) {
1017ec681f3Smrg       return EXIT_FAILURE;
1027ec681f3Smrg    }
1037ec681f3Smrg
1047ec681f3Smrg    DXGI_SWAP_CHAIN_DESC SwapChainDesc;
1057ec681f3Smrg    ZeroMemory(&SwapChainDesc, sizeof SwapChainDesc);
1067ec681f3Smrg    SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;;
1077ec681f3Smrg    SwapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
1087ec681f3Smrg    SwapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
1097ec681f3Smrg    SwapChainDesc.SampleDesc.Quality = 0;
1107ec681f3Smrg    SwapChainDesc.SampleDesc.Count = 1;
1117ec681f3Smrg    SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
1127ec681f3Smrg    SwapChainDesc.BufferCount = 2;
1137ec681f3Smrg    SwapChainDesc.OutputWindow = hWnd;
1147ec681f3Smrg    SwapChainDesc.Windowed = true;
1157ec681f3Smrg    SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
1167ec681f3Smrg
1177ec681f3Smrg    ComPtr<ID3D11Device> pDevice;
1187ec681f3Smrg    ComPtr<ID3D11DeviceContext> pDeviceContext;
1197ec681f3Smrg    ComPtr<IDXGISwapChain> pSwapChain;
1207ec681f3Smrg    hr = D3D11CreateDeviceAndSwapChain(nullptr,
1217ec681f3Smrg                                       D3D_DRIVER_TYPE_SOFTWARE,
1227ec681f3Smrg                                       hSoftware,
1237ec681f3Smrg                                       Flags,
1247ec681f3Smrg                                       FeatureLevels,
1257ec681f3Smrg                                       _countof(FeatureLevels),
1267ec681f3Smrg                                       D3D11_SDK_VERSION,
1277ec681f3Smrg                                       &SwapChainDesc,
1287ec681f3Smrg                                       &pSwapChain,
1297ec681f3Smrg                                       &pDevice,
1307ec681f3Smrg                                       nullptr, /* pFeatureLevel */
1317ec681f3Smrg                                       &pDeviceContext);
1327ec681f3Smrg    if (FAILED(hr)) {
1337ec681f3Smrg        return EXIT_FAILURE;
1347ec681f3Smrg    }
1357ec681f3Smrg
1367ec681f3Smrg    ComPtr<IDXGIDevice> pDXGIDevice;
1377ec681f3Smrg    hr = pDevice->QueryInterface(IID_IDXGIDevice, (void **)&pDXGIDevice);
1387ec681f3Smrg    if (FAILED(hr)) {
1397ec681f3Smrg        return EXIT_FAILURE;
1407ec681f3Smrg    }
1417ec681f3Smrg
1427ec681f3Smrg    ComPtr<IDXGIAdapter> pAdapter;
1437ec681f3Smrg    hr = pDXGIDevice->GetAdapter(&pAdapter);
1447ec681f3Smrg    if (FAILED(hr)) {
1457ec681f3Smrg        return EXIT_FAILURE;
1467ec681f3Smrg    }
1477ec681f3Smrg
1487ec681f3Smrg    DXGI_ADAPTER_DESC Desc;
1497ec681f3Smrg    hr = pAdapter->GetDesc(&Desc);
1507ec681f3Smrg    if (FAILED(hr)) {
1517ec681f3Smrg        return EXIT_FAILURE;
1527ec681f3Smrg    }
1537ec681f3Smrg
1547ec681f3Smrg    printf("using %S\n", Desc.Description);
1557ec681f3Smrg
1567ec681f3Smrg    ComPtr<ID3D11Texture2D> pBackBuffer;
1577ec681f3Smrg    hr = pSwapChain->GetBuffer(0, IID_ID3D11Texture2D, (void **)&pBackBuffer);
1587ec681f3Smrg    if (FAILED(hr)) {
1597ec681f3Smrg        return EXIT_FAILURE;
1607ec681f3Smrg    }
1617ec681f3Smrg
1627ec681f3Smrg    D3D11_RENDER_TARGET_VIEW_DESC RenderTargetViewDesc;
1637ec681f3Smrg    ZeroMemory(&RenderTargetViewDesc, sizeof RenderTargetViewDesc);
1647ec681f3Smrg    RenderTargetViewDesc.Format = SwapChainDesc.BufferDesc.Format;
1657ec681f3Smrg    RenderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
1667ec681f3Smrg    RenderTargetViewDesc.Texture2D.MipSlice = 0;
1677ec681f3Smrg
1687ec681f3Smrg    ComPtr<ID3D11RenderTargetView> pRenderTargetView;
1697ec681f3Smrg    hr = pDevice->CreateRenderTargetView(pBackBuffer.Get(), &RenderTargetViewDesc, &pRenderTargetView);
1707ec681f3Smrg    if (FAILED(hr)) {
1717ec681f3Smrg        return EXIT_FAILURE;
1727ec681f3Smrg    }
1737ec681f3Smrg
1747ec681f3Smrg    pDeviceContext->OMSetRenderTargets(1, pRenderTargetView.GetAddressOf(), nullptr);
1757ec681f3Smrg
1767ec681f3Smrg
1777ec681f3Smrg    const float clearColor[4] = { 0.3f, 0.1f, 0.3f, 1.0f };
1787ec681f3Smrg    pDeviceContext->ClearRenderTargetView(pRenderTargetView.Get(), clearColor);
1797ec681f3Smrg
1807ec681f3Smrg    ComPtr<ID3D11VertexShader> pVertexShader;
1817ec681f3Smrg    hr = pDevice->CreateVertexShader(g_VS, sizeof g_VS, nullptr, &pVertexShader);
1827ec681f3Smrg    if (FAILED(hr)) {
1837ec681f3Smrg        return EXIT_FAILURE;
1847ec681f3Smrg    }
1857ec681f3Smrg
1867ec681f3Smrg    struct Vertex {
1877ec681f3Smrg        float position[4];
1887ec681f3Smrg        float color[4];
1897ec681f3Smrg    };
1907ec681f3Smrg
1917ec681f3Smrg    static const D3D11_INPUT_ELEMENT_DESC InputElementDescs[] = {
1927ec681f3Smrg        { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(Vertex, position), D3D11_INPUT_PER_VERTEX_DATA, 0 },
1937ec681f3Smrg        { "COLOR",    0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(Vertex, color),    D3D11_INPUT_PER_VERTEX_DATA, 0 }
1947ec681f3Smrg    };
1957ec681f3Smrg
1967ec681f3Smrg    ComPtr<ID3D11InputLayout> pVertexLayout;
1977ec681f3Smrg    hr = pDevice->CreateInputLayout(InputElementDescs,
1987ec681f3Smrg                                    _countof(InputElementDescs),
1997ec681f3Smrg                                    g_VS, sizeof g_VS,
2007ec681f3Smrg                                    &pVertexLayout);
2017ec681f3Smrg    if (FAILED(hr)) {
2027ec681f3Smrg        return EXIT_FAILURE;
2037ec681f3Smrg    }
2047ec681f3Smrg
2057ec681f3Smrg    pDeviceContext->IASetInputLayout(pVertexLayout.Get());
2067ec681f3Smrg
2077ec681f3Smrg    ComPtr<ID3D11PixelShader> pPixelShader;
2087ec681f3Smrg    hr = pDevice->CreatePixelShader(g_PS, sizeof g_PS, nullptr, &pPixelShader);
2097ec681f3Smrg    if (FAILED(hr)) {
2107ec681f3Smrg        return EXIT_FAILURE;
2117ec681f3Smrg    }
2127ec681f3Smrg
2137ec681f3Smrg    pDeviceContext->VSSetShader(pVertexShader.Get(), nullptr, 0);
2147ec681f3Smrg    pDeviceContext->PSSetShader(pPixelShader.Get(), nullptr, 0);
2157ec681f3Smrg
2167ec681f3Smrg    static const Vertex vertices[] = {
2177ec681f3Smrg        { { -0.9f, -0.9f, 0.5f, 1.0f}, { 0.8f, 0.0f, 0.0f, 0.1f } },
2187ec681f3Smrg        { {  0.9f, -0.9f, 0.5f, 1.0f}, { 0.0f, 0.9f, 0.0f, 0.1f } },
2197ec681f3Smrg        { {  0.0f,  0.9f, 0.5f, 1.0f}, { 0.0f, 0.0f, 0.7f, 0.1f } },
2207ec681f3Smrg    };
2217ec681f3Smrg
2227ec681f3Smrg    D3D11_BUFFER_DESC BufferDesc;
2237ec681f3Smrg    ZeroMemory(&BufferDesc, sizeof BufferDesc);
2247ec681f3Smrg    BufferDesc.Usage = D3D11_USAGE_DYNAMIC;
2257ec681f3Smrg    BufferDesc.ByteWidth = sizeof vertices;
2267ec681f3Smrg    BufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
2277ec681f3Smrg    BufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
2287ec681f3Smrg    BufferDesc.MiscFlags = 0;
2297ec681f3Smrg
2307ec681f3Smrg    D3D11_SUBRESOURCE_DATA BufferData;
2317ec681f3Smrg    BufferData.pSysMem = vertices;
2327ec681f3Smrg    BufferData.SysMemPitch = 0;
2337ec681f3Smrg    BufferData.SysMemSlicePitch = 0;
2347ec681f3Smrg
2357ec681f3Smrg    ComPtr<ID3D11Buffer> pVertexBuffer;
2367ec681f3Smrg    hr = pDevice->CreateBuffer(&BufferDesc, &BufferData, &pVertexBuffer);
2377ec681f3Smrg    if (FAILED(hr)) {
2387ec681f3Smrg        return EXIT_FAILURE;
2397ec681f3Smrg    }
2407ec681f3Smrg
2417ec681f3Smrg    UINT Stride = sizeof(Vertex);
2427ec681f3Smrg    UINT Offset = 0;
2437ec681f3Smrg    pDeviceContext->IASetVertexBuffers(0, 1, pVertexBuffer.GetAddressOf(), &Stride, &Offset);
2447ec681f3Smrg
2457ec681f3Smrg    D3D11_VIEWPORT ViewPort;
2467ec681f3Smrg    ViewPort.TopLeftX = 0;
2477ec681f3Smrg    ViewPort.TopLeftY = 0;
2487ec681f3Smrg    ViewPort.Width = WindowWidth;
2497ec681f3Smrg    ViewPort.Height = WindowHeight;
2507ec681f3Smrg    ViewPort.MinDepth = 0.0f;
2517ec681f3Smrg    ViewPort.MaxDepth = 1.0f;
2527ec681f3Smrg    pDeviceContext->RSSetViewports(1, &ViewPort);
2537ec681f3Smrg
2547ec681f3Smrg    D3D11_RASTERIZER_DESC RasterizerDesc;
2557ec681f3Smrg    ZeroMemory(&RasterizerDesc, sizeof RasterizerDesc);
2567ec681f3Smrg    RasterizerDesc.CullMode = D3D11_CULL_NONE;
2577ec681f3Smrg    RasterizerDesc.FillMode = D3D11_FILL_SOLID;
2587ec681f3Smrg    RasterizerDesc.FrontCounterClockwise = true;
2597ec681f3Smrg    RasterizerDesc.DepthClipEnable = true;
2607ec681f3Smrg    ComPtr<ID3D11RasterizerState> pRasterizerState;
2617ec681f3Smrg    hr = pDevice->CreateRasterizerState(&RasterizerDesc, &pRasterizerState);
2627ec681f3Smrg    if (FAILED(hr)) {
2637ec681f3Smrg        return EXIT_FAILURE;
2647ec681f3Smrg    }
2657ec681f3Smrg    pDeviceContext->RSSetState(pRasterizerState.Get());
2667ec681f3Smrg
2677ec681f3Smrg    pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
2687ec681f3Smrg
2697ec681f3Smrg    pDeviceContext->Draw(_countof(vertices), 0);
2707ec681f3Smrg
2717ec681f3Smrg    pSwapChain->Present(0, 0);
2727ec681f3Smrg
2737ec681f3Smrg    Sleep(1000);
2747ec681f3Smrg
2757ec681f3Smrg    ID3D11Buffer *pNullBuffer = nullptr;
2767ec681f3Smrg    UINT NullStride = 0;
2777ec681f3Smrg    UINT NullOffset = 0;
2787ec681f3Smrg    pDeviceContext->IASetVertexBuffers(0, 1, &pNullBuffer, &NullStride, &NullOffset);
2797ec681f3Smrg
2807ec681f3Smrg    pDeviceContext->OMSetRenderTargets(0, nullptr, nullptr);
2817ec681f3Smrg
2827ec681f3Smrg    pDeviceContext->IASetInputLayout(nullptr);
2837ec681f3Smrg
2847ec681f3Smrg    pDeviceContext->VSSetShader(nullptr, nullptr, 0);
2857ec681f3Smrg
2867ec681f3Smrg    pDeviceContext->PSSetShader(nullptr, nullptr, 0);
2877ec681f3Smrg
2887ec681f3Smrg    pDeviceContext->RSSetState(nullptr);
2897ec681f3Smrg
2907ec681f3Smrg    DestroyWindow(hWnd);
2917ec681f3Smrg
2927ec681f3Smrg    return EXIT_SUCCESS;
2937ec681f3Smrg}
2947ec681f3Smrg
295