1/**************************************************************************
2 *
3 * Copyright 2012-2021 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 **************************************************************************/
25
26
27#include <stdio.h>
28#include <stddef.h>
29#include <string.h>
30
31#include <initguid.h>
32#include <windows.h>
33
34#include <d3d11.h>
35
36#include <wrl/client.h>
37
38using Microsoft::WRL::ComPtr;
39
40#include "tri_vs_4_0.h"
41#include "tri_ps_4_0.h"
42
43
44int
45main(int argc, char *argv[])
46{
47    HRESULT hr;
48
49    HINSTANCE hInstance = GetModuleHandle(nullptr);
50
51    WNDCLASSEX wc = {
52        sizeof(WNDCLASSEX),
53        CS_CLASSDC,
54        DefWindowProc,
55        0,
56        0,
57        hInstance,
58        nullptr,
59        nullptr,
60        nullptr,
61        nullptr,
62        "tri",
63        nullptr
64    };
65    RegisterClassEx(&wc);
66
67    const int WindowWidth = 250;
68    const int WindowHeight = 250;
69
70    DWORD dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW | WS_VISIBLE;
71
72    RECT rect = {0, 0, WindowWidth, WindowHeight};
73    AdjustWindowRect(&rect, dwStyle, FALSE);
74
75    HWND hWnd = CreateWindow(wc.lpszClassName,
76                             "Simple example using DirectX10",
77                             dwStyle,
78                             CW_USEDEFAULT, CW_USEDEFAULT,
79                             rect.right - rect.left,
80                             rect.bottom - rect.top,
81                             nullptr,
82                             nullptr,
83                             hInstance,
84                             nullptr);
85    if (!hWnd) {
86        return EXIT_FAILURE;
87    }
88
89    UINT Flags = 0;
90    hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_NULL, 0, D3D11_CREATE_DEVICE_DEBUG, nullptr, 0, D3D11_SDK_VERSION, nullptr, nullptr, nullptr);
91    if (SUCCEEDED(hr)) {
92        Flags |= D3D11_CREATE_DEVICE_DEBUG;
93    }
94
95    static const D3D_FEATURE_LEVEL FeatureLevels[] = {
96        D3D_FEATURE_LEVEL_10_0
97    };
98
99    HMODULE hSoftware = LoadLibraryA("d3d10sw.dll");
100    if (!hSoftware) {
101       return EXIT_FAILURE;
102    }
103
104    DXGI_SWAP_CHAIN_DESC SwapChainDesc;
105    ZeroMemory(&SwapChainDesc, sizeof SwapChainDesc);
106    SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;;
107    SwapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
108    SwapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
109    SwapChainDesc.SampleDesc.Quality = 0;
110    SwapChainDesc.SampleDesc.Count = 1;
111    SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
112    SwapChainDesc.BufferCount = 2;
113    SwapChainDesc.OutputWindow = hWnd;
114    SwapChainDesc.Windowed = true;
115    SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
116
117    ComPtr<ID3D11Device> pDevice;
118    ComPtr<ID3D11DeviceContext> pDeviceContext;
119    ComPtr<IDXGISwapChain> pSwapChain;
120    hr = D3D11CreateDeviceAndSwapChain(nullptr,
121                                       D3D_DRIVER_TYPE_SOFTWARE,
122                                       hSoftware,
123                                       Flags,
124                                       FeatureLevels,
125                                       _countof(FeatureLevels),
126                                       D3D11_SDK_VERSION,
127                                       &SwapChainDesc,
128                                       &pSwapChain,
129                                       &pDevice,
130                                       nullptr, /* pFeatureLevel */
131                                       &pDeviceContext);
132    if (FAILED(hr)) {
133        return EXIT_FAILURE;
134    }
135
136    ComPtr<IDXGIDevice> pDXGIDevice;
137    hr = pDevice->QueryInterface(IID_IDXGIDevice, (void **)&pDXGIDevice);
138    if (FAILED(hr)) {
139        return EXIT_FAILURE;
140    }
141
142    ComPtr<IDXGIAdapter> pAdapter;
143    hr = pDXGIDevice->GetAdapter(&pAdapter);
144    if (FAILED(hr)) {
145        return EXIT_FAILURE;
146    }
147
148    DXGI_ADAPTER_DESC Desc;
149    hr = pAdapter->GetDesc(&Desc);
150    if (FAILED(hr)) {
151        return EXIT_FAILURE;
152    }
153
154    printf("using %S\n", Desc.Description);
155
156    ComPtr<ID3D11Texture2D> pBackBuffer;
157    hr = pSwapChain->GetBuffer(0, IID_ID3D11Texture2D, (void **)&pBackBuffer);
158    if (FAILED(hr)) {
159        return EXIT_FAILURE;
160    }
161
162    D3D11_RENDER_TARGET_VIEW_DESC RenderTargetViewDesc;
163    ZeroMemory(&RenderTargetViewDesc, sizeof RenderTargetViewDesc);
164    RenderTargetViewDesc.Format = SwapChainDesc.BufferDesc.Format;
165    RenderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
166    RenderTargetViewDesc.Texture2D.MipSlice = 0;
167
168    ComPtr<ID3D11RenderTargetView> pRenderTargetView;
169    hr = pDevice->CreateRenderTargetView(pBackBuffer.Get(), &RenderTargetViewDesc, &pRenderTargetView);
170    if (FAILED(hr)) {
171        return EXIT_FAILURE;
172    }
173
174    pDeviceContext->OMSetRenderTargets(1, pRenderTargetView.GetAddressOf(), nullptr);
175
176
177    const float clearColor[4] = { 0.3f, 0.1f, 0.3f, 1.0f };
178    pDeviceContext->ClearRenderTargetView(pRenderTargetView.Get(), clearColor);
179
180    ComPtr<ID3D11VertexShader> pVertexShader;
181    hr = pDevice->CreateVertexShader(g_VS, sizeof g_VS, nullptr, &pVertexShader);
182    if (FAILED(hr)) {
183        return EXIT_FAILURE;
184    }
185
186    struct Vertex {
187        float position[4];
188        float color[4];
189    };
190
191    static const D3D11_INPUT_ELEMENT_DESC InputElementDescs[] = {
192        { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(Vertex, position), D3D11_INPUT_PER_VERTEX_DATA, 0 },
193        { "COLOR",    0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(Vertex, color),    D3D11_INPUT_PER_VERTEX_DATA, 0 }
194    };
195
196    ComPtr<ID3D11InputLayout> pVertexLayout;
197    hr = pDevice->CreateInputLayout(InputElementDescs,
198                                    _countof(InputElementDescs),
199                                    g_VS, sizeof g_VS,
200                                    &pVertexLayout);
201    if (FAILED(hr)) {
202        return EXIT_FAILURE;
203    }
204
205    pDeviceContext->IASetInputLayout(pVertexLayout.Get());
206
207    ComPtr<ID3D11PixelShader> pPixelShader;
208    hr = pDevice->CreatePixelShader(g_PS, sizeof g_PS, nullptr, &pPixelShader);
209    if (FAILED(hr)) {
210        return EXIT_FAILURE;
211    }
212
213    pDeviceContext->VSSetShader(pVertexShader.Get(), nullptr, 0);
214    pDeviceContext->PSSetShader(pPixelShader.Get(), nullptr, 0);
215
216    static const Vertex vertices[] = {
217        { { -0.9f, -0.9f, 0.5f, 1.0f}, { 0.8f, 0.0f, 0.0f, 0.1f } },
218        { {  0.9f, -0.9f, 0.5f, 1.0f}, { 0.0f, 0.9f, 0.0f, 0.1f } },
219        { {  0.0f,  0.9f, 0.5f, 1.0f}, { 0.0f, 0.0f, 0.7f, 0.1f } },
220    };
221
222    D3D11_BUFFER_DESC BufferDesc;
223    ZeroMemory(&BufferDesc, sizeof BufferDesc);
224    BufferDesc.Usage = D3D11_USAGE_DYNAMIC;
225    BufferDesc.ByteWidth = sizeof vertices;
226    BufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
227    BufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
228    BufferDesc.MiscFlags = 0;
229
230    D3D11_SUBRESOURCE_DATA BufferData;
231    BufferData.pSysMem = vertices;
232    BufferData.SysMemPitch = 0;
233    BufferData.SysMemSlicePitch = 0;
234
235    ComPtr<ID3D11Buffer> pVertexBuffer;
236    hr = pDevice->CreateBuffer(&BufferDesc, &BufferData, &pVertexBuffer);
237    if (FAILED(hr)) {
238        return EXIT_FAILURE;
239    }
240
241    UINT Stride = sizeof(Vertex);
242    UINT Offset = 0;
243    pDeviceContext->IASetVertexBuffers(0, 1, pVertexBuffer.GetAddressOf(), &Stride, &Offset);
244
245    D3D11_VIEWPORT ViewPort;
246    ViewPort.TopLeftX = 0;
247    ViewPort.TopLeftY = 0;
248    ViewPort.Width = WindowWidth;
249    ViewPort.Height = WindowHeight;
250    ViewPort.MinDepth = 0.0f;
251    ViewPort.MaxDepth = 1.0f;
252    pDeviceContext->RSSetViewports(1, &ViewPort);
253
254    D3D11_RASTERIZER_DESC RasterizerDesc;
255    ZeroMemory(&RasterizerDesc, sizeof RasterizerDesc);
256    RasterizerDesc.CullMode = D3D11_CULL_NONE;
257    RasterizerDesc.FillMode = D3D11_FILL_SOLID;
258    RasterizerDesc.FrontCounterClockwise = true;
259    RasterizerDesc.DepthClipEnable = true;
260    ComPtr<ID3D11RasterizerState> pRasterizerState;
261    hr = pDevice->CreateRasterizerState(&RasterizerDesc, &pRasterizerState);
262    if (FAILED(hr)) {
263        return EXIT_FAILURE;
264    }
265    pDeviceContext->RSSetState(pRasterizerState.Get());
266
267    pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
268
269    pDeviceContext->Draw(_countof(vertices), 0);
270
271    pSwapChain->Present(0, 0);
272
273    Sleep(1000);
274
275    ID3D11Buffer *pNullBuffer = nullptr;
276    UINT NullStride = 0;
277    UINT NullOffset = 0;
278    pDeviceContext->IASetVertexBuffers(0, 1, &pNullBuffer, &NullStride, &NullOffset);
279
280    pDeviceContext->OMSetRenderTargets(0, nullptr, nullptr);
281
282    pDeviceContext->IASetInputLayout(nullptr);
283
284    pDeviceContext->VSSetShader(nullptr, nullptr, 0);
285
286    pDeviceContext->PSSetShader(nullptr, nullptr, 0);
287
288    pDeviceContext->RSSetState(nullptr);
289
290    DestroyWindow(hWnd);
291
292    return EXIT_SUCCESS;
293}
294
295