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
38 using Microsoft::WRL::ComPtr;
39
40 #include "tri_vs_4_0.h"
41 #include "tri_ps_4_0.h"
42
43
44 int
main(int argc,char * argv[])45 main(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("libgallium_d3d10.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