Renderer.cpp 40.7 KB
Newer Older
Gargaj's avatar
Gargaj committed
1
2
3
#include <windows.h>
#include <windowsx.h>
#include <tchar.h>
Gargaj's avatar
Gargaj committed
4
#include <float.h>
Gargaj's avatar
Gargaj committed
5

Gargaj's avatar
Gargaj committed
6
#include <d3d11.h>
Gargaj's avatar
Gargaj committed
7
8
#include <D3Dcompiler.h>

Gargaj's avatar
Gargaj committed
9
10
#include "../Renderer.h"

11
12
13
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#include "Scintilla.h"
Gargaj's avatar
Gargaj committed
14
15

const char * shaderKeyword =
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  " register packoffset static const"
  " break continue discard do for if else switch while case default return true false"
  " BINORMAL BINORMAL0 BINORMAL1 BINORMAL2 BINORMAL3 BINORMAL4 BINORMAL5 BINORMAL6 BINORMAL7"
  " BLENDINDICES BLENDINDICES0 BLENDINDICES1 BLENDINDICES2 BLENDINDICES3 BLENDINDICES4 BLENDINDICES5 BLENDINDICES6 BLENDINDICES7"
  " BLENDWEIGHT BLENDWEIGHT0 BLENDWEIGHT1 BLENDWEIGHT2 BLENDWEIGHT3 BLENDWEIGHT4 BLENDWEIGHT5 BLENDWEIGHT6 BLENDWEIGHT7"
  " COLOR COLOR0 COLOR1 COLOR2 COLOR3 COLOR4 COLOR5 COLOR6 COLOR7"
  " NORMAL NORMAL0 NORMAL1 NORMAL2 NORMAL3 NORMAL4 NORMAL5 NORMAL6 NORMAL7"
  " POSITION POSITION0 POSITION1 POSITION2 POSITION3 POSITION4 POSITION5 POSITION6 POSITION7"
  " POSITIONT"
  " PSIZE PSIZE0 PSIZE1 PSIZE2 PSIZE3 PSIZE4 PSIZE5 PSIZE6 PSIZE7"
  " TANGENT TANGENT0 TANGENT1 TANGENT2 TANGENT3 TANGENT4 TANGENT5 TANGENT6 TANGENT7"
  " TEXCOORD TEXCOORD0 TEXCOORD1 TEXCOORD2 TEXCOORD3 TEXCOORD4 TEXCOORD5 TEXCOORD6 TEXCOORD7 TEXCOORD8 TEXCOORD9"
  " TEXCOORD0 TEXCOORD1 TEXCOORD2 TEXCOORD3 TEXCOORD4 TEXCOORD5 TEXCOORD6 TEXCOORD7 TEXCOORD8 TEXCOORD9"
  " SV_Coverage SV_Depth SV_DispatchThreadID SV_DomainLocation SV_GroupID SV_GroupIndex SV_GroupThreadID SV_GSInstanceID SV_InsideTessFactor SV_IsFrontFace SV_OutputControlPointID SV_POSITION SV_Position SV_RenderTargetArrayIndex SV_SampleIndex SV_TessFactor SV_ViewportArrayIndex SV_InstanceID SV_PrimitiveID SV_VertexID SV_TargetID"
  " SV_TARGET SV_Target SV_Target0 SV_Target1 SV_Target2 SV_Target3 SV_Target4 SV_Target5 SV_Target6 SV_Target7"
  " SV_ClipDistance0 SV_ClipDistance1 SV_ClipDistance2 SV_ClipDistance3 SV_ClipDistance4 SV_ClipDistance5 SV_ClipDistance6 SV_ClipDistance7"
  " SV_CullDistance0 SV_CullDistance1 SV_CullDistance2 SV_CullDistance3 SV_CullDistance4 SV_CullDistance5 SV_CullDistance6 SV_CullDistance7";
Gargaj's avatar
Gargaj committed
33
34

const char * shaderType = 
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  "bool bool1 bool2 bool3 bool4"
  " bool1x1 bool1x2 bool1x3 bool1x4"
  " bool2x1 bool2x2 bool2x3 bool2x4"
  " bool3x1 bool3x2 bool3x3 bool3x4"
  " bool4x1 bool4x2 bool4x3 bool4x4"
  " int int1 int2 int3 int4"
  " int1x1 int1x2 int1x3 int1x4"
  " int2x1 int2x2 int2x3 int2x4"
  " int3x1 int3x2 int3x3 int3x4"
  " int4x1 int4x2 int4x3 int4x4"
  " uint uint1 uint2 uint3 uint4"
  " uint1x1 uint1x2 uint1x3 uint1x4"
  " uint2x1 uint2x2 uint2x3 uint2x4"
  " uint3x1 uint3x2 uint3x3 uint3x4"
  " uint4x1 uint4x2 uint4x3 uint4x4"
  " UINT UINT2 UINT3 UINT4"
  " dword dword1 dword2 dword3 dword4"
  " dword1x1 dword1x2 dword1x3 dword1x4"
  " dword2x1 dword2x2 dword2x3 dword2x4"
  " dword3x1 dword3x2 dword3x3 dword3x4"
  " dword4x1 dword4x2 dword4x3 dword4x4"
  " half half1 half2 half3 half4"
  " half1x1 half1x2 half1x3 half1x4"
  " half2x1 half2x2 half2x3 half2x4"
  " half3x1 half3x2 half3x3 half3x4"
  " half4x1 half4x2 half4x3 half4x4"
  " float float1 float2 float3 float4"
  " float1x1 float1x2 float1x3 float1x4"
  " float2x1 float2x2 float2x3 float2x4"
  " float3x1 float3x2 float3x3 float3x4"
  " float4x1 float4x2 float4x3 float4x4"
  " double double1 double2 double3 double4"
  " double1x1 double1x2 double1x3 double1x4"
  " double2x1 double2x2 double2x3 double2x4"
  " double3x1 double3x2 double3x3 double3x4"
  " double4x1 double4x2 double4x3 double4x4"
  " snorm unorm string void cbuffer struct"
  " Buffer AppendStructuredBfufer ByteAddressBuffer ConsumeStructuredBuffer StructuredBuffer"
  " RWBuffer RWByteAddressBuffer RWStructuredBuffer RWTexture1D RWTexture1DArray RWTexture2D RWTexture2DArray RWTexture3D"
  " InputPatch OutputPatch"
  " linear centroid nointerpolation noperspective sample"
  " sampler sampler1D sampler2D sampler3D samplerCUBE SamplerComparisonState SamplerState sampler_state"
  " AddressU AddressV AddressW BorderColor Filter MaxAnisotropy MaxLOD MinLOD MipLODBias ComparisonFunc ComparisonFilter"
  " texture Texture1D Texture1DArray Texture2D Texture2DArray Texture2DMS Texture2DMSArray Texture3D TextureCube";
Gargaj's avatar
Gargaj committed
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

const char * shaderBuiltin =
  "abs acos all AllMemoryBarrier AllMemoryBarrierWithGroupSync any asdouble"
  " asfloat asin asint asuint atan atan2 ceil clamp clip cos cosh countbits"
  " cross D3DCOLORtoUBYTE4 ddx ddx_coarse ddx_fine ddy ddy_coarse ddy_fine"
  " degrees determinant DeviceMemoryBarrier DeviceMemoryBarrierWithGroupSync"
  " distance dot dst EvaluateAttributeAtCentroid EvaluateAttributeAtSample"
  " EvaluateAttributeSnapped exp exp2 f16tof32 f32tof16 faceforward firstbithigh"
  " firstbitlow floor fmod frac frexp fwidth GetRenderTargetSampleCount"
  " GetRenderTargetSamplePosition GroupMemoryBarrier GroupMemoryBarrierWithGroupSync"
  " InterlockedAdd InterlockedAnd InterlockedCompareExchange InterlockedCompareStore"
  " InterlockedExchange InterlockedMax InterlockedMin InterlockedOr InterlockedXor"
  " isfinite isinf isnan ldexp length lerp lit log log10 log2 mad max min modf mul"
  " noise normalize pow Process2DQuadTessFactorsAvg Process2DQuadTessFactorsMax"
  " Process2DQuadTessFactorsMin ProcessIsolineTessFactors ProcessQuadTessFactorsAvg"
  " ProcessQuadTessFactorsMax ProcessQuadTessFactorsMin ProcessTriTessFactorsAvg"
  " ProcessTriTessFactorsMax ProcessTriTessFactorsMin radians rcp reflect refract"
  " reversebits round rsqrt saturate sign sin sincos sinh smoothstep sqrt step"
  " tan tanh tex1D tex1Dbias tex1Dgrad tex1Dlod tex1Dproj tex2D tex2Dbias"
  " tex2Dgrad tex2Dlod tex2Dproj tex3D tex3Dbias tex3Dgrad tex3Dlod tex3Dproj"
  " texCUBE texCUBEbias texCUBEgrad texCUBElod texCUBEproj transpose trunc";

namespace Renderer
{
  char * defaultShaderFilename = "shader.dx11.hlsl";
  char defaultShader[65536] = 
105
106
107
108
    "{%textures:begin%}" // leave off \n here
    "Texture2D {%textures:name%};\n"
    "{%textures:end%}" // leave off \n here
    "Texture1D texFFT; // towards 0.0 is bass / lower freq, towards 1.0 is higher / treble freq\n"
Gargaj's avatar
Gargaj committed
109
    "Texture1D texFFTSmoothed; // this one has longer falloff and less harsh transients\n"
110
    "Texture1D texFFTIntegrated; // this is continually increasing\n"
Gargaj's avatar
Gargaj committed
111
    "SamplerState smp;\n"
Gargaj's avatar
Gargaj committed
112
    "\n"
Gargaj's avatar
Gargaj committed
113
114
    "cbuffer constants\n"
    "{\n"
115
116
117
118
119
    "  float fGlobalTime; // in seconds\n"
    "  float2 v2Resolution; // viewport resolution (in pixels)\n"
    "{%midi:begin%}"
    "  float {%midi:name%};\n"
    "{%midi:end%}"
Gargaj's avatar
Gargaj committed
120
    "}\n"
Gargaj's avatar
Gargaj committed
121
    "\n"
122
123
124
125
126
    "float4 plas( float2 v, float time )\n"
    "{\n"
    "  float c = 0.5 + sin( v.x * 10.0 ) + cos( sin( time + v.y ) * 20.0 );\n"
    "  return float4( sin(c * 0.2 + cos(time)), c * 0.15, cos( c * 0.1 + time / .4 ) * .25, 1.0 );\n"
    "}\n"
Gargaj's avatar
Gargaj committed
127
    "float4 main( float4 position : SV_POSITION, float2 TexCoord : TEXCOORD ) : SV_TARGET\n"
Gargaj's avatar
Gargaj committed
128
129
130
131
132
133
134
135
136
137
    "{\n"
    "  float2 uv = TexCoord;\n"
    "  uv -= 0.5;\n"
    "  uv /= float2(v2Resolution.y / v2Resolution.x, 1);"
    "\n"
    "  float2 m;\n"
    "  m.x = atan(uv.x / uv.y) / 3.14;\n"
    "  m.y = 1 / length(uv) * .2;\n"
    "  float d = m.y;\n"
    "\n"
Gargaj's avatar
Gargaj committed
138
    "  float f = texFFT.Sample( smp, d ).r * 100;\n"
Gargaj's avatar
Gargaj committed
139
140
141
    "  m.x += sin( fGlobalTime ) * 0.1;\n"
    "  m.y += fGlobalTime * 0.25;\n"
    "\n"
142
143
144
    "  float4 t = plas( m * 3.14, fGlobalTime ) / d;\n"
    "  t = saturate( t );\n"
    "  return f + t;\n"
Gargaj's avatar
Gargaj committed
145
    "}";
Gargaj's avatar
Gargaj committed
146

Gargaj's avatar
Gargaj committed
147
  char defaultVertexShader[65536] = 
Gargaj's avatar
Gargaj committed
148
149
    "struct VS_INPUT_PP { float3 Pos : POSITION; float2 TexCoord : TEXCOORD; };\n"
    "struct VS_OUTPUT_PP { float4 Pos : SV_POSITION; float2 TexCoord : TEXCOORD; };\n"
Gargaj's avatar
Gargaj committed
150
151
152
153
154
155
156
157
158
159
160
    "\n"
    "VS_OUTPUT_PP main( VS_INPUT_PP In )\n"
    "{\n"
    "  VS_OUTPUT_PP Out;\n"
    "  Out.Pos = float4( In.Pos, 1.0 );\n"
    "  Out.TexCoord = In.TexCoord;\n"
    "  return Out;\n"
    "}\n";

  bool run = true;

Gargaj's avatar
Gargaj committed
161
162
163
164
165
166
167
  IDXGISwapChain * pSwapChain = NULL;
  ID3D11Device * pDevice = NULL;
  ID3D11DeviceContext * pContext = NULL;
  ID3D11RenderTargetView * pRenderTarget = NULL;
  ID3D11VertexShader * pVertexShader = NULL;
  ID3D11PixelShader * theShader = NULL;
  ID3D11ShaderReflection * pShaderReflection = NULL;
168
169
  ID3D11Texture2D * pBackBuffer = NULL;
  ID3D11Texture2D * pFrameGrabTexture = NULL;
Gargaj's avatar
Gargaj committed
170

Gargaj's avatar
Gargaj committed
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
  int nWidth = 0;
  int nHeight = 0;
  HWND hWnd = NULL;

  KeyEvent keyEventBuffer[512];
  int keyEventBufferCount = 0;
  MouseEvent mouseEventBuffer[512];
  int mouseEventBufferCount = 0;

  LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 
  {
    switch (uMsg) 
    {
    case WM_KEYDOWN: 
      {
        int sciKey = 0;
        switch(wParam)
        {
        case VK_DOWN:         sciKey = SCK_DOWN;      break;
        case VK_UP:           sciKey = SCK_UP;        break;
        case VK_LEFT:         sciKey = SCK_LEFT;      break;
        case VK_RIGHT:        sciKey = SCK_RIGHT;     break;
        case VK_HOME:         sciKey = SCK_HOME;      break;
        case VK_END:          sciKey = SCK_END;       break;
        case VK_PRIOR:        sciKey = SCK_PRIOR;     break;
        case VK_NEXT:         sciKey = SCK_NEXT;      break;
        case VK_DELETE:       sciKey = SCK_DELETE;    break;
        case VK_INSERT:       sciKey = SCK_INSERT;    break;
        case VK_ESCAPE:       sciKey = SCK_ESCAPE;    break;
        case VK_BACK:         sciKey = SCK_BACK;      break;
        case VK_TAB:          sciKey = SCK_TAB;       break;
        case VK_RETURN:       sciKey = SCK_RETURN;    break;
//         case VK_KP_PLUS:      sciKey = SCK_ADD;       break;
//         case VK_KP_MINUS:     sciKey = SCK_SUBTRACT;  break;
//         case VK_KP_DIVIDE:    sciKey = SCK_DIVIDE;    break;
//         case VK_LSUPER:       sciKey = SCK_WIN;       break;
//         case VK_RSUPER:       sciKey = SCK_RWIN;      break;
        case VK_MENU:         sciKey = SCK_MENU;      break;
//         case VK_SLASH:        sciKey = '/';           break;
//         case VK_ASTERISK:     sciKey = '`';           break;
//         case VK_LEFTBRACKET:  sciKey = '[';           break;
//         case VK_BACKSLASH:    sciKey = '\\';          break;
//         case VK_RIGHTBRACKET: sciKey = ']';           break;
Gargaj's avatar
Gargaj committed
214
        case VK_F2:         sciKey = 283;      break;
Gargaj's avatar
Gargaj committed
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
        case VK_F5:         sciKey = 286;      break;
        case VK_F11:        sciKey = 292;      break;
        case VK_SHIFT:
        case VK_LSHIFT:
        case VK_RSHIFT:
        case VK_LMENU:
        case VK_RMENU:
        case VK_CONTROL:
        case VK_LCONTROL:
        case VK_RCONTROL:
          sciKey = 0;
          break;
        default:
          sciKey = wParam;
        }
        if (sciKey)
        {
          keyEventBuffer[keyEventBufferCount].ctrl  = GetAsyncKeyState( VK_LCONTROL ) || GetAsyncKeyState( VK_RCONTROL );
          keyEventBuffer[keyEventBufferCount].alt   = GetAsyncKeyState( VK_LMENU ) || GetAsyncKeyState( VK_RMENU );
          keyEventBuffer[keyEventBufferCount].shift = GetAsyncKeyState( VK_LSHIFT ) || GetAsyncKeyState( VK_RSHIFT );
          keyEventBuffer[keyEventBufferCount].scanCode = sciKey;
          keyEventBuffer[keyEventBufferCount].character = 0;
          keyEventBufferCount++;
        }
        //pKeys[wParam] = 1;
      } break;
    case WM_CHAR: 
      {
        if (wParam >= 32)
        {
          keyEventBuffer[keyEventBufferCount].ctrl  = GetAsyncKeyState( VK_LCONTROL ) || GetAsyncKeyState( VK_RCONTROL );
          keyEventBuffer[keyEventBufferCount].alt   = GetAsyncKeyState( VK_LMENU ) || GetAsyncKeyState( VK_RMENU );
          keyEventBuffer[keyEventBufferCount].shift = GetAsyncKeyState( VK_LSHIFT ) || GetAsyncKeyState( VK_RSHIFT );
          keyEventBuffer[keyEventBufferCount].scanCode = 0;
          keyEventBuffer[keyEventBufferCount].character = wParam;
          keyEventBufferCount++;
        }
        //pKeys[wParam] = 1;
      } break;

    case WM_KEYUP: 
      {
        //pKeys[wParam] = 0;
      } break;

    case WM_LBUTTONDOWN: 
      {
        mouseEventBuffer[mouseEventBufferCount].eventType = MOUSEEVENTTYPE_DOWN;
        mouseEventBuffer[mouseEventBufferCount].button = MOUSEBUTTON_LEFT;
        mouseEventBuffer[mouseEventBufferCount].x = GET_X_LPARAM(lParam);
        mouseEventBuffer[mouseEventBufferCount].y = GET_Y_LPARAM(lParam);
        mouseEventBufferCount++;
      } break;

    case WM_MOUSEMOVE: 
      {
        mouseEventBuffer[mouseEventBufferCount].eventType = MOUSEEVENTTYPE_MOVE;
        mouseEventBuffer[mouseEventBufferCount].x = GET_X_LPARAM(lParam);
        mouseEventBuffer[mouseEventBufferCount].y = GET_Y_LPARAM(lParam);
        mouseEventBufferCount++;
      } break;

    case WM_LBUTTONUP: 
      {
        mouseEventBuffer[mouseEventBufferCount].eventType = MOUSEEVENTTYPE_UP;
        mouseEventBuffer[mouseEventBufferCount].button = MOUSEBUTTON_LEFT;
        mouseEventBuffer[mouseEventBufferCount].x = GET_X_LPARAM(lParam);
        mouseEventBuffer[mouseEventBufferCount].y = GET_Y_LPARAM(lParam);
        mouseEventBufferCount++;
      } break;

mathieu _alkama_ m's avatar
mathieu _alkama_ m committed
286
287
288
289
    case WM_MOUSEWHEEL:
      {
        mouseEventBuffer[mouseEventBufferCount].eventType = MOUSEEVENTTYPE_SCROLL;
        mouseEventBuffer[mouseEventBufferCount].x = 0;
290
        mouseEventBuffer[mouseEventBufferCount].y = GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA;
mathieu _alkama_ m's avatar
mathieu _alkama_ m committed
291
292
293
294
295
296
        mouseEventBufferCount++;
      } break;

    case WM_MOUSEHWHEEL:
      {
        mouseEventBuffer[mouseEventBufferCount].eventType = MOUSEEVENTTYPE_SCROLL;
297
        mouseEventBuffer[mouseEventBufferCount].x = -GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA;
mathieu _alkama_ m's avatar
mathieu _alkama_ m committed
298
299
300
301
        mouseEventBuffer[mouseEventBufferCount].y = 0;
        mouseEventBufferCount++;
      } break;

Gargaj's avatar
Gargaj committed
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
    case WM_SYSCOMMAND: 
      {
        switch (wParam) 
        {
        case SC_SCREENSAVE:
        case SC_MONITORPOWER: 
          {
            return 0;
          }
        }
      } break;

    case WM_CLOSE: 
      {
        run = false;
      } break;
    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam);
  }

  bool InitWindow(RENDERER_SETTINGS * pSetup) 
  {
    WNDCLASS WC;

    WC.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    WC.lpfnWndProc = &WndProc;
    WC.cbClsExtra = 0;
    WC.cbWndExtra = 0;
    WC.hInstance = GetModuleHandle(NULL);
    //WC.hIcon = LoadIcon(setup->hInstance,MAKEINTRESOURCE(IDI_ICON1));
    WC.hIcon = NULL;
    WC.hCursor = LoadCursor(NULL, IDC_ARROW);
    WC.hbrBackground = NULL;
    WC.lpszMenuName = NULL;
    WC.lpszClassName = _T("fwzwnd");
    if(!RegisterClass(&WC)) return 0;

    DWORD wExStyle = WS_EX_APPWINDOW;
    DWORD wStyle = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
    if (pSetup->windowMode == RENDERER_WINDOWMODE_WINDOWED) wStyle |= WS_OVERLAPPED | WS_CAPTION;

    RECT wr={0,0,pSetup->nWidth,pSetup->nHeight};
    AdjustWindowRectEx(&wr, wStyle, FALSE, wExStyle);

Gargaj's avatar
Gargaj committed
347
    hWnd = CreateWindowEx(wExStyle,_T("fwzwnd"),_T("BONZOMATIC - Direct3D 11.0 edition"),wStyle,
Gargaj's avatar
Gargaj committed
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
      (GetSystemMetrics(SM_CXSCREEN) - pSetup->nWidth )/2,
      (GetSystemMetrics(SM_CYSCREEN) - pSetup->nHeight)/2,
      wr.right-wr.left, wr.bottom-wr.top,
      NULL, NULL, WC.hInstance, NULL);

    if (!hWnd) 
      return false;

    ShowWindow(hWnd, SW_SHOW);
    SetForegroundWindow(hWnd);
    SetFocus(hWnd);

    return true;
  }

Gargaj's avatar
Gargaj committed
363
  bool bVsync = false;
Gargaj's avatar
Gargaj committed
364
365
  bool InitDirect3D(RENDERER_SETTINGS * pSetup) 
  {
Gargaj's avatar
Gargaj committed
366
367
    DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;

Gargaj's avatar
Gargaj committed
368
369
370
    DXGI_SWAP_CHAIN_DESC desc;
    ZeroMemory(&desc, sizeof(DXGI_SWAP_CHAIN_DESC));
    desc.BufferCount = 1;
Gargaj's avatar
Gargaj committed
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
    desc.BufferDesc.Width = pSetup->nWidth;
    desc.BufferDesc.Height = pSetup->nHeight;
    desc.BufferDesc.Format = format;
    if (pSetup->bVsync)
    {
      bVsync = true;
      IDXGIFactory1 * pFactory = NULL;
      HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory);
      if (pFactory)
      {
        IDXGIAdapter1 * pAdapter = NULL;
        pFactory->EnumAdapters1( 0, &pAdapter );
        if (pAdapter)
        {
          IDXGIOutput * pOutput = NULL;
          pAdapter->EnumOutputs( 0, &pOutput );
          if (pOutput)
          {
            unsigned int nModeCount = 0;
            pOutput->GetDisplayModeList( format, DXGI_ENUM_MODES_INTERLACED | DXGI_ENUM_MODES_SCALING, &nModeCount, NULL);

            DXGI_MODE_DESC * pModes = new DXGI_MODE_DESC[ nModeCount ];
            pOutput->GetDisplayModeList( format, DXGI_ENUM_MODES_INTERLACED | DXGI_ENUM_MODES_SCALING, &nModeCount, pModes);

            for (int i=0; i<nModeCount; i++)
            {
              if (pModes[i].Width == pSetup->nWidth && pModes[i].Height == pSetup->nHeight)
              {
                desc.BufferDesc = pModes[i];
                break;
              }
            }
            delete[] pModes;

            pOutput->Release();
          }

          pAdapter->Release();
        }

        pFactory->Release();
      }
    }
Gargaj's avatar
Gargaj committed
414
415
    desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    desc.OutputWindow = hWnd;
Gargaj's avatar
Gargaj committed
416
417
418
419
420
421
422
    desc.SampleDesc.Count = 1;
    desc.Windowed = pSetup->windowMode != RENDERER_WINDOWMODE_FULLSCREEN;

    DWORD deviceCreationFlags = 0;
#ifdef _DEBUG
    //deviceCreationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
Gargaj's avatar
Gargaj committed
423

Gargaj's avatar
Gargaj committed
424
425
426
427
    if (D3D11CreateDeviceAndSwapChain(
      NULL,
      D3D_DRIVER_TYPE_HARDWARE,
      NULL,
Gargaj's avatar
Gargaj committed
428
      deviceCreationFlags,
Gargaj's avatar
Gargaj committed
429
430
431
432
433
434
435
436
      NULL,
      NULL,
      D3D11_SDK_VERSION,
      &desc,
      &pSwapChain,
      &pDevice,
      NULL,
      &pContext) != S_OK)
Gargaj's avatar
Gargaj committed
437
438
    {
      printf("[Renderer] D3D11CreateDeviceAndSwapChain failed\n");
Gargaj's avatar
Gargaj committed
439
      return false;
Gargaj's avatar
Gargaj committed
440
    }
Gargaj's avatar
Gargaj committed
441

Gargaj's avatar
Gargaj committed
442
443
444
445
446
447
448
    pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pBackBuffer);

    pDevice->CreateRenderTargetView(pBackBuffer, NULL, &pRenderTarget);
    pBackBuffer->Release();

    pContext->OMSetRenderTargets(1, &pRenderTarget, NULL);

449
450
451
452
453
454
455
456
457
458
    // create staging texture for frame grabbing

    D3D11_TEXTURE2D_DESC description;
    pBackBuffer->GetDesc( &description );
    description.BindFlags = 0;
    description.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
    description.Usage = D3D11_USAGE_STAGING;

    HRESULT hr = pDevice->CreateTexture2D( &description, NULL, &pFrameGrabTexture );

Gargaj's avatar
Gargaj committed
459
    return true;
Gargaj's avatar
Gargaj committed
460
461
  }

Gargaj's avatar
Gargaj committed
462
463
  ID3D11Buffer * pFullscreenQuadVB = NULL;
  ID3D11InputLayout * pFullscreenQuadLayout = NULL;
Gargaj's avatar
Gargaj committed
464
465
  ID3D11SamplerState * pFullscreenQuadSamplerState = NULL;
  ID3D11Buffer * pFullscreenQuadConstantBuffer = NULL;
466
467
#define FULLSCREENQUADCONSTANTS_SIZE 512
  unsigned char pFullscreenQuadConstants[FULLSCREENQUADCONSTANTS_SIZE];
Gargaj's avatar
Gargaj committed
468
469
  ID3D11BlendState* pFullscreenQuadBlendState = NULL;
  ID3D11RasterizerState * pFullscreenQuadRasterizerState = NULL;
Gargaj's avatar
Gargaj committed
470

Gargaj's avatar
Gargaj committed
471
  bool InitD3D11QuadRendering( RENDERER_SETTINGS * settings )
Gargaj's avatar
Gargaj committed
472
  {
Gargaj's avatar
Gargaj committed
473
474
475
476
    ID3DBlob * pCode = NULL;
    ID3DBlob * pErrors = NULL;
    if (D3DCompile( defaultVertexShader, strlen(defaultVertexShader), NULL, NULL, NULL, "main", "vs_4_0", NULL, NULL, &pCode, &pErrors ) != S_OK)
    {
Gargaj's avatar
Gargaj committed
477
      printf("[Renderer] D3DCompile failed\n");
Gargaj's avatar
Gargaj committed
478
479
480
481
482
      return false;
    }

    if (pDevice->CreateVertexShader( pCode->GetBufferPointer(), pCode->GetBufferSize(), NULL, &pVertexShader ) != S_OK)
    {
Gargaj's avatar
Gargaj committed
483
      printf("[Renderer] CreateVertexShader failed\n");
Gargaj's avatar
Gargaj committed
484
485
486
487
488
489
      return false;
    }

    //////////////////////////////////////////////////////////////////////////

    static float pQuad[] = {
Gargaj's avatar
Gargaj committed
490
491
492
493
      -1.0, -1.0,  0.5, 0.0, 0.0,
      -1.0,  1.0,  0.5, 0.0, 1.0,
       1.0, -1.0,  0.5, 1.0, 0.0,
       1.0,  1.0,  0.5, 1.0, 1.0,
Gargaj's avatar
Gargaj committed
494
495
496
497
498
499
500
501
502
503
504
505
506
507
    };

    D3D11_BUFFER_DESC desc;
    ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));

    desc.ByteWidth = sizeof(float) * 5 * 4;
    desc.Usage = D3D11_USAGE_DEFAULT;
    desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;

    D3D11_SUBRESOURCE_DATA subData;
    ZeroMemory(&subData, sizeof(D3D11_SUBRESOURCE_DATA));
    subData.pSysMem = pQuad;

    if (pDevice->CreateBuffer(&desc, &subData, &pFullscreenQuadVB) != S_OK)
Gargaj's avatar
Gargaj committed
508
509
    {
      printf("[Renderer] CreateBuffer failed\n");
Gargaj's avatar
Gargaj committed
510
      return false;
Gargaj's avatar
Gargaj committed
511
    }
Gargaj's avatar
Gargaj committed
512
513
514

    static D3D11_INPUT_ELEMENT_DESC pQuadDesc[] =
    {
Gargaj's avatar
Gargaj committed
515
516
      {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0 * sizeof(float), D3D11_INPUT_PER_VERTEX_DATA, 0},
      {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT   , 0, 3 * sizeof(float), D3D11_INPUT_PER_VERTEX_DATA, 0},
Gargaj's avatar
Gargaj committed
517
518
    };

Gargaj's avatar
Gargaj committed
519
    if (pDevice->CreateInputLayout( pQuadDesc, 2, pCode->GetBufferPointer(), pCode->GetBufferSize(), &pFullscreenQuadLayout) != S_OK)
Gargaj's avatar
Gargaj committed
520
521
    {
      printf("[Renderer] CreateInputLayout failed\n");
Gargaj's avatar
Gargaj committed
522
      return false;
Gargaj's avatar
Gargaj committed
523
    }
Gargaj's avatar
Gargaj committed
524

Gargaj's avatar
Gargaj committed
525
526
527
528
529
530
531
532
533
534
535
536
537
538
    //////////////////////////////////////////////////////////////////////////

    D3D11_VIEWPORT viewport;
    ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));

    viewport.TopLeftX = 0;
    viewport.TopLeftY = 0;
    viewport.Width  = settings->nWidth;
    viewport.Height = settings->nHeight;

    pContext->RSSetViewports(1, &viewport);

    //////////////////////////////////////////////////////////////////////////

Gargaj's avatar
Gargaj committed
539
    D3D11_SAMPLER_DESC sampDesc = CD3D11_SAMPLER_DESC( CD3D11_DEFAULT() );
Gargaj's avatar
Gargaj committed
540
541
542
543
    sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
    sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
    sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
    sampDesc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT;
Gargaj's avatar
Gargaj committed
544
    if (pDevice->CreateSamplerState( &sampDesc, &pFullscreenQuadSamplerState ) != S_OK)
Gargaj's avatar
Gargaj committed
545
546
547
548
549
550
      return false;

    //////////////////////////////////////////////////////////////////////////

    D3D11_BUFFER_DESC cbDesc;
    ZeroMemory( &cbDesc, sizeof(D3D11_BUFFER_DESC) );
Gargaj's avatar
Gargaj committed
551
    cbDesc.ByteWidth = sizeof( pFullscreenQuadConstants );
Gargaj's avatar
Gargaj committed
552
553
554
555
556
    cbDesc.Usage = D3D11_USAGE_DYNAMIC;
    cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

    ZeroMemory( &subData, sizeof(D3D11_SUBRESOURCE_DATA) );
Gargaj's avatar
Gargaj committed
557
    subData.pSysMem = &pFullscreenQuadConstants;
Gargaj's avatar
Gargaj committed
558

Gargaj's avatar
Gargaj committed
559
560
561
    if (pDevice->CreateBuffer( &cbDesc, &subData, &pFullscreenQuadConstantBuffer ) != S_OK)
      return false;

Gargaj's avatar
Gargaj committed
562
563
564
565
566
567
568
569
570
571
    //////////////////////////////////////////////////////////////////////////

    D3D11_BLEND_DESC blendDesc = CD3D11_BLEND_DESC( CD3D11_DEFAULT() );
    if (pDevice->CreateBlendState( &blendDesc, &pFullscreenQuadBlendState ) != S_OK)
      return false;

    D3D11_RASTERIZER_DESC rastDesc = CD3D11_RASTERIZER_DESC( CD3D11_DEFAULT() );
    if (pDevice->CreateRasterizerState( &rastDesc, &pFullscreenQuadRasterizerState ) != S_OK)
      return false;

Gargaj's avatar
Gargaj committed
572
573
574
    return true;
  }

575
#define GUIQUADVB_SIZE (1024 * 6)
Gargaj's avatar
Gargaj committed
576

577
  char defaultGUIPixelShader[65536] = 
Gargaj's avatar
Gargaj committed
578
579
    "Texture2D tex;\n"
    "SamplerState smp;\n"
580
    "float4 main( float4 position : SV_POSITION, float4 Color: COLOR, float2 TexCoord : TEXCOORD0, float Factor : TEXCOORD1 ) : SV_TARGET\n"
Gargaj's avatar
Gargaj committed
581
    "{\n"
Gargaj's avatar
Gargaj committed
582
    "  float4 v4Texture = Color * tex.Sample(smp,TexCoord);//float4( Color.rgb, Color.a * .a );\n"
583
584
    "  float4 v4Color = Color;\n"
    "  return lerp( v4Texture, v4Color, Factor );\n"
Gargaj's avatar
Gargaj committed
585
586
    "}\n";
  char defaultGUIVertexShader[65536] = 
587
588
    "struct VS_INPUT_PP { float3 Pos : POSITION; float4 Color: COLOR; float2 TexCoord : TEXCOORD0; float Factor : TEXCOORD1; };\n"
    "struct VS_OUTPUT_PP { float4 Pos : SV_POSITION; float4 Color: COLOR; float2 TexCoord : TEXCOORD0; float Factor : TEXCOORD1; };\n"
Gargaj's avatar
Gargaj committed
589
590
591
592
593
594
595
596
597
598
    "\n"
    "cbuffer c { float4x4 matProj; float2 v2Offset; }\n"
    "\n"
    "VS_OUTPUT_PP main( VS_INPUT_PP In )\n"
    "{\n"
    "  VS_OUTPUT_PP Out;\n"
    "  Out.Pos = float4( In.Pos + float3(v2Offset,0), 1.0 );\n"
    "  Out.Pos = mul( Out.Pos, matProj );\n"
    "  Out.Color = In.Color;\n"
    "  Out.TexCoord = In.TexCoord;\n"
599
    "  Out.Factor = In.Factor;\n"
Gargaj's avatar
Gargaj committed
600
601
602
603
    "  return Out;\n"
    "}\n";

  ID3D11VertexShader * pGUIVertexShader = NULL;
604
  ID3D11PixelShader * pGUIPixelShader = NULL;
Gargaj's avatar
Gargaj committed
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
  ID3D11Buffer * pGUIQuadVB = NULL;
  ID3D11InputLayout * pGUIQuadLayout = NULL;
  ID3D11Buffer * pGUIConstantBuffer = NULL;
  ID3D11BlendState* pGUIBlendState = NULL;
  ID3D11RasterizerState * pGUIRasterizerState = NULL;
  float pGUIMatrix[ 4 * 4 + 16 ];

  void MatrixOrthoOffCenterLH(float * pout, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, FLOAT zf)
  {
    ZeroMemory( pout, sizeof(float) * 4 * 4 );
    pout[0 + 0 * 4] = 2.0f / (r - l);
    pout[1 + 1 * 4] = 2.0f / (t - b);
    pout[2 + 2 * 4] = 1.0f / (zf -zn);
    pout[3 + 0 * 4] = -1.0f -2.0f *l / (r - l);
    pout[3 + 1 * 4] = 1.0f + 2.0f * t / (b - t);
    pout[3 + 2 * 4] = zn / (zn -zf);
    pout[3 + 3 * 4] = 1.0;
  }

  bool InitD3D11GUIRendering( RENDERER_SETTINGS * settings )
  {
    ID3DBlob * pCode = NULL;
    ID3DBlob * pErrors = NULL;
628
    if (D3DCompile( defaultGUIPixelShader, strlen(defaultGUIPixelShader), NULL, NULL, NULL, "main", "ps_4_0", NULL, NULL, &pCode, &pErrors ) != S_OK)
Gargaj's avatar
Gargaj committed
629
    {
Gargaj's avatar
Gargaj committed
630
      printf("[Renderer] D3DCompile (PS) failed\n");
Gargaj's avatar
Gargaj committed
631
632
633
      return false;
    }

634
    if (pDevice->CreatePixelShader( pCode->GetBufferPointer(), pCode->GetBufferSize(), NULL, &pGUIPixelShader ) != S_OK)
Gargaj's avatar
Gargaj committed
635
    {
Gargaj's avatar
Gargaj committed
636
      printf("[Renderer] CreatePixelShader failed\n");
Gargaj's avatar
Gargaj committed
637
638
639
640
641
      return false;
    }

    if (D3DCompile( defaultGUIVertexShader, strlen(defaultGUIVertexShader), NULL, NULL, NULL, "main", "vs_4_0", NULL, NULL, &pCode, &pErrors ) != S_OK)
    {
Gargaj's avatar
Gargaj committed
642
      printf("[Renderer] D3DCompile (VS) failed\n");
Gargaj's avatar
Gargaj committed
643
644
645
646
647
      return false;
    }

    if (pDevice->CreateVertexShader( pCode->GetBufferPointer(), pCode->GetBufferSize(), NULL, &pGUIVertexShader ) != S_OK)
    {
Gargaj's avatar
Gargaj committed
648
      printf("[Renderer] CreateVertexShader failed\n");
Gargaj's avatar
Gargaj committed
649
650
651
652
653
654
      return false;
    }

    D3D11_BUFFER_DESC desc;
    ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));

655
    desc.ByteWidth = sizeof(float) * 7 * GUIQUADVB_SIZE;
Gargaj's avatar
Gargaj committed
656
657
658
659
660
    desc.Usage = D3D11_USAGE_DYNAMIC;
    desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

    if (pDevice->CreateBuffer(&desc, NULL, &pGUIQuadVB) != S_OK)
Gargaj's avatar
Gargaj committed
661
662
    {
      printf("[Renderer] CreateBuffer (VB) failed\n");
Gargaj's avatar
Gargaj committed
663
      return false;
Gargaj's avatar
Gargaj committed
664
    }
Gargaj's avatar
Gargaj committed
665
666
667
668
669
670

    static D3D11_INPUT_ELEMENT_DESC pGUIDesc[] =
    {
      {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0 * sizeof(float), D3D11_INPUT_PER_VERTEX_DATA, 0},
      {"COLOR"   , 0, DXGI_FORMAT_R8G8B8A8_UNORM , 0, 3 * sizeof(float), D3D11_INPUT_PER_VERTEX_DATA, 0},
      {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT   , 0, 4 * sizeof(float), D3D11_INPUT_PER_VERTEX_DATA, 0},
671
      {"TEXCOORD", 1, DXGI_FORMAT_R32_FLOAT      , 0, 6 * sizeof(float), D3D11_INPUT_PER_VERTEX_DATA, 0},
Gargaj's avatar
Gargaj committed
672
673
    };

674
    if (pDevice->CreateInputLayout( pGUIDesc, 4, pCode->GetBufferPointer(), pCode->GetBufferSize(), &pGUIQuadLayout) != S_OK)
Gargaj's avatar
Gargaj committed
675
676
    {
      printf("[Renderer] CreateInputLayout failed\n");
Gargaj's avatar
Gargaj committed
677
      return false;
Gargaj's avatar
Gargaj committed
678
    }
Gargaj's avatar
Gargaj committed
679
680
681

    D3D11_BUFFER_DESC cbDesc;
    ZeroMemory( &cbDesc, sizeof(D3D11_BUFFER_DESC) );
Gargaj's avatar
Gargaj committed
682
    cbDesc.ByteWidth = sizeof( float ) * 4 * 4 * 2;
Gargaj's avatar
Gargaj committed
683
684
685
686
687
688
689
690
691
692
693
    cbDesc.Usage = D3D11_USAGE_DYNAMIC;
    cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

    MatrixOrthoOffCenterLH( pGUIMatrix, 0, nWidth, nHeight, 0, -1.0f, 1.0f );
    
    D3D11_SUBRESOURCE_DATA subData;
    ZeroMemory( &subData, sizeof(D3D11_SUBRESOURCE_DATA) );
    subData.pSysMem = &pGUIMatrix;

    if (pDevice->CreateBuffer( &cbDesc, &subData, &pGUIConstantBuffer ) != S_OK)
Gargaj's avatar
Gargaj committed
694
695
    {
      printf("[Renderer] CreateBuffer (CB) failed\n");
Gargaj's avatar
Gargaj committed
696
      return false;
Gargaj's avatar
Gargaj committed
697
    }
Gargaj's avatar
Gargaj committed
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713

    D3D11_BLEND_DESC blendDesc = CD3D11_BLEND_DESC( CD3D11_DEFAULT() );
    blendDesc.RenderTarget[0].BlendEnable = true;
    blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
    blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
    if (pDevice->CreateBlendState( &blendDesc, &pGUIBlendState ) != S_OK)
      return false;

    D3D11_RASTERIZER_DESC rastDesc = CD3D11_RASTERIZER_DESC( CD3D11_DEFAULT() );
    rastDesc.ScissorEnable = true;
    if (pDevice->CreateRasterizerState( &rastDesc, &pGUIRasterizerState ) != S_OK)
      return false;

    return true;
  }

Gargaj's avatar
Gargaj committed
714
715
  bool Open( RENDERER_SETTINGS * settings )
  {
Gargaj's avatar
Gargaj committed
716
717
718
    nWidth  = settings->nWidth;
    nHeight = settings->nHeight;

Gargaj's avatar
Gargaj committed
719
    if (!InitWindow(settings))
Gargaj's avatar
Gargaj committed
720
721
    {
      printf("[Renderer] InitWindow failed\n");
Gargaj's avatar
Gargaj committed
722
      return false;
Gargaj's avatar
Gargaj committed
723
    }
Gargaj's avatar
Gargaj committed
724
725

    if (!InitDirect3D(settings))
Gargaj's avatar
Gargaj committed
726
727
    {
      printf("[Renderer] InitDirect3D failed\n");
Gargaj's avatar
Gargaj committed
728
      return false;
Gargaj's avatar
Gargaj committed
729
    }
Gargaj's avatar
Gargaj committed
730
731

    if (!InitD3D11QuadRendering(settings))
Gargaj's avatar
Gargaj committed
732
733
    {
      printf("[Renderer] InitD3D11QuadRendering failed\n");
Gargaj's avatar
Gargaj committed
734
      return false;
Gargaj's avatar
Gargaj committed
735
    }
Gargaj's avatar
Gargaj committed
736

Gargaj's avatar
Gargaj committed
737
    if (!InitD3D11GUIRendering(settings))
Gargaj's avatar
Gargaj committed
738
739
    {
      printf("[Renderer] InitD3D11GUIRendering failed\n");
Gargaj's avatar
Gargaj committed
740
      return false;
Gargaj's avatar
Gargaj committed
741
    }
Gargaj's avatar
Gargaj committed
742

Gargaj's avatar
Gargaj committed
743
744
745
746
747
    return true;
  }

  void StartFrame()
  {
Gargaj's avatar
Gargaj committed
748
749
750
751
752
753
754
755
756
    MSG msg;
    if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) 
    {
      TranslateMessage( &msg );
      DispatchMessage( &msg );
    }

    float f[4] = { 0.08f, 0.18f, 0.18f, 1.0f };
    pContext->ClearRenderTargetView(pRenderTarget, f);
Gargaj's avatar
Gargaj committed
757
758
759
  }
  void EndFrame()
  {
Gargaj's avatar
Gargaj committed
760
    pSwapChain->Present( bVsync ? 1 : 0, NULL );
Gargaj's avatar
Gargaj committed
761
762
763
764
765
766
767
  }
  bool WantsToQuit()
  {
    return !run;
  }
  void Close()
  {
Gargaj's avatar
Gargaj committed
768
769
    // TODO: a bunch of other crap needs to be deallocated here but i cant be arsed

Gargaj's avatar
Gargaj committed
770
771
772
    if (theShader) theShader->Release();
    if (pShaderReflection) pShaderReflection->Release();
    if (pVertexShader) pVertexShader->Release();
Gargaj's avatar
Gargaj committed
773

Gargaj's avatar
Gargaj committed
774
775
    if (pFullscreenQuadLayout) pFullscreenQuadLayout->Release();
    if (pFullscreenQuadVB) pFullscreenQuadVB->Release();
Gargaj's avatar
Gargaj committed
776
777
778
779
780
781
782
783
784
785
786
787
    if (pFullscreenQuadSamplerState) pFullscreenQuadSamplerState->Release();
    if (pFullscreenQuadConstantBuffer) pFullscreenQuadConstantBuffer->Release();
    if (pFullscreenQuadBlendState) pFullscreenQuadBlendState->Release();
    if (pFullscreenQuadRasterizerState) pFullscreenQuadRasterizerState->Release();

    if (pGUIRasterizerState) pGUIRasterizerState->Release();
    if (pGUIBlendState) pGUIBlendState->Release();
    if (pGUIConstantBuffer) pGUIConstantBuffer->Release();
    if (pGUIPixelShader) pGUIPixelShader->Release();
    if (pGUIVertexShader) pGUIVertexShader->Release();
    if (pGUIQuadLayout) pGUIQuadLayout->Release();
    if (pGUIQuadVB) pGUIQuadVB->Release();
Gargaj's avatar
Gargaj committed
788
789

    if (pRenderTarget) pRenderTarget->Release();
Gargaj's avatar
Gargaj committed
790
791
    if (pContext) pContext->Release();
    if (pSwapChain) pSwapChain->Release();
Gargaj's avatar
Gargaj committed
792
793
794
795
796
797
798
799
800
801
    if (pDevice) pDevice->Release();
    if (!hWnd) 
    {
      DestroyWindow(hWnd);
      UnregisterClass(_T("fwzwnd"),GetModuleHandle(NULL));
    }
  }

  void RenderFullscreenQuad()
  {
Gargaj's avatar
Gargaj committed
802
    float factor[4] = { 1.0f, 1.0f, 1.0f, 1.0f, };
Gargaj's avatar
Gargaj committed
803
804
805
    pContext->VSSetShader( pVertexShader, NULL, NULL );
    pContext->PSSetShader( theShader, NULL, NULL );
    pContext->IASetInputLayout( pFullscreenQuadLayout );
Gargaj's avatar
Gargaj committed
806
807
    pContext->PSSetSamplers( 0, 1, &pFullscreenQuadSamplerState );
    pContext->PSSetConstantBuffers( 0, 1, &pFullscreenQuadConstantBuffer );
Gargaj's avatar
Gargaj committed
808
809
    pContext->OMSetBlendState( pFullscreenQuadBlendState, factor, 0xFFFFFFFF );
    pContext->RSSetState( pFullscreenQuadRasterizerState );
Gargaj's avatar
Gargaj committed
810
811
812
813
814
815
816
817
818

    ID3D11Buffer * buffers[] = { pFullscreenQuadVB };
    UINT stride[] = { sizeof(float) * 5 };
    UINT offset[] = { 0 };

    pContext->IASetVertexBuffers( 0, 1, buffers, stride, offset );
    pContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP );

    pContext->Draw( 4, 0 );
Gargaj's avatar
Gargaj committed
819
820
  }

Gargaj's avatar
Gargaj committed
821
  ID3D11ShaderReflectionConstantBuffer * pCBuf = NULL;
Gargaj's avatar
Gargaj committed
822
823
  bool ReloadShader( char * szShaderCode, int nShaderCodeSize, char * szErrorBuffer, int nErrorBufferSize )
  {
Gargaj's avatar
Gargaj committed
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
    ID3DBlob * pCode = NULL;
    ID3DBlob * pErrors = NULL;
    if (D3DCompile( szShaderCode, nShaderCodeSize, NULL, NULL, NULL, "main", "ps_4_0", NULL, NULL, &pCode, &pErrors ) != S_OK)
    {
      memset( szErrorBuffer, 0, nErrorBufferSize );
      strncpy( szErrorBuffer, (char*)pErrors->GetBufferPointer(), nErrorBufferSize - 1 );
      return false;
    }

    if (theShader) 
    {
      theShader->Release();
      theShader = NULL;
    }

    if (pDevice->CreatePixelShader( pCode->GetBufferPointer(), pCode->GetBufferSize(), NULL, &theShader ) != S_OK)
    {
      return false;
    }
    D3DReflect( pCode->GetBufferPointer(), pCode->GetBufferSize(), IID_ID3D11ShaderReflection, (void**)&pShaderReflection );
Gargaj's avatar
Gargaj committed
844
845
    pCBuf = pShaderReflection->GetConstantBufferByIndex(0);

Gargaj's avatar
Gargaj committed
846
847
848
    return true;
  }

Gargaj's avatar
Gargaj committed
849
850
851
  void __UpdateConstants()
  {
    D3D11_MAPPED_SUBRESOURCE subRes;
Gargaj's avatar
Gargaj committed
852
853
854
    pContext->Map( pFullscreenQuadConstantBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &subRes );
    CopyMemory( subRes.pData, &pFullscreenQuadConstants, sizeof(pFullscreenQuadConstants) );
    pContext->Unmap( pFullscreenQuadConstantBuffer, NULL );
Gargaj's avatar
Gargaj committed
855
856
  }

Gargaj's avatar
Gargaj committed
857
858
  void SetShaderConstant( char * szConstName, float x )
  {
Gargaj's avatar
Gargaj committed
859
860
    ID3D11ShaderReflectionVariable * pCVar = pCBuf->GetVariableByName( szConstName );
    D3D11_SHADER_VARIABLE_DESC pDesc;
861
862
    if (pCVar->GetDesc( &pDesc ) != S_OK)
      return;
Gargaj's avatar
Gargaj committed
863
    
Gargaj's avatar
Gargaj committed
864
    ((float*)(((unsigned char*)&pFullscreenQuadConstants) + pDesc.StartOffset))[0] = x;
Gargaj's avatar
Gargaj committed
865

Gargaj's avatar
Gargaj committed
866
    __UpdateConstants();
Gargaj's avatar
Gargaj committed
867
868
869
870
  }

  void SetShaderConstant( char * szConstName, float x, float y )
  {
Gargaj's avatar
Gargaj committed
871
872
    ID3D11ShaderReflectionVariable * pCVar = pCBuf->GetVariableByName(szConstName);
    D3D11_SHADER_VARIABLE_DESC pDesc;
873
874
    if (pCVar->GetDesc( &pDesc ) != S_OK)
      return;
Gargaj's avatar
Gargaj committed
875

Gargaj's avatar
Gargaj committed
876
877
    ((float*)(((unsigned char*)&pFullscreenQuadConstants) + pDesc.StartOffset))[0] = x;
    ((float*)(((unsigned char*)&pFullscreenQuadConstants) + pDesc.StartOffset))[1] = y;
Gargaj's avatar
Gargaj committed
878

Gargaj's avatar
Gargaj committed
879
    __UpdateConstants();
Gargaj's avatar
Gargaj committed
880
881
  }

Gargaj's avatar
Gargaj committed
882
  struct DX11Texture : public Texture
Gargaj's avatar
Gargaj committed
883
  {
Gargaj's avatar
Gargaj committed
884
    ID3D11Resource * pTexture;
Gargaj's avatar
Gargaj committed
885
886
    DXGI_FORMAT format;
    ID3D11ShaderResourceView * pResourceView;
Gargaj's avatar
Gargaj committed
887
888
  };

Gargaj's avatar
Gargaj committed
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
  void CreateResourceView( DX11Texture * tex )
  {
    D3D11_SHADER_RESOURCE_VIEW_DESC desc;
    ZeroMemory( &desc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC) );
    desc.Format = tex->format;
    if (tex->type == TEXTURETYPE_1D)
    {
      desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
      desc.Texture1D.MostDetailedMip = 0;
      desc.Texture1D.MipLevels = 1;
    }
    else if (tex->type == TEXTURETYPE_2D)
    {
      desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
      desc.Texture2D.MostDetailedMip = 0;
      desc.Texture2D.MipLevels = 1;
    }
    pDevice->CreateShaderResourceView( tex->pTexture, &desc, &tex->pResourceView );
  }

Gargaj's avatar
Gargaj committed
909
910
911
  int textureUnit = 0;
  Texture * CreateRGBA8TextureFromFile( char * szFilename )
  {
Gargaj's avatar
Gargaj committed
912
913
914
915
916
917
918
919
920
921
    int comp = 0;
    int width = 0;
    int height = 0;
    unsigned char * c = stbi_load( szFilename, (int*)&width, (int*)&height, &comp, STBI_rgb_alpha );
    if (!c) return NULL;

    D3D11_TEXTURE2D_DESC desc;
    ZeroMemory(&desc,sizeof(D3D11_TEXTURE2D_DESC));
    desc.Width = width;
    desc.Height = height;
Gargaj's avatar
Gargaj committed
922
    desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
Gargaj's avatar
Gargaj committed
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
    desc.MipLevels = 1;
    desc.ArraySize = 1;
    desc.SampleDesc.Count = 1;
    desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    
    D3D11_SUBRESOURCE_DATA subData;
    ZeroMemory(&subData,sizeof(D3D11_SUBRESOURCE_DATA));
    subData.pSysMem = c;
    subData.SysMemPitch = width * sizeof(unsigned char) * 4;

    ID3D11Texture2D * pTex = NULL;

    if (pDevice->CreateTexture2D( &desc, &subData, &pTex ) != S_OK)
      return NULL;

    stbi_image_free(c);

    DX11Texture * tex = new DX11Texture();
    tex->width = width;
    tex->height = height;
    tex->pTexture = pTex;
    tex->type = TEXTURETYPE_2D;
    tex->format = desc.Format;
    CreateResourceView(tex);
    return tex;
Gargaj's avatar
Gargaj committed
948
949
950
951
  }

  Texture * Create1DR32Texture( int w )
  {
Gargaj's avatar
Gargaj committed
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
    D3D11_TEXTURE1D_DESC desc;
    ZeroMemory(&desc,sizeof(D3D11_TEXTURE1D_DESC));
    desc.Width = w;
    desc.Format = DXGI_FORMAT_R32_FLOAT;
    desc.MipLevels = 1;
    desc.ArraySize = 1;
    desc.Usage = D3D11_USAGE_DYNAMIC;
    desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;

    ID3D11Texture1D * pTex = NULL;

    if (pDevice->CreateTexture1D( &desc, NULL, &pTex ) != S_OK)
      return NULL;

    DX11Texture * tex = new DX11Texture();
    tex->width = w;
    tex->height = 1;
    tex->pTexture = pTex;
    tex->type = TEXTURETYPE_1D;
    tex->format = desc.Format;
    CreateResourceView(tex);
    return tex;
Gargaj's avatar
Gargaj committed
975
976
977
978
  }

  void SetShaderTexture( char * szTextureName, Texture * tex )
  {
Gargaj's avatar
Gargaj committed
979
980
981
982
983
984
    D3D11_SHADER_INPUT_BIND_DESC desc;
    if (pShaderReflection->GetResourceBindingDescByName( szTextureName, &desc ) == S_OK)
    {
      DX11Texture * pTex = (DX11Texture *) tex;
      pContext->PSSetShaderResources( desc.BindPoint, 1, &pTex->pResourceView );
    }
Gargaj's avatar
Gargaj committed
985
986
987
988
  }

  bool UpdateR32Texture( Texture * tex, float * data )
  {
Gargaj's avatar
Gargaj committed
989
990
991
992
993
994
    ID3D11Texture1D * pTex = (ID3D11Texture1D *) ((DX11Texture *) tex)->pTexture;

    D3D11_MAPPED_SUBRESOURCE subRes;
    pContext->Map( pTex, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &subRes );
    CopyMemory( subRes.pData, data, sizeof(float) * tex->width );
    pContext->Unmap( pTex, NULL );
Gargaj's avatar
Gargaj committed
995
996
997
998
999
    return true;
  }

  Texture * CreateA8TextureFromData( int w, int h, unsigned char * data )
  {
Gargaj's avatar
Gargaj committed
1000
1001
1002
1003
    D3D11_TEXTURE2D_DESC desc;
    ZeroMemory(&desc,sizeof(D3D11_TEXTURE2D_DESC));
    desc.Width = w;
    desc.Height = h;
Gargaj's avatar
Gargaj committed
1004
    desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
Gargaj's avatar
Gargaj committed
1005
1006
1007
1008
1009
    desc.MipLevels = 1;
    desc.ArraySize = 1;
    desc.SampleDesc.Count = 1;
    desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;

Gargaj's avatar
Gargaj committed
1010
1011
1012
    unsigned int * p = new unsigned int[ w * h ];
    for (int i=0; i < w * h; i++)
      p[i] = (data[i] << 24) | 0xFFFFFF;
Gargaj's avatar
Gargaj committed
1013
1014
    D3D11_SUBRESOURCE_DATA subData;
    ZeroMemory(&subData,sizeof(D3D11_SUBRESOURCE_DATA));
Gargaj's avatar
Gargaj committed
1015
1016
    subData.pSysMem = p;
    subData.SysMemPitch = w * sizeof(unsigned int);
Gargaj's avatar
Gargaj committed
1017
1018
1019
1020
1021
1022

    ID3D11Texture2D * pTex = NULL;

    if (pDevice->CreateTexture2D( &desc, &subData, &pTex ) != S_OK)
      return NULL;

Gargaj's avatar
Gargaj committed
1023
1024
    delete[] p;

Gargaj's avatar
Gargaj committed
1025
1026
1027
1028
1029
1030
1031
1032
    DX11Texture * tex = new DX11Texture();
    tex->width = w;
    tex->height = h;
    tex->pTexture = pTex;
    tex->type = TEXTURETYPE_2D;
    tex->format = desc.Format;
    CreateResourceView(tex);
    return tex;
Gargaj's avatar
Gargaj committed
1033
1034
  }

Gargaj's avatar
Gargaj committed
1035
1036
1037
1038
1039
1040
1041
  void ReleaseTexture( Texture * tex )
  {
    ((DX11Texture *)tex)->pResourceView->Release();
    ((DX11Texture *)tex)->pTexture->Release();
    delete tex;
  }

Gargaj's avatar
Gargaj committed
1042
1043
1044
  //////////////////////////////////////////////////////////////////////////
  // text rendering

1045
1046
  int nDrawCallCount = 0;
  Texture * lastTexture = NULL;
Gargaj's avatar
Gargaj committed
1047
1048
  void StartTextRendering()
  {
Gargaj's avatar
Gargaj committed
1049
1050
    float factor[4] = { 1.0, 1.0, 1.0, 1.0 };
    pContext->VSSetShader( pGUIVertexShader, NULL, NULL );
1051
    pContext->PSSetShader( pGUIPixelShader, NULL, NULL );
Gargaj's avatar
Gargaj committed
1052
1053
1054
1055
1056
1057
    pContext->IASetInputLayout( pGUIQuadLayout );
    pContext->VSSetConstantBuffers( 0, 1, &pGUIConstantBuffer );
    pContext->OMSetBlendState( pGUIBlendState, factor, 0xFFFFFFFF );
    pContext->RSSetState( pGUIRasterizerState );

    ID3D11Buffer * buffers[] = { pGUIQuadVB };
1058
    UINT stride[] = { sizeof(float) * 7 };
Gargaj's avatar
Gargaj committed
1059
    UINT offset[] = { 0 };
Gargaj's avatar
Gargaj committed
1060

Gargaj's avatar
Gargaj committed
1061
    pContext->IASetVertexBuffers( 0, 1, buffers, stride, offset );
1062
1063
1064
    lastTexture = NULL;
    
    nDrawCallCount = 0;
Gargaj's avatar
Gargaj committed
1065
1066
1067
  }

  int bufferPointer = 0;
1068
  unsigned char buffer[GUIQUADVB_SIZE * sizeof(float) * 7];
Gargaj's avatar
Gargaj committed
1069
1070
1071
1072
1073
  bool lastModeIsQuad = true;
  void __FlushRenderCache()
  {
    if (!bufferPointer) return;

Gargaj's avatar
Gargaj committed
1074
1075
    D3D11_MAPPED_SUBRESOURCE subRes;
    pContext->Map( pGUIQuadVB, 0, D3D11_MAP_WRITE_DISCARD, NULL, &subRes );
1076
    CopyMemory( subRes.pData, buffer, bufferPointer * sizeof(float) * 7 );
Gargaj's avatar
Gargaj committed
1077
    pContext->Unmap( pGUIQuadVB, 0 );
Gargaj's avatar
Gargaj committed
1078
1079

    if (lastModeIsQuad)
Gargaj's avatar
Gargaj committed
1080
1081
1082
    {
      pContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
    }
Gargaj's avatar
Gargaj committed
1083
    else
Gargaj's avatar
Gargaj committed
1084
1085
1086
1087
    {
      pContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_LINELIST );
    }
    pContext->Draw( bufferPointer, 0 );
1088
    nDrawCallCount++;
Gargaj's avatar
Gargaj committed
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098

    bufferPointer = 0;
  }
  void __WriteVertexToBuffer( const Vertex & v )
  {
    if (bufferPointer >= GUIQUADVB_SIZE)
    {
      __FlushRenderCache();
    }

1099
    float * f = (float*)(buffer + bufferPointer * sizeof(float) * 7);
Gargaj's avatar
Gargaj committed
1100
1101
1102
    *(f++) = v.x;
    *(f++) = v.y;
    *(f++) = 0.0;
Gargaj's avatar
Gargaj committed
1103
    *(unsigned int *)(f++) = v.c;
Gargaj's avatar
Gargaj committed
1104
1105
    *(f++) = v.u;
    *(f++) = v.v;
1106
    *(f++) = lastTexture ? 0.0 : 1.0;
Gargaj's avatar
Gargaj committed
1107
1108
1109
1110
1111
1112
1113
    bufferPointer++;
  }
  void BindTexture( Texture * tex )
  {
    if (lastTexture != tex)
    {
      lastTexture = tex;
Gargaj's avatar
Gargaj committed
1114
1115
      if (tex)
      {
Gargaj's avatar
Gargaj committed
1116
        __FlushRenderCache();
Gargaj's avatar
Gargaj committed
1117
1118
1119
        DX11Texture * pTex = (DX11Texture *) tex;
        pContext->PSSetShaderResources( 0, 1, &pTex->pResourceView );
      }
Gargaj's avatar
Gargaj committed
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
    }
  }

  void RenderQuad( const Vertex & a, const Vertex & b, const Vertex & c, const Vertex & d )
  {
    if (!lastModeIsQuad)
    {
      __FlushRenderCache();
      lastModeIsQuad = true;
    }
    __WriteVertexToBuffer(a);
    __WriteVertexToBuffer(b);
    __WriteVertexToBuffer(d);
    __WriteVertexToBuffer(b);
    __WriteVertexToBuffer(c);
Gargaj's avatar
Gargaj committed
1135
    __WriteVertexToBuffer(d);
Gargaj's avatar
Gargaj committed
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
  }

  void RenderLine( const Vertex & a, const Vertex & b )
  {
    if (lastModeIsQuad)
    {
      __FlushRenderCache();
      lastModeIsQuad = false;
    }
    __WriteVertexToBuffer(a);
    __WriteVertexToBuffer(b);
  }

  void SetTextRenderingViewport( Scintilla::PRectangle rect )
  {
    __FlushRenderCache();
Gargaj's avatar
Gargaj committed
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162

    pGUIMatrix[ 16 + 0 ] = rect.left;
    pGUIMatrix[ 16 + 1 ] = rect.top;

    D3D11_MAPPED_SUBRESOURCE subRes;
    pContext->Map( pGUIConstantBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &subRes );
    CopyMemory( subRes.pData, &pGUIMatrix, sizeof(float) * 16 * 2 );
    pContext->Unmap( pGUIConstantBuffer, NULL );

    D3D11_RECT rc = { rect.left, rect.top, rect.right, rect.bottom };
    pContext->RSSetScissorRects( 1, &rc );
Gargaj's avatar
Gargaj committed
1163
1164
1165
1166
1167
1168
  }
  void EndTextRendering()
  {
    __FlushRenderCache();
  }

1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
  //////////////////////////////////////////////////////////////////////////

  bool GrabFrame( void * pPixelBuffer )
  {
    if (!pFrameGrabTexture)
      return false;

    pContext->CopyResource( pFrameGrabTexture, pBackBuffer );

    D3D11_MAPPED_SUBRESOURCE resource;
    unsigned int nSubresource = D3D11CalcSubresource( 0, 0, 0 );
    if (pContext->Map( pFrameGrabTexture, nSubresource, D3D11_MAP_READ, 0, &resource ) != S_OK)
      return false;
    
    unsigned char* pSrc = (unsigned char*)resource.pData;
    unsigned char* pDst = (unsigned char*)pPixelBuffer;
    for( int i = 0; i < nHeight; i++ )
    {
      memcpy( pDst, pSrc, nWidth * 4 );
      pSrc += resource.RowPitch;
      pDst += nWidth * 4;
    }

    pContext->Unmap( pFrameGrabTexture, nSubresource );

    return true;
  }

Gargaj's avatar
Gargaj committed
1197
}