1 /*
2  * Nuklear - 1.32.0 - public domain
3  * no warrenty implied; use at your own risk.
4  * authored from 2015-2016 by Micha Mettke
5  */
6 /*
7  * ==============================================================
8  *
9  *                              API
10  *
11  * ===============================================================
12  */
13 #ifndef NK_D3D11_H_
14 #define NK_D3D11_H_
15 
16 #define WIN32_LEAN_AND_MEAN
17 #include <windows.h>
18 
19 typedef struct ID3D11Device ID3D11Device;
20 typedef struct ID3D11DeviceContext ID3D11DeviceContext;
21 
22 NK_API struct nk_context *nk_d3d11_init(ID3D11Device *device, int width, int height, unsigned int max_vertex_buffer, unsigned int max_index_buffer);
23 NK_API void nk_d3d11_font_stash_begin(struct nk_font_atlas **atlas);
24 NK_API void nk_d3d11_font_stash_end(void);
25 NK_API int nk_d3d11_handle_event(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
26 NK_API void nk_d3d11_render(ID3D11DeviceContext *context, enum nk_anti_aliasing);
27 NK_API void nk_d3d11_resize(ID3D11DeviceContext *context, int width, int height);
28 NK_API void nk_d3d11_shutdown(void);
29 
30 #endif
31 /*
32  * ==============================================================
33  *
34  *                          IMPLEMENTATION
35  *
36  * ===============================================================
37  */
38 #ifdef NK_D3D11_IMPLEMENTATION
39 
40 #define WIN32_LEAN_AND_MEAN
41 #define COBJMACROS
42 #include <d3d11.h>
43 
44 #include <stddef.h>
45 #include <string.h>
46 #include <float.h>
47 #include <assert.h>
48 
49 #include "nuklear_d3d11_vertex_shader.h"
50 #include "nuklear_d3d11_pixel_shader.h"
51 
52 struct nk_d3d11_vertex {
53     float position[2];
54     float uv[2];
55     nk_byte col[4];
56 };
57 
58 static struct
59 {
60     struct nk_context ctx;
61     struct nk_font_atlas atlas;
62     struct nk_buffer cmds;
63 
64     struct nk_draw_null_texture null;
65     unsigned int max_vertex_buffer;
66     unsigned int max_index_buffer;
67 
68     D3D11_VIEWPORT viewport;
69     ID3D11Device *device;
70     ID3D11RasterizerState *rasterizer_state;
71     ID3D11VertexShader *vertex_shader;
72     ID3D11InputLayout *input_layout;
73     ID3D11Buffer *const_buffer;
74     ID3D11PixelShader *pixel_shader;
75     ID3D11BlendState *blend_state;
76     ID3D11Buffer *index_buffer;
77     ID3D11Buffer *vertex_buffer;
78     ID3D11ShaderResourceView *font_texture_view;
79     ID3D11SamplerState *sampler_state;
80 } d3d11;
81 
82 NK_API void
nk_d3d11_render(ID3D11DeviceContext * context,enum nk_anti_aliasing AA)83 nk_d3d11_render(ID3D11DeviceContext *context, enum nk_anti_aliasing AA)
84 {
85     const float blend_factor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
86     const UINT stride = sizeof(struct nk_d3d11_vertex);
87     const UINT offset = 0;
88 #ifdef NK_UINT_DRAW_INDEX
89     DXGI_FORMAT index_buffer_format = DXGI_FORMAT_R32_UINT;
90 #else
91     DXGI_FORMAT index_buffer_format = DXGI_FORMAT_R16_UINT;
92 #endif
93 
94     ID3D11DeviceContext_IASetInputLayout(context, d3d11.input_layout);
95     ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &d3d11.vertex_buffer, &stride, &offset);
96     ID3D11DeviceContext_IASetIndexBuffer(context, d3d11.index_buffer, index_buffer_format, 0);
97     ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
98 
99     ID3D11DeviceContext_VSSetShader(context, d3d11.vertex_shader, NULL, 0);
100     ID3D11DeviceContext_VSSetConstantBuffers(context, 0, 1, &d3d11.const_buffer);
101 
102     ID3D11DeviceContext_PSSetShader(context, d3d11.pixel_shader, NULL, 0);
103     ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &d3d11.sampler_state);
104 
105     ID3D11DeviceContext_OMSetBlendState(context, d3d11.blend_state, blend_factor, 0xffffffff);
106     ID3D11DeviceContext_RSSetState(context, d3d11.rasterizer_state);
107     ID3D11DeviceContext_RSSetViewports(context, 1, &d3d11.viewport);
108 
109     /* Convert from command queue into draw list and draw to screen */
110     {/* load draw vertices & elements directly into vertex + element buffer */
111     D3D11_MAPPED_SUBRESOURCE vertices;
112     D3D11_MAPPED_SUBRESOURCE indices;
113     const struct nk_draw_command *cmd;
114     UINT offset = 0;
115     HRESULT hr;
116 
117     hr = ID3D11DeviceContext_Map(context, (ID3D11Resource *)d3d11.vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &vertices);
118     NK_ASSERT(SUCCEEDED(hr));
119     hr = ID3D11DeviceContext_Map(context, (ID3D11Resource *)d3d11.index_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &indices);
120     NK_ASSERT(SUCCEEDED(hr));
121 
122     {/* fill converting configuration */
123         struct nk_convert_config config;
124         NK_STORAGE const struct nk_draw_vertex_layout_element vertex_layout[] = {
125             {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_d3d11_vertex, position)},
126             {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_d3d11_vertex, uv)},
127             {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_d3d11_vertex, col)},
128             {NK_VERTEX_LAYOUT_END}
129         };
130         memset(&config, 0, sizeof(config));
131         config.vertex_layout = vertex_layout;
132         config.vertex_size = sizeof(struct nk_d3d11_vertex);
133         config.vertex_alignment = NK_ALIGNOF(struct nk_d3d11_vertex);
134         config.global_alpha = 1.0f;
135         config.shape_AA = AA;
136         config.line_AA = AA;
137         config.circle_segment_count = 22;
138         config.curve_segment_count = 22;
139         config.arc_segment_count = 22;
140         config.null = d3d11.null;
141 
142         {/* setup buffers to load vertices and elements */
143         struct nk_buffer vbuf, ibuf;
144         nk_buffer_init_fixed(&vbuf, vertices.pData, (size_t)d3d11.max_vertex_buffer);
145         nk_buffer_init_fixed(&ibuf, indices.pData, (size_t)d3d11.max_index_buffer);
146         nk_convert(&d3d11.ctx, &d3d11.cmds, &vbuf, &ibuf, &config);}
147     }
148 
149     ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)d3d11.vertex_buffer, 0);
150     ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)d3d11.index_buffer, 0);
151 
152     /* iterate over and execute each draw command */
153     nk_draw_foreach(cmd, &d3d11.ctx, &d3d11.cmds)
154     {
155         D3D11_RECT scissor;
156         ID3D11ShaderResourceView *texture_view = (ID3D11ShaderResourceView *)cmd->texture.ptr;
157         if (!cmd->elem_count) continue;
158 
159         scissor.left = (LONG)cmd->clip_rect.x;
160         scissor.right = (LONG)(cmd->clip_rect.x + cmd->clip_rect.w);
161         scissor.top = (LONG)cmd->clip_rect.y;
162         scissor.bottom = (LONG)(cmd->clip_rect.y + cmd->clip_rect.h);
163 
164         ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &texture_view);
165         ID3D11DeviceContext_RSSetScissorRects(context, 1, &scissor);
166         ID3D11DeviceContext_DrawIndexed(context, (UINT)cmd->elem_count, offset, 0);
167         offset += cmd->elem_count;
168     }
169     nk_clear(&d3d11.ctx);
170     nk_buffer_clear(&d3d11.cmds);}
171 }
172 
173 static void
nk_d3d11_get_projection_matrix(int width,int height,float * result)174 nk_d3d11_get_projection_matrix(int width, int height, float *result)
175 {
176     const float L = 0.0f;
177     const float R = (float)width;
178     const float T = 0.0f;
179     const float B = (float)height;
180     float matrix[4][4] =
181     {
182         { 0.0f, 0.0f, 0.0f, 0.0f },
183         { 0.0f, 0.0f, 0.0f, 0.0f },
184         { 0.0f, 0.0f, 0.5f, 0.0f },
185         { 0.0f, 0.0f, 0.5f, 1.0f },
186     };
187     matrix[0][0] = 2.0f / (R - L);
188     matrix[1][1] = 2.0f / (T - B);
189     matrix[3][0] = (R + L) / (L - R);
190     matrix[3][1] = (T + B) / (B - T);
191     memcpy(result, matrix, sizeof(matrix));
192 }
193 
194 NK_API void
nk_d3d11_resize(ID3D11DeviceContext * context,int width,int height)195 nk_d3d11_resize(ID3D11DeviceContext *context, int width, int height)
196 {
197     D3D11_MAPPED_SUBRESOURCE mapped;
198     if (SUCCEEDED(ID3D11DeviceContext_Map(context, (ID3D11Resource *)d3d11.const_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped)))
199     {
200         nk_d3d11_get_projection_matrix(width, height, (float *)mapped.pData);
201         ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)d3d11.const_buffer, 0);
202 
203         d3d11.viewport.Width = (float)width;
204         d3d11.viewport.Height = (float)height;
205     }
206 }
207 
208 NK_API int
nk_d3d11_handle_event(HWND wnd,UINT msg,WPARAM wparam,LPARAM lparam)209 nk_d3d11_handle_event(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
210 {
211     switch (msg)
212     {
213     case WM_KEYDOWN:
214     case WM_KEYUP:
215     case WM_SYSKEYDOWN:
216     case WM_SYSKEYUP:
217     {
218         int down = !((lparam >> 31) & 1);
219         int ctrl = GetKeyState(VK_CONTROL) & (1 << 15);
220 
221         switch (wparam)
222         {
223         case VK_SHIFT:
224         case VK_LSHIFT:
225         case VK_RSHIFT:
226             nk_input_key(&d3d11.ctx, NK_KEY_SHIFT, down);
227             return 1;
228 
229         case VK_DELETE:
230             nk_input_key(&d3d11.ctx, NK_KEY_DEL, down);
231             return 1;
232 
233         case VK_RETURN:
234             nk_input_key(&d3d11.ctx, NK_KEY_ENTER, down);
235             return 1;
236 
237         case VK_TAB:
238             nk_input_key(&d3d11.ctx, NK_KEY_TAB, down);
239             return 1;
240 
241         case VK_LEFT:
242             if (ctrl)
243                 nk_input_key(&d3d11.ctx, NK_KEY_TEXT_WORD_LEFT, down);
244             else
245                 nk_input_key(&d3d11.ctx, NK_KEY_LEFT, down);
246             return 1;
247 
248         case VK_RIGHT:
249             if (ctrl)
250                 nk_input_key(&d3d11.ctx, NK_KEY_TEXT_WORD_RIGHT, down);
251             else
252                 nk_input_key(&d3d11.ctx, NK_KEY_RIGHT, down);
253             return 1;
254 
255         case VK_BACK:
256             nk_input_key(&d3d11.ctx, NK_KEY_BACKSPACE, down);
257             return 1;
258 
259         case VK_HOME:
260             nk_input_key(&d3d11.ctx, NK_KEY_TEXT_START, down);
261             nk_input_key(&d3d11.ctx, NK_KEY_SCROLL_START, down);
262             return 1;
263 
264         case VK_END:
265             nk_input_key(&d3d11.ctx, NK_KEY_TEXT_END, down);
266             nk_input_key(&d3d11.ctx, NK_KEY_SCROLL_END, down);
267             return 1;
268 
269         case VK_NEXT:
270             nk_input_key(&d3d11.ctx, NK_KEY_SCROLL_DOWN, down);
271             return 1;
272 
273         case VK_PRIOR:
274             nk_input_key(&d3d11.ctx, NK_KEY_SCROLL_UP, down);
275             return 1;
276 
277         case 'C':
278             if (ctrl) {
279                 nk_input_key(&d3d11.ctx, NK_KEY_COPY, down);
280                 return 1;
281             }
282             break;
283 
284         case 'V':
285             if (ctrl) {
286                 nk_input_key(&d3d11.ctx, NK_KEY_PASTE, down);
287                 return 1;
288             }
289             break;
290 
291         case 'X':
292             if (ctrl) {
293                 nk_input_key(&d3d11.ctx, NK_KEY_CUT, down);
294                 return 1;
295             }
296             break;
297 
298         case 'Z':
299             if (ctrl) {
300                 nk_input_key(&d3d11.ctx, NK_KEY_TEXT_UNDO, down);
301                 return 1;
302             }
303             break;
304 
305         case 'R':
306             if (ctrl) {
307                 nk_input_key(&d3d11.ctx, NK_KEY_TEXT_REDO, down);
308                 return 1;
309             }
310             break;
311         }
312         return 0;
313     }
314 
315     case WM_CHAR:
316         if (wparam >= 32)
317         {
318             nk_input_unicode(&d3d11.ctx, (nk_rune)wparam);
319             return 1;
320         }
321         break;
322 
323     case WM_LBUTTONDOWN:
324         nk_input_button(&d3d11.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
325         SetCapture(wnd);
326         return 1;
327 
328     case WM_LBUTTONUP:
329         nk_input_button(&d3d11.ctx, NK_BUTTON_DOUBLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
330         nk_input_button(&d3d11.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
331         ReleaseCapture();
332         return 1;
333 
334     case WM_RBUTTONDOWN:
335         nk_input_button(&d3d11.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
336         SetCapture(wnd);
337         return 1;
338 
339     case WM_RBUTTONUP:
340         nk_input_button(&d3d11.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
341         ReleaseCapture();
342         return 1;
343 
344     case WM_MBUTTONDOWN:
345         nk_input_button(&d3d11.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
346         SetCapture(wnd);
347         return 1;
348 
349     case WM_MBUTTONUP:
350         nk_input_button(&d3d11.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
351         ReleaseCapture();
352         return 1;
353 
354     case WM_MOUSEWHEEL:
355         nk_input_scroll(&d3d11.ctx, nk_vec2(0,(float)(short)HIWORD(wparam) / WHEEL_DELTA));
356         return 1;
357 
358     case WM_MOUSEMOVE:
359         nk_input_motion(&d3d11.ctx, (short)LOWORD(lparam), (short)HIWORD(lparam));
360         return 1;
361 
362     case WM_LBUTTONDBLCLK:
363         nk_input_button(&d3d11.ctx, NK_BUTTON_DOUBLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
364         return 1;
365     }
366 
367     return 0;
368 }
369 
370 static void
nk_d3d11_clipboard_paste(nk_handle usr,struct nk_text_edit * edit)371 nk_d3d11_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
372 {
373     (void)usr;
374     if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL))
375     {
376         HGLOBAL mem = GetClipboardData(CF_UNICODETEXT);
377         if (mem)
378         {
379             SIZE_T size = GlobalSize(mem) - 1;
380             if (size)
381             {
382                 LPCWSTR wstr = (LPCWSTR)GlobalLock(mem);
383                 if (wstr)
384                 {
385                     int utf8size = WideCharToMultiByte(CP_UTF8, 0, wstr, size / sizeof(wchar_t), NULL, 0, NULL, NULL);
386                     if (utf8size)
387                     {
388                         char* utf8 = (char*)malloc(utf8size);
389                         if (utf8)
390                         {
391                             WideCharToMultiByte(CP_UTF8, 0, wstr, size / sizeof(wchar_t), utf8, utf8size, NULL, NULL);
392                             nk_textedit_paste(edit, utf8, utf8size);
393                             free(utf8);
394                         }
395                     }
396                     GlobalUnlock(mem);
397                 }
398             }
399         }
400         CloseClipboard();
401     }
402 }
403 
404 static void
nk_d3d11_clipboard_copy(nk_handle usr,const char * text,int len)405 nk_d3d11_clipboard_copy(nk_handle usr, const char *text, int len)
406 {
407     (void)usr;
408     if (OpenClipboard(NULL))
409     {
410         int wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
411         if (wsize)
412         {
413             HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (wsize + 1) * sizeof(wchar_t));
414             if (mem)
415             {
416                 wchar_t* wstr = (wchar_t*)GlobalLock(mem);
417                 if (wstr)
418                 {
419                     MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize);
420                     wstr[wsize] = 0;
421                     GlobalUnlock(mem);
422                     SetClipboardData(CF_UNICODETEXT, mem);
423                 }
424             }
425         }
426         CloseClipboard();
427     }
428 }
429 
430 NK_API struct nk_context*
nk_d3d11_init(ID3D11Device * device,int width,int height,unsigned int max_vertex_buffer,unsigned int max_index_buffer)431 nk_d3d11_init(ID3D11Device *device, int width, int height, unsigned int max_vertex_buffer, unsigned int max_index_buffer)
432 {
433     HRESULT hr;
434     d3d11.max_vertex_buffer = max_vertex_buffer;
435     d3d11.max_index_buffer = max_index_buffer;
436     d3d11.device = device;
437     ID3D11Device_AddRef(device);
438 
439     nk_init_default(&d3d11.ctx, 0);
440     d3d11.ctx.clip.copy = nk_d3d11_clipboard_copy;
441     d3d11.ctx.clip.paste = nk_d3d11_clipboard_paste;
442     d3d11.ctx.clip.userdata = nk_handle_ptr(0);
443 
444     nk_buffer_init_default(&d3d11.cmds);
445 
446     {/* rasterizer state */
447     D3D11_RASTERIZER_DESC desc;
448     memset(&desc, 0, sizeof(desc));
449     desc.FillMode = D3D11_FILL_SOLID;
450     desc.CullMode = D3D11_CULL_NONE;
451     desc.FrontCounterClockwise = FALSE;
452     desc.DepthBias = 0;
453     desc.DepthBiasClamp = 0;
454     desc.SlopeScaledDepthBias = 0.0f;
455     desc.DepthClipEnable = TRUE;
456     desc.ScissorEnable = TRUE;
457     desc.MultisampleEnable = FALSE;
458     desc.AntialiasedLineEnable = FALSE;
459     hr = ID3D11Device_CreateRasterizerState(device,&desc, &d3d11.rasterizer_state);
460     NK_ASSERT(SUCCEEDED(hr));}
461 
462     /* vertex shader */
463     {hr = ID3D11Device_CreateVertexShader(device,nk_d3d11_vertex_shader, sizeof(nk_d3d11_vertex_shader), NULL, &d3d11.vertex_shader);
464     NK_ASSERT(SUCCEEDED(hr));}
465 
466     /* input layout */
467     {const D3D11_INPUT_ELEMENT_DESC layout[] = {
468         { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(struct nk_d3d11_vertex, position), D3D11_INPUT_PER_VERTEX_DATA, 0 },
469         { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,       0, offsetof(struct nk_d3d11_vertex, uv),       D3D11_INPUT_PER_VERTEX_DATA, 0 },
470         { "COLOR",    0, DXGI_FORMAT_R8G8B8A8_UNORM,     0, offsetof(struct nk_d3d11_vertex, col),      D3D11_INPUT_PER_VERTEX_DATA, 0 },
471     };
472     hr = ID3D11Device_CreateInputLayout(device,layout, ARRAYSIZE(layout), nk_d3d11_vertex_shader, sizeof(nk_d3d11_vertex_shader), &d3d11.input_layout);
473     NK_ASSERT(SUCCEEDED(hr));}
474 
475     /* constant buffer */
476     {float matrix[4*4];
477     D3D11_BUFFER_DESC desc;
478     memset(&desc, 0, sizeof(desc));
479     desc.ByteWidth = sizeof(matrix);
480     desc.Usage = D3D11_USAGE_DYNAMIC;
481     desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
482     desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
483     desc.MiscFlags = 0;
484 
485     {D3D11_SUBRESOURCE_DATA data;
486     data.pSysMem = matrix;
487     data.SysMemPitch = 0;
488     data.SysMemSlicePitch = 0;
489 
490     nk_d3d11_get_projection_matrix(width, height, matrix);
491     hr = ID3D11Device_CreateBuffer(device, &desc, &data, &d3d11.const_buffer);
492     NK_ASSERT(SUCCEEDED(hr));}}
493 
494     /* pixel shader */
495     {hr = ID3D11Device_CreatePixelShader(device, nk_d3d11_pixel_shader, sizeof(nk_d3d11_pixel_shader), NULL, &d3d11.pixel_shader);
496     NK_ASSERT(SUCCEEDED(hr));}
497 
498     {/* blend state */
499     D3D11_BLEND_DESC desc;
500     memset(&desc, 0, sizeof(desc));
501     desc.AlphaToCoverageEnable = FALSE;
502     desc.RenderTarget[0].BlendEnable = TRUE;
503     desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
504     desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
505     desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
506     desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
507     desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
508     desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
509     desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
510     hr = ID3D11Device_CreateBlendState(device, &desc, &d3d11.blend_state);
511     NK_ASSERT(SUCCEEDED(hr));}
512 
513     /* vertex buffer */
514     {D3D11_BUFFER_DESC desc;
515     memset(&desc, 0, sizeof(desc));
516     desc.Usage = D3D11_USAGE_DYNAMIC;
517     desc.ByteWidth = max_vertex_buffer;
518     desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
519     desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
520     desc.MiscFlags = 0;
521     hr = ID3D11Device_CreateBuffer(device, &desc, NULL, &d3d11.vertex_buffer);
522     NK_ASSERT(SUCCEEDED(hr));}
523 
524     /* index buffer */
525     {D3D11_BUFFER_DESC desc;
526     memset(&desc, 0, sizeof(desc));
527     desc.Usage = D3D11_USAGE_DYNAMIC;
528     desc.ByteWidth = max_index_buffer;
529     desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
530     desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
531     hr = ID3D11Device_CreateBuffer(device, &desc, NULL, &d3d11.index_buffer);
532     NK_ASSERT(SUCCEEDED(hr));}
533 
534     /* sampler state */
535     {D3D11_SAMPLER_DESC desc;
536     memset(&desc, 0, sizeof(desc));
537     desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
538     desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
539     desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
540     desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
541     desc.MipLODBias = 0.0f;
542     desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
543     desc.MinLOD = 0.0f;
544     desc.MaxLOD = FLT_MAX;
545     hr = ID3D11Device_CreateSamplerState(device, &desc, &d3d11.sampler_state);
546     NK_ASSERT(SUCCEEDED(hr));}
547 
548     /* viewport */
549     {d3d11.viewport.TopLeftX = 0.0f;
550     d3d11.viewport.TopLeftY = 0.0f;
551     d3d11.viewport.Width = (float)width;
552     d3d11.viewport.Height = (float)height;
553     d3d11.viewport.MinDepth = 0.0f;
554     d3d11.viewport.MaxDepth = 1.0f;}
555     return &d3d11.ctx;
556 }
557 
558 NK_API void
nk_d3d11_font_stash_begin(struct nk_font_atlas ** atlas)559 nk_d3d11_font_stash_begin(struct nk_font_atlas **atlas)
560 {
561     nk_font_atlas_init_default(&d3d11.atlas);
562     nk_font_atlas_begin(&d3d11.atlas);
563     *atlas = &d3d11.atlas;
564 }
565 
566 NK_API void
nk_d3d11_font_stash_end(void)567 nk_d3d11_font_stash_end(void)
568 {
569     const void *image; int w, h;
570     image = nk_font_atlas_bake(&d3d11.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
571 
572     /* upload font to texture and create texture view */
573     {ID3D11Texture2D *font_texture;
574     HRESULT hr;
575 
576     D3D11_TEXTURE2D_DESC desc;
577     memset(&desc, 0, sizeof(desc));
578     desc.Width = (UINT)w;
579     desc.Height = (UINT)h;
580     desc.MipLevels = 1;
581     desc.ArraySize = 1;
582     desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
583     desc.SampleDesc.Count = 1;
584     desc.SampleDesc.Quality = 0;
585     desc.Usage = D3D11_USAGE_DEFAULT;
586     desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
587     desc.CPUAccessFlags = 0;
588 
589     {D3D11_SUBRESOURCE_DATA data;
590     data.pSysMem = image;
591     data.SysMemPitch = (UINT)(w * 4);
592     data.SysMemSlicePitch = 0;
593     hr = ID3D11Device_CreateTexture2D(d3d11.device, &desc, &data, &font_texture);
594     assert(SUCCEEDED(hr));}
595 
596     {D3D11_SHADER_RESOURCE_VIEW_DESC srv;
597     memset(&srv, 0, sizeof(srv));
598     srv.Format = desc.Format;
599     srv.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
600     srv.Texture2D.MipLevels = 1;
601     srv.Texture2D.MostDetailedMip = 0;
602     hr = ID3D11Device_CreateShaderResourceView(d3d11.device, (ID3D11Resource *)font_texture, &srv, &d3d11.font_texture_view);
603     assert(SUCCEEDED(hr));}
604     ID3D11Texture2D_Release(font_texture);}
605 
606     nk_font_atlas_end(&d3d11.atlas, nk_handle_ptr(d3d11.font_texture_view), &d3d11.null);
607     if (d3d11.atlas.default_font)
608         nk_style_set_font(&d3d11.ctx, &d3d11.atlas.default_font->handle);
609 }
610 
611 NK_API
nk_d3d11_shutdown(void)612 void nk_d3d11_shutdown(void)
613 {
614     nk_font_atlas_clear(&d3d11.atlas);
615     nk_buffer_free(&d3d11.cmds);
616     nk_free(&d3d11.ctx);
617 
618     ID3D11SamplerState_Release(d3d11.sampler_state);
619     ID3D11ShaderResourceView_Release(d3d11.font_texture_view);
620     ID3D11Buffer_Release(d3d11.vertex_buffer);
621     ID3D11Buffer_Release(d3d11.index_buffer);
622     ID3D11BlendState_Release(d3d11.blend_state);
623     ID3D11PixelShader_Release(d3d11.pixel_shader);
624     ID3D11Buffer_Release(d3d11.const_buffer);
625     ID3D11VertexShader_Release(d3d11.vertex_shader);
626     ID3D11InputLayout_Release(d3d11.input_layout);
627     ID3D11RasterizerState_Release(d3d11.rasterizer_state);
628     ID3D11Device_Release(d3d11.device);
629 }
630 
631 #endif
632 
633