1 #include <windows.h>
2 #include <windowsx.h>
3 #include <tchar.h>
4 #include <d3d9.h>
5 #include <d3dx9.h>
6 #include "../Renderer.h"
7 
8 #define STB_IMAGE_IMPLEMENTATION
9 #include <stb_image.h>
10 #include "Scintilla.h"
11 
12 #define DEVTYPE D3DDEVTYPE_HAL
13 
14 #if defined(__MINGW32__) && !defined(D3D9b_SDK_VERSION)
15 #define D3D9b_SDK_VERSION 31
16   // From https://docs.rs/winapi/0.2.8/i686-pc-windows-gnu/winapi/d3d9/constant.D3D9b_SDK_VERSION.html
17 #endif
18 
19 #ifndef WM_MOUSEHWHEEL
20 #define WM_MOUSEHWHEEL (0x020E)
21 #endif
22 
23 const char * shaderKeyword =
24   " register packoffset static const"
25   " break continue discard do for if else switch while case default return true false"
26   " BINORMAL BINORMAL0 BINORMAL1 BINORMAL2 BINORMAL3 BINORMAL4 BINORMAL5 BINORMAL6 BINORMAL7"
27   " BLENDINDICES BLENDINDICES0 BLENDINDICES1 BLENDINDICES2 BLENDINDICES3 BLENDINDICES4 BLENDINDICES5 BLENDINDICES6 BLENDINDICES7"
28   " BLENDWEIGHT BLENDWEIGHT0 BLENDWEIGHT1 BLENDWEIGHT2 BLENDWEIGHT3 BLENDWEIGHT4 BLENDWEIGHT5 BLENDWEIGHT6 BLENDWEIGHT7"
29   " COLOR COLOR0 COLOR1 COLOR2 COLOR3 COLOR4 COLOR5 COLOR6 COLOR7"
30   " NORMAL NORMAL0 NORMAL1 NORMAL2 NORMAL3 NORMAL4 NORMAL5 NORMAL6 NORMAL7"
31   " POSITION POSITION0 POSITION1 POSITION2 POSITION3 POSITION4 POSITION5 POSITION6 POSITION7"
32   " POSITIONT"
33   " PSIZE PSIZE0 PSIZE1 PSIZE2 PSIZE3 PSIZE4 PSIZE5 PSIZE6 PSIZE7"
34   " TANGENT TANGENT0 TANGENT1 TANGENT2 TANGENT3 TANGENT4 TANGENT5 TANGENT6 TANGENT7"
35   " TEXCOORD TEXCOORD0 TEXCOORD1 TEXCOORD2 TEXCOORD3 TEXCOORD4 TEXCOORD5 TEXCOORD6 TEXCOORD7 TEXCOORD8 TEXCOORD9"
36   " TEXCOORD0 TEXCOORD1 TEXCOORD2 TEXCOORD3 TEXCOORD4 TEXCOORD5 TEXCOORD6 TEXCOORD7 TEXCOORD8 TEXCOORD9"
37   " 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"
38   " SV_TARGET SV_Target SV_Target0 SV_Target1 SV_Target2 SV_Target3 SV_Target4 SV_Target5 SV_Target6 SV_Target7"
39   " SV_ClipDistance0 SV_ClipDistance1 SV_ClipDistance2 SV_ClipDistance3 SV_ClipDistance4 SV_ClipDistance5 SV_ClipDistance6 SV_ClipDistance7"
40   " SV_CullDistance0 SV_CullDistance1 SV_CullDistance2 SV_CullDistance3 SV_CullDistance4 SV_CullDistance5 SV_CullDistance6 SV_CullDistance7";
41 
42 const char * shaderType =
43   "bool bool1 bool2 bool3 bool4"
44   " bool1x1 bool1x2 bool1x3 bool1x4"
45   " bool2x1 bool2x2 bool2x3 bool2x4"
46   " bool3x1 bool3x2 bool3x3 bool3x4"
47   " bool4x1 bool4x2 bool4x3 bool4x4"
48   " int int1 int2 int3 int4"
49   " int1x1 int1x2 int1x3 int1x4"
50   " int2x1 int2x2 int2x3 int2x4"
51   " int3x1 int3x2 int3x3 int3x4"
52   " int4x1 int4x2 int4x3 int4x4"
53   " uint uint1 uint2 uint3 uint4"
54   " uint1x1 uint1x2 uint1x3 uint1x4"
55   " uint2x1 uint2x2 uint2x3 uint2x4"
56   " uint3x1 uint3x2 uint3x3 uint3x4"
57   " uint4x1 uint4x2 uint4x3 uint4x4"
58   " UINT UINT2 UINT3 UINT4"
59   " dword dword1 dword2 dword3 dword4"
60   " dword1x1 dword1x2 dword1x3 dword1x4"
61   " dword2x1 dword2x2 dword2x3 dword2x4"
62   " dword3x1 dword3x2 dword3x3 dword3x4"
63   " dword4x1 dword4x2 dword4x3 dword4x4"
64   " half half1 half2 half3 half4"
65   " half1x1 half1x2 half1x3 half1x4"
66   " half2x1 half2x2 half2x3 half2x4"
67   " half3x1 half3x2 half3x3 half3x4"
68   " half4x1 half4x2 half4x3 half4x4"
69   " float float1 float2 float3 float4"
70   " float1x1 float1x2 float1x3 float1x4"
71   " float2x1 float2x2 float2x3 float2x4"
72   " float3x1 float3x2 float3x3 float3x4"
73   " float4x1 float4x2 float4x3 float4x4"
74   " double double1 double2 double3 double4"
75   " double1x1 double1x2 double1x3 double1x4"
76   " double2x1 double2x2 double2x3 double2x4"
77   " double3x1 double3x2 double3x3 double3x4"
78   " double4x1 double4x2 double4x3 double4x4"
79   " snorm unorm string void cbuffer struct"
80   " Buffer AppendStructuredBfufer ByteAddressBuffer ConsumeStructuredBuffer StructuredBuffer"
81   " RWBuffer RWByteAddressBuffer RWStructuredBuffer RWTexture1D RWTexture1DArray RWTexture2D RWTexture2DArray RWTexture3D"
82   " InputPatch OutputPatch"
83   " linear centroid nointerpolation noperspective sample"
84   " sampler sampler1D sampler2D sampler3D samplerCUBE SamplerComparisonState SamplerState sampler_state"
85   " AddressU AddressV AddressW BorderColor Filter MaxAnisotropy MaxLOD MinLOD MipLODBias ComparisonFunc ComparisonFilter"
86   " texture Texture1D Texture1DArray Texture2D Texture2DArray Texture2DMS Texture2DMSArray Texture3D TextureCube";
87 
88 const char * shaderBuiltin =
89   "abs acos all AllMemoryBarrier AllMemoryBarrierWithGroupSync any asdouble"
90   " asfloat asin asint asuint atan atan2 ceil clamp clip cos cosh countbits"
91   " cross D3DCOLORtoUBYTE4 ddx ddx_coarse ddx_fine ddy ddy_coarse ddy_fine"
92   " degrees determinant DeviceMemoryBarrier DeviceMemoryBarrierWithGroupSync"
93   " distance dot dst EvaluateAttributeAtCentroid EvaluateAttributeAtSample"
94   " EvaluateAttributeSnapped exp exp2 f16tof32 f32tof16 faceforward firstbithigh"
95   " firstbitlow floor fmod frac frexp fwidth GetRenderTargetSampleCount"
96   " GetRenderTargetSamplePosition GroupMemoryBarrier GroupMemoryBarrierWithGroupSync"
97   " InterlockedAdd InterlockedAnd InterlockedCompareExchange InterlockedCompareStore"
98   " InterlockedExchange InterlockedMax InterlockedMin InterlockedOr InterlockedXor"
99   " isfinite isinf isnan ldexp length lerp lit log log10 log2 mad max min modf mul"
100   " noise normalize pow Process2DQuadTessFactorsAvg Process2DQuadTessFactorsMax"
101   " Process2DQuadTessFactorsMin ProcessIsolineTessFactors ProcessQuadTessFactorsAvg"
102   " ProcessQuadTessFactorsMax ProcessQuadTessFactorsMin ProcessTriTessFactorsAvg"
103   " ProcessTriTessFactorsMax ProcessTriTessFactorsMin radians rcp reflect refract"
104   " reversebits round rsqrt saturate sign sin sincos sinh smoothstep sqrt step"
105   " tan tanh tex1D tex1Dbias tex1Dgrad tex1Dlod tex1Dproj tex2D tex2Dbias"
106   " tex2Dgrad tex2Dlod tex2Dproj tex3D tex3Dbias tex3Dgrad tex3Dlod tex3Dproj"
107   " texCUBE texCUBEbias texCUBEgrad texCUBElod texCUBEproj transpose trunc";
108 
109 namespace Renderer
110 {
111   const char * defaultShaderFilename = "shader.dx9.hlsl";
112   const char defaultShader[65536] =
113     "texture texTFFT; sampler1D texFFT = sampler_state { Texture = <texTFFT>; }; \n"
114     "// towards 0.0 is bass / lower freq, towards 1.0 is higher / treble freq\n"
115     "texture texFFTSmoothedT; sampler1D texFFTSmoothed = sampler_state { Texture = <texFFTSmoothedT>; }; \n"
116     "// this one has longer falloff and less harsh transients\n"
117     "texture texFFTIntegratedT; sampler1D texFFTIntegrated = sampler_state { Texture = <texFFTIntegratedT>; }; \n"
118     "// this is continually increasing\n"
119     "texture texPreviousFrameT; sampler2D texPreviousFrame = sampler_state { Texture = <texPreviousFrameT>; }; \n"
120     "// screenshot of the previous frame\n"
121     "\n"
122     "{%textures:begin%}" // leave off \n here
123     "texture raw{%textures:name%}; sampler2D {%textures:name%} = sampler_state { Texture = <raw{%textures:name%}>; };\n"
124     "{%textures:end%}"
125     "\n"
126     "{%midi:begin%}" // leave off \n here
127     "float {%midi:name%};\n"
128     "{%midi:end%}"
129     "float fGlobalTime; // in seconds\n"
130     "float fFrameTime; // duration of the last frame, in seconds\n"
131     "float2 v2Resolution; // viewport resolution (in pixels)\n"
132     "\n"
133     "float4 plas( float2 v, float time )\n"
134     "{\n"
135     "\tfloat c = 0.5 + sin( v.x * 10.0 ) + cos( sin( time + v.y ) * 20.0 );\n"
136     "\treturn float4( sin(c * 0.2 + cos(time)), c * 0.15, cos( c * 0.1 + time / .4 ) * .25, 1.0 );\n"
137     "}\n"
138     "\n"
139     "float4 main( float2 TexCoord : TEXCOORD0 ) : COLOR0\n"
140     "{\n"
141     "\tfloat2 uv = TexCoord;\n"
142     "\tuv -= 0.5;\n"
143     "\tuv /= float2(v2Resolution.y / v2Resolution.x, 1);"
144     "\n"
145     "\tfloat2 m;\n"
146     "\tm.x = atan(uv.x / uv.y) / 3.14;\n"
147     "\tm.y = 1 / length(uv) * .2;\n"
148     "\tfloat d = m.y;\n"
149     "\n"
150     "\tfloat f = tex1D( texFFT, d ).r * 100;\n"
151     "\tm.x += sin( fGlobalTime ) * 0.1;\n"
152     "\tm.y += fGlobalTime * 0.25;\n"
153     "\n"
154     "\tfloat4 t = plas( m * 3.14, fGlobalTime ) / d;\n"
155     "\tt = saturate( t );\n"
156     "\treturn f + t;\n"
157     "}";
158   char defaultVertexShader[65536] =
159     "struct VS_INPUT_PP { float3 Pos : POSITION0; float2 TexCoord : TEXCOORD0; };\n"
160     "struct VS_OUTPUT_PP { float4 Pos : POSITION0; float2 TexCoord : TEXCOORD0; };\n"
161     "\n"
162     "VS_OUTPUT_PP main( VS_INPUT_PP In )\n"
163     "{\n"
164     "\tVS_OUTPUT_PP Out;\n"
165     "\tOut.Pos = float4( In.Pos, 1.0 );\n"
166     "\tOut.TexCoord = In.TexCoord;\n"
167     "\treturn Out;\n"
168     "}\n";
169 
170   bool run = true;
171 
172   LPDIRECT3D9 pD3D = NULL;
173   LPDIRECT3DDEVICE9 pDevice = NULL;
174   LPD3DXCONSTANTTABLE pConstantTable = NULL;
175   LPDIRECT3DVERTEXSHADER9 pVertexShader = NULL;
176   LPDIRECT3DPIXELSHADER9 theShader = NULL;
177   LPDIRECT3DSURFACE9 pBackBuffer = NULL;
178   LPDIRECT3DSURFACE9 pFrameGrabTexture = NULL;
179 
180   int nWidth = 0;
181   int nHeight = 0;
182   HWND hWnd = NULL;
183 
184   KeyEvent keyEventBuffer[512];
185   int keyEventBufferCount = 0;
186   MouseEvent mouseEventBuffer[512];
187   int mouseEventBufferCount = 0;
188 
WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)189   LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
190   {
191     switch (uMsg)
192     {
193     case WM_KEYDOWN:
194       {
195         int sciKey = 0;
196         switch(wParam)
197         {
198         case VK_DOWN:         sciKey = SCK_DOWN;      break;
199         case VK_UP:           sciKey = SCK_UP;        break;
200         case VK_LEFT:         sciKey = SCK_LEFT;      break;
201         case VK_RIGHT:        sciKey = SCK_RIGHT;     break;
202         case VK_HOME:         sciKey = SCK_HOME;      break;
203         case VK_END:          sciKey = SCK_END;       break;
204         case VK_PRIOR:        sciKey = SCK_PRIOR;     break;
205         case VK_NEXT:         sciKey = SCK_NEXT;      break;
206         case VK_DELETE:       sciKey = SCK_DELETE;    break;
207         case VK_INSERT:       sciKey = SCK_INSERT;    break;
208         case VK_ESCAPE:       sciKey = SCK_ESCAPE;    break;
209         case VK_BACK:         sciKey = SCK_BACK;      break;
210         case VK_TAB:          sciKey = SCK_TAB;       break;
211         case VK_RETURN:       sciKey = SCK_RETURN;    break;
212 //         case VK_KP_PLUS:      sciKey = SCK_ADD;       break;
213 //         case VK_KP_MINUS:     sciKey = SCK_SUBTRACT;  break;
214 //         case VK_KP_DIVIDE:    sciKey = SCK_DIVIDE;    break;
215 //         case VK_LSUPER:       sciKey = SCK_WIN;       break;
216 //         case VK_RSUPER:       sciKey = SCK_RWIN;      break;
217         case VK_MENU:         sciKey = SCK_MENU;      break;
218 //         case VK_SLASH:        sciKey = '/';           break;
219 //         case VK_ASTERISK:     sciKey = '`';           break;
220 //         case VK_LEFTBRACKET:  sciKey = '[';           break;
221 //         case VK_BACKSLASH:    sciKey = '\\';          break;
222 //         case VK_RIGHTBRACKET: sciKey = ']';           break;
223         case VK_F2:         sciKey = 283;      break;
224         case VK_F5:         sciKey = 286;      break;
225         case VK_F11:        sciKey = 292;      break;
226         case VK_SHIFT:
227         case VK_LSHIFT:
228         case VK_RSHIFT:
229         case VK_LMENU:
230         case VK_RMENU:
231         case VK_CONTROL:
232         case VK_LCONTROL:
233         case VK_RCONTROL:
234           sciKey = 0;
235           break;
236         default:
237           sciKey = wParam;
238         }
239         if (sciKey)
240         {
241           keyEventBuffer[keyEventBufferCount].ctrl  = GetAsyncKeyState( VK_LCONTROL ) || GetAsyncKeyState( VK_RCONTROL );
242           keyEventBuffer[keyEventBufferCount].alt   = GetAsyncKeyState( VK_LMENU ) || GetAsyncKeyState( VK_RMENU );
243           keyEventBuffer[keyEventBufferCount].shift = GetAsyncKeyState( VK_LSHIFT ) || GetAsyncKeyState( VK_RSHIFT );
244           keyEventBuffer[keyEventBufferCount].scanCode = sciKey;
245           keyEventBuffer[keyEventBufferCount].character = 0;
246           keyEventBufferCount++;
247         }
248         //pKeys[wParam] = 1;
249       } break;
250     case WM_CHAR:
251       {
252         if (wParam >= 32)
253         {
254           keyEventBuffer[keyEventBufferCount].ctrl  = GetAsyncKeyState( VK_LCONTROL ) || GetAsyncKeyState( VK_RCONTROL );
255           keyEventBuffer[keyEventBufferCount].alt   = GetAsyncKeyState( VK_LMENU ) || GetAsyncKeyState( VK_RMENU );
256           keyEventBuffer[keyEventBufferCount].shift = GetAsyncKeyState( VK_LSHIFT ) || GetAsyncKeyState( VK_RSHIFT );
257           keyEventBuffer[keyEventBufferCount].scanCode = 0;
258           keyEventBuffer[keyEventBufferCount].character = wParam;
259           keyEventBufferCount++;
260         }
261         //pKeys[wParam] = 1;
262       } break;
263 
264     case WM_KEYUP:
265       {
266         //pKeys[wParam] = 0;
267       } break;
268 
269     case WM_LBUTTONDOWN:
270       {
271         mouseEventBuffer[mouseEventBufferCount].eventType = MOUSEEVENTTYPE_DOWN;
272         mouseEventBuffer[mouseEventBufferCount].button = MOUSEBUTTON_LEFT;
273         mouseEventBuffer[mouseEventBufferCount].x = GET_X_LPARAM(lParam);
274         mouseEventBuffer[mouseEventBufferCount].y = GET_Y_LPARAM(lParam);
275         mouseEventBufferCount++;
276       } break;
277 
278     case WM_MOUSEMOVE:
279       {
280         mouseEventBuffer[mouseEventBufferCount].eventType = MOUSEEVENTTYPE_MOVE;
281         mouseEventBuffer[mouseEventBufferCount].x = GET_X_LPARAM(lParam);
282         mouseEventBuffer[mouseEventBufferCount].y = GET_Y_LPARAM(lParam);
283         mouseEventBufferCount++;
284       } break;
285 
286     case WM_LBUTTONUP:
287       {
288         mouseEventBuffer[mouseEventBufferCount].eventType = MOUSEEVENTTYPE_UP;
289         mouseEventBuffer[mouseEventBufferCount].button = MOUSEBUTTON_LEFT;
290         mouseEventBuffer[mouseEventBufferCount].x = GET_X_LPARAM(lParam);
291         mouseEventBuffer[mouseEventBufferCount].y = GET_Y_LPARAM(lParam);
292         mouseEventBufferCount++;
293       } break;
294 
295     case WM_MOUSEWHEEL:
296       {
297         mouseEventBuffer[mouseEventBufferCount].eventType = MOUSEEVENTTYPE_SCROLL;
298         mouseEventBuffer[mouseEventBufferCount].x = 0;
299         mouseEventBuffer[mouseEventBufferCount].y = GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA;
300         mouseEventBufferCount++;
301       } break;
302 
303     case WM_MOUSEHWHEEL:
304       {
305         mouseEventBuffer[mouseEventBufferCount].eventType = MOUSEEVENTTYPE_SCROLL;
306         mouseEventBuffer[mouseEventBufferCount].x = -GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA;
307         mouseEventBuffer[mouseEventBufferCount].y = 0;
308         mouseEventBufferCount++;
309       } break;
310 
311     case WM_SYSCOMMAND:
312       {
313         switch (wParam)
314         {
315         case SC_SCREENSAVE:
316         case SC_MONITORPOWER:
317           {
318             return 0;
319           }
320         }
321       } break;
322 
323     case WM_CLOSE:
324       {
325         run = false;
326       } break;
327     }
328 
329     return DefWindowProc(hWnd, uMsg, wParam, lParam);
330   }
331 
InitWindow(RENDERER_SETTINGS * pSetup)332   bool InitWindow(RENDERER_SETTINGS * pSetup)
333   {
334     WNDCLASS WC;
335 
336     WC.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
337     WC.lpfnWndProc = &WndProc;
338     WC.cbClsExtra = 0;
339     WC.cbWndExtra = 0;
340     WC.hInstance = GetModuleHandle(NULL);
341     //WC.hIcon = LoadIcon(setup->hInstance,MAKEINTRESOURCE(IDI_ICON1));
342     WC.hIcon = NULL;
343     WC.hCursor = LoadCursor(NULL, IDC_ARROW);
344     WC.hbrBackground = NULL;
345     WC.lpszMenuName = NULL;
346     WC.lpszClassName = _T("fwzwnd");
347     if(!RegisterClass(&WC)) return 0;
348 
349     DWORD wExStyle = WS_EX_APPWINDOW;
350     DWORD wStyle = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
351     if (pSetup->windowMode == RENDERER_WINDOWMODE_WINDOWED) wStyle |= WS_OVERLAPPED | WS_CAPTION;
352 
353     RECT wr={0,0,pSetup->nWidth,pSetup->nHeight};
354     AdjustWindowRectEx(&wr, wStyle, FALSE, wExStyle);
355 
356     hWnd = CreateWindowEx(wExStyle,_T("fwzwnd"),_T("BONZOMATIC - Direct3D 9.0c edition"),wStyle,
357       (GetSystemMetrics(SM_CXSCREEN) - pSetup->nWidth )/2,
358       (GetSystemMetrics(SM_CYSCREEN) - pSetup->nHeight)/2,
359       wr.right-wr.left, wr.bottom-wr.top,
360       NULL, NULL, WC.hInstance, NULL);
361 
362     if (!hWnd)
363       return false;
364 
365     ShowWindow(hWnd, SW_SHOW);
366     SetForegroundWindow(hWnd);
367     SetFocus(hWnd);
368 
369     return true;
370   }
371 
372   D3DPRESENT_PARAMETERS d3dpp;
InitDirect3D(RENDERER_SETTINGS * pSetup)373   bool InitDirect3D(RENDERER_SETTINGS * pSetup)
374   {
375     pD3D = Direct3DCreate9(D3D9b_SDK_VERSION);
376     if (!pD3D)
377     {
378       printf("[Renderer] Direct3DCreate9 failed\n");
379       return false;
380     }
381 
382     nWidth  = pSetup->nWidth;
383     nHeight = pSetup->nHeight;
384 
385     ZeroMemory(&d3dpp,sizeof(d3dpp));
386 
387     d3dpp.SwapEffect     = D3DSWAPEFFECT_DISCARD;
388     d3dpp.hDeviceWindow  = hWnd;
389     d3dpp.Windowed       = pSetup->windowMode != RENDERER_WINDOWMODE_FULLSCREEN;
390     d3dpp.PresentationInterval = pSetup->bVsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
391 
392     d3dpp.BackBufferCount  = 1;
393 
394     d3dpp.BackBufferWidth  = pSetup->nWidth;
395     d3dpp.BackBufferHeight = pSetup->nHeight;
396 
397     D3DDISPLAYMODE d3ddm;
398     if( FAILED( pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) )
399     {
400       printf("[Renderer] GetAdapterDisplayMode failed\n");
401       return false;
402     }
403 
404     static D3DFORMAT pBackbufferFormats32[] = {
405       D3DFMT_X8R8G8B8,
406       D3DFMT_A8R8G8B8,
407       D3DFMT_UNKNOWN
408     };
409     D3DFORMAT * pFormats = pBackbufferFormats32;
410     for (int i=0; pFormats[i] != D3DFMT_UNKNOWN; i++)
411       if ( SUCCEEDED(pD3D->CheckDeviceType( D3DADAPTER_DEFAULT, DEVTYPE, d3ddm.Format, pFormats[i], d3dpp.Windowed )) )
412         d3dpp.BackBufferFormat = pFormats[i];
413 
414     if (d3dpp.BackBufferFormat == D3DFMT_UNKNOWN)
415     {
416       printf("[Renderer] No suitable backbuffer format found\n");
417       return false;
418     }
419 
420     d3dpp.EnableAutoDepthStencil = FALSE;
421 
422     static D3DMULTISAMPLE_TYPE pMultisampleTypes[]=
423     {
424       D3DMULTISAMPLE_2_SAMPLES,
425       D3DMULTISAMPLE_4_SAMPLES,
426       D3DMULTISAMPLE_6_SAMPLES,
427       D3DMULTISAMPLE_8_SAMPLES,
428       D3DMULTISAMPLE_NONE
429     };
430 
431     d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
432 
433     HRESULT h;
434     h = pD3D->CreateDevice( D3DADAPTER_DEFAULT, DEVTYPE, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
435     if (h != D3D_OK)
436     {
437       h = pD3D->CreateDevice( D3DADAPTER_DEFAULT, DEVTYPE, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
438       if(h != D3D_OK)
439       {
440         printf("[Renderer] CreateDevice failed: %08X\n",h);
441         return false;
442       }
443     }
444 
445     pDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
446 
447     for (int x=0; x<4; x++)
448     {
449       pDevice->SetSamplerState( x, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
450       pDevice->SetSamplerState( x, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
451       pDevice->SetSamplerState( x, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
452     }
453 
454     pDevice->GetRenderTarget( 0, &pBackBuffer );
455 
456     return 1;
457   }
458 
459   LPDIRECT3DVERTEXBUFFER9 pFullscreenQuadVB = NULL;
460   LPDIRECT3DVERTEXBUFFER9 pGUIQuadVB = NULL;
461   LPDIRECT3DVERTEXDECLARATION9 pFullscreenQuadVertexDecl = NULL;
462 
463 #define GUIQUADVB_SIZE (128*6)
464 
Open(RENDERER_SETTINGS * settings)465   bool Open( RENDERER_SETTINGS * settings )
466   {
467     if (!InitWindow(settings))
468     {
469       printf("[Renderer] InitWindow failed\n");
470       return false;
471     }
472 
473     if (!InitDirect3D(settings))
474     {
475       printf("[Renderer] InitDirect3D failed\n");
476       return false;
477     }
478 
479     static D3DVERTEXELEMENT9 pFullscreenQuadElements[] =
480     {
481       { 0, 0*sizeof(float), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
482       { 0, 3*sizeof(float), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
483       D3DDECL_END()
484     };
485 
486     static float pQuad[] =
487     {
488       -1.0, -1.0,  0.0, 0.0 + 0.5 / (float)nWidth, 0.0 + 0.5 / (float)nHeight,
489       -1.0,  1.0,  0.0, 0.0 + 0.5 / (float)nWidth, 1.0 + 0.5 / (float)nHeight,
490        1.0, -1.0,  0.0, 1.0 + 0.5 / (float)nWidth, 0.0 + 0.5 / (float)nHeight,
491        1.0,  1.0,  0.0, 1.0 + 0.5 / (float)nWidth, 1.0 + 0.5 / (float)nHeight,
492     };
493 
494     pDevice->CreateVertexBuffer( 4 * 5 * sizeof(float), D3DUSAGE_WRITEONLY, D3DFVF_XYZ | D3DFVF_TEX1, D3DPOOL_DEFAULT, &pFullscreenQuadVB, NULL);
495     void * v;
496     pFullscreenQuadVB->Lock( 0, 4 * 5 * sizeof(float), &v, NULL );
497     CopyMemory( v, pQuad, 4 * 5 * sizeof(float) );
498     pFullscreenQuadVB->Unlock();
499 
500     pDevice->CreateVertexDeclaration( pFullscreenQuadElements, &pFullscreenQuadVertexDecl );
501 
502     //////////////////////////////////////////////////////////////////////////
503 
504     pDevice->CreateVertexBuffer( GUIQUADVB_SIZE * 6 * sizeof(float), D3DUSAGE_WRITEONLY, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1, D3DPOOL_DEFAULT, &pGUIQuadVB, NULL);
505 
506     //////////////////////////////////////////////////////////////////////////
507 
508     LPD3DXBUFFER pShader = NULL;
509     LPD3DXBUFFER pErrors = NULL;
510 
511     if (D3DXCompileShader( defaultVertexShader, strlen(defaultVertexShader), NULL, NULL, "main", "vs_3_0", NULL, &pShader, &pErrors, NULL ) != D3D_OK)
512     {
513       printf("[Renderer] D3DXCompileShader failed\n");
514       return false;
515     }
516 
517     if (pDevice->CreateVertexShader( (DWORD*)pShader->GetBufferPointer(), &pVertexShader ) != D3D_OK)
518     {
519       printf("[Renderer] CreateVertexShader failed\n");
520       return false;
521     }
522 
523     if (pDevice->CreateOffscreenPlainSurface( settings->nWidth, settings->nHeight, d3dpp.BackBufferFormat, D3DPOOL_SYSTEMMEM, &pFrameGrabTexture, NULL) != D3D_OK)
524     {
525       printf("[Renderer] CreateOffscreenPlainSurface failed\n");
526       return false;
527     }
528 
529     return true;
530   }
531 
532   unsigned int nCacheFlushCount = 0;
StartFrame()533   void StartFrame()
534   {
535     nCacheFlushCount = 0;
536     MSG msg;
537     if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
538     {
539       TranslateMessage( &msg );
540       DispatchMessage( &msg );
541     }
542 
543     pDevice->Clear( 0, NULL, D3DCLEAR_TARGET, 0xFF808080, 1.0f, 0 );
544     pDevice->BeginScene();
545   }
EndFrame()546   void EndFrame()
547   {
548     pDevice->EndScene();
549     pDevice->Present( NULL, NULL, NULL, NULL );
550   }
WantsToQuit()551   bool WantsToQuit()
552   {
553     return !run;
554   }
Close()555   void Close()
556   {
557     if (pFullscreenQuadVB) pFullscreenQuadVB->Release();
558     if (pFullscreenQuadVertexDecl) pFullscreenQuadVertexDecl->Release();
559     if (pGUIQuadVB) pGUIQuadVB->Release();
560     if (pVertexShader) pVertexShader->Release();
561     if (theShader) theShader->Release();
562     if (pDevice) pDevice->Release();
563     if (pD3D) pD3D->Release();
564     if (hWnd)
565     {
566       DestroyWindow(hWnd);
567       UnregisterClass(_T("fwzwnd"),GetModuleHandle(NULL));
568     }
569   }
570 
RenderFullscreenQuad()571   void RenderFullscreenQuad()
572   {
573     pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, false );
574 
575     pDevice->SetVertexShader( pVertexShader );
576     pDevice->SetPixelShader( theShader );
577 
578     pDevice->SetVertexDeclaration( pFullscreenQuadVertexDecl );
579     pDevice->SetStreamSource( 0, pFullscreenQuadVB, 0, sizeof(float) * 5 );
580     pDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
581   }
582 
ReloadShader(const char * szShaderCode,int nShaderCodeSize,char * szErrorBuffer,int nErrorBufferSize)583   bool ReloadShader( const char * szShaderCode, int nShaderCodeSize, char * szErrorBuffer, int nErrorBufferSize )
584   {
585     LPD3DXBUFFER pShader = NULL;
586     LPD3DXBUFFER pErrors = NULL;
587 
588     if (D3DXCompileShader( szShaderCode, nShaderCodeSize, NULL, NULL, "main", "ps_3_0", NULL, &pShader, &pErrors, &pConstantTable ) != D3D_OK)
589     {
590       memset( szErrorBuffer, 0, nErrorBufferSize );
591       strncpy( szErrorBuffer, (const char*)pErrors->GetBufferPointer(), nErrorBufferSize - 1 );
592       return false;
593     }
594 
595     if (theShader)
596     {
597       theShader->Release();
598       theShader = NULL;
599     }
600 
601     if (pDevice->CreatePixelShader( (DWORD*)pShader->GetBufferPointer(), &theShader ) != D3D_OK)
602     {
603       return false;
604     }
605 
606     return true;
607   }
608 
SetShaderConstant(const char * szConstName,float x)609   void SetShaderConstant( const char * szConstName, float x )
610   {
611     pConstantTable->SetFloat( pDevice, szConstName, x );
612   }
613 
614   static D3DXVECTOR4 SetShaderConstant_VEC4;
SetShaderConstant(const char * szConstName,float x,float y)615   void SetShaderConstant( const char * szConstName, float x, float y )
616   {
617     SetShaderConstant_VEC4.x = x;
618     SetShaderConstant_VEC4.y = y;
619     SetShaderConstant_VEC4.z = 0;
620     SetShaderConstant_VEC4.w = 0;
621     pConstantTable->SetVector( pDevice, szConstName, &SetShaderConstant_VEC4 );
622   }
623 
624   struct DX9Texture : public Texture
625   {
626     LPDIRECT3DTEXTURE9 pTexture;
627   };
628 
629   int textureUnit = 0;
630 
CreateRGBA8Texture()631   Renderer::Texture * CreateRGBA8Texture()
632   {
633     LPDIRECT3DTEXTURE9 pTex = NULL;
634     pDevice->CreateTexture( nWidth, nHeight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTex, NULL );
635 
636     if ( !pTex )
637       return NULL;
638 
639     DX9Texture * tex = new DX9Texture();
640     tex->pTexture = pTex;
641     tex->width = nWidth;
642     tex->height = nHeight;
643     tex->type = TEXTURETYPE_2D;
644     return tex;
645 
646   }
647 
CreateRGBA8TextureFromFile(const char * szFilename)648   Texture * CreateRGBA8TextureFromFile( const char * szFilename )
649   {
650     LPDIRECT3DTEXTURE9 pTex = NULL;
651     D3DXIMAGE_INFO info;
652     HRESULT h = D3DXCreateTextureFromFileExA(
653       pDevice,
654       szFilename,
655       D3DX_DEFAULT_NONPOW2,
656       D3DX_DEFAULT_NONPOW2,
657       0,
658       NULL,
659       D3DFMT_FROM_FILE,
660       D3DPOOL_DEFAULT,
661       D3DX_DEFAULT,
662       D3DX_DEFAULT,
663       NULL,
664       &info,
665       NULL,
666       &pTex);
667 
668     if (!pTex)
669       return NULL;
670 
671     DX9Texture * tex = new DX9Texture();
672     tex->pTexture = pTex;
673     tex->width = info.Width;
674     tex->height = info.Height;
675     tex->type = TEXTURETYPE_2D;
676     return tex;
677   }
678 
Create1DR32Texture(int w)679   Texture * Create1DR32Texture( int w )
680   {
681     LPDIRECT3DTEXTURE9 pTex = NULL;
682     pDevice->CreateTexture( w, 1, 0, D3DUSAGE_DYNAMIC, D3DFMT_R32F, D3DPOOL_DEFAULT, &pTex, NULL );
683 
684     if (!pTex)
685       return NULL;
686 
687     D3DLOCKED_RECT rect;
688     pTex->LockRect( 0, &rect, NULL, NULL );
689     memset( rect.pBits, 0, w * sizeof(float) );
690     pTex->UnlockRect(0);
691 
692     DX9Texture * tex = new DX9Texture();
693     tex->pTexture = pTex;
694     tex->width = w;
695     tex->height = 1;
696     tex->type = TEXTURETYPE_1D;
697     return tex;
698   }
699 
SetShaderTexture(const char * szTextureName,Texture * tex)700   void SetShaderTexture( const char * szTextureName, Texture * tex )
701   {
702     int idx = pConstantTable->GetSamplerIndex( szTextureName );
703     if (idx >= 0)
704     {
705       pDevice->SetSamplerState( idx, D3DSAMP_SRGBTEXTURE, TRUE );
706       pDevice->SetSamplerState( idx, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP );
707       pDevice->SetSamplerState( idx, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP );
708       pDevice->SetTexture( idx, ((DX9Texture *)tex)->pTexture );
709     }
710   }
711 
UpdateR32Texture(Texture * tex,float * data)712   bool UpdateR32Texture( Texture * tex, float * data )
713   {
714     LPDIRECT3DTEXTURE9 pTex = ((DX9Texture *)tex)->pTexture;
715 
716     D3DLOCKED_RECT rect;
717     pTex->LockRect( 0, &rect, NULL, D3DLOCK_DISCARD );
718     memcpy( rect.pBits, data, tex->width * sizeof(float) );
719     pTex->UnlockRect(0);
720 
721     return true;
722   }
723 
CreateA8TextureFromData(int w,int h,const unsigned char * data)724   Texture * CreateA8TextureFromData( int w, int h, const unsigned char * data )
725   {
726     LPDIRECT3DTEXTURE9 pTex = NULL;
727     pDevice->CreateTexture( w, h, 0, NULL, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTex, NULL );
728 
729     if (!pTex)
730       return NULL;
731 
732     D3DLOCKED_RECT rect;
733     pTex->LockRect( 0, &rect, NULL, NULL );
734     const unsigned char * src = data;
735     unsigned char * dst = (unsigned char *)rect.pBits;
736     for (int i=0; i<h; i++)
737     {
738       const unsigned char * srcLine = src;
739       unsigned int * dstLine = (unsigned int *)dst;
740       for (int j=0; j<w; j++)
741       {
742         *dstLine = (*srcLine << 24) | 0xFFFFFF;
743         srcLine++;
744         dstLine++;
745       }
746       src += w * sizeof(unsigned char);
747       dst += rect.Pitch;
748     }
749     pTex->UnlockRect(0);
750 
751     DX9Texture * tex = new DX9Texture();
752     tex->pTexture = pTex;
753     tex->width = w;
754     tex->height = h;
755     tex->type = TEXTURETYPE_1D;
756     return tex;
757   }
758 
ReleaseTexture(Texture * tex)759   void ReleaseTexture( Texture * tex )
760   {
761     ( (DX9Texture *) tex )->pTexture->Release();
762     delete tex;
763   }
764 
CopyBackbufferToTexture(Texture * tex)765   void CopyBackbufferToTexture( Texture * tex )
766   {
767     LPDIRECT3DTEXTURE9 pTex = ( (DX9Texture *) tex )->pTexture;
768     LPDIRECT3DSURFACE9 pSurf = NULL;
769     pTex->GetSurfaceLevel( 0, &pSurf );
770     if ( pSurf )
771     {
772       HRESULT res = pDevice->StretchRect( pBackBuffer, NULL, pSurf, NULL, D3DTEXF_LINEAR );
773       pSurf->Release();
774     }
775   }
776 
777   //////////////////////////////////////////////////////////////////////////
778   // text rendering
779 
StartTextRendering()780   void StartTextRendering()
781   {
782     pDevice->SetVertexShader( NULL );
783     pDevice->SetPixelShader( NULL );
784     pDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, TRUE );
785     //pDevice->SetVertexDeclaration( pGUIVertexDecl );
786     pDevice->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
787     pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
788     pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
789     pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
790 
791     D3DXMATRIX mat;
792     D3DXMatrixIdentity( &mat );
793     pDevice->SetTransform( D3DTS_VIEW, &mat );
794     pDevice->SetTransform( D3DTS_WORLD, &mat );
795     D3DXMatrixOrthoOffCenterLH( (D3DXMATRIX*)&mat, 0, nWidth, nHeight, 0, -1.0f, 1.0f );
796     pDevice->SetTransform( D3DTS_PROJECTION, &mat );
797 
798     pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
799     pDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE );
800     pDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE );
801     pDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
802     pDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
803     pDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE );
804   }
805 
806   int bufferPointer = 0;
807   unsigned char buffer[GUIQUADVB_SIZE * sizeof(float) * 6];
808   bool lastModeIsQuad = true;
__FlushRenderCache()809   void __FlushRenderCache()
810   {
811     if (!bufferPointer) return;
812 
813     nCacheFlushCount++;
814     void * v = NULL;
815     pGUIQuadVB->Lock( 0, bufferPointer * sizeof(float) * 6, &v, NULL );
816     CopyMemory( v, buffer, bufferPointer * sizeof(float) * 6 );
817     pGUIQuadVB->Unlock();
818 
819     pDevice->SetStreamSource( 0, pGUIQuadVB, 0, sizeof(float) * 6 );
820     if (lastModeIsQuad)
821       pDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, bufferPointer / 3 );
822     else
823       pDevice->DrawPrimitive( D3DPT_LINELIST, 0, bufferPointer / 2 );
824 
825     bufferPointer = 0;
826   }
_dxARGBtoABGR(unsigned int abgr)827   inline unsigned int _dxARGBtoABGR(unsigned int abgr)
828   {
829     return (abgr&0xff00ff00)+((abgr<<16)&0x00ff0000)+((abgr>>16)&0x000000ff);
830   }
831   Texture * lastTexture = NULL;
__WriteVertexToBuffer(const Vertex & v)832   void __WriteVertexToBuffer( const Vertex & v )
833   {
834     if (bufferPointer >= GUIQUADVB_SIZE)
835     {
836       __FlushRenderCache();
837     }
838 
839     float * f = (float*)(buffer + bufferPointer * sizeof(float) * 6);
840     *(f++) = v.x;
841     *(f++) = v.y;
842     *(f++) = 0.0;
843     *(unsigned int *)(f++) = _dxARGBtoABGR( v.c );
844     *(f++) = v.u + (lastTexture ? (0.5 / (float)lastTexture->width ) : 0.0);
845     *(f++) = v.v + (lastTexture ? (0.5 / (float)lastTexture->height) : 0.0);
846     bufferPointer++;
847   }
BindTexture(Texture * tex)848   void BindTexture( Texture * tex )
849   {
850     if (lastTexture != tex)
851     {
852       __FlushRenderCache();
853       lastTexture = tex;
854       pDevice->SetTexture( 0, tex ? ((DX9Texture *)tex)->pTexture : NULL );
855     }
856   }
857 
RenderQuad(const Vertex & a,const Vertex & b,const Vertex & c,const Vertex & d)858   void RenderQuad( const Vertex & a, const Vertex & b, const Vertex & c, const Vertex & d )
859   {
860     if (!lastModeIsQuad)
861     {
862       __FlushRenderCache();
863       lastModeIsQuad = true;
864     }
865     __WriteVertexToBuffer(a);
866     __WriteVertexToBuffer(b);
867     __WriteVertexToBuffer(d);
868     __WriteVertexToBuffer(b);
869     __WriteVertexToBuffer(c);
870     __WriteVertexToBuffer(d);
871   }
872 
RenderLine(const Vertex & a,const Vertex & b)873   void RenderLine( const Vertex & a, const Vertex & b )
874   {
875     if (lastModeIsQuad)
876     {
877       __FlushRenderCache();
878       lastModeIsQuad = false;
879     }
880     __WriteVertexToBuffer(a);
881     __WriteVertexToBuffer(b);
882   }
883 
SetTextRenderingViewport(Scintilla::PRectangle rect)884   void SetTextRenderingViewport( Scintilla::PRectangle rect )
885   {
886     __FlushRenderCache();
887     D3DXMATRIX mat;
888     D3DXMatrixIdentity( &mat );
889     mat._41 = rect.left;
890     mat._42 = rect.top;
891     pDevice->SetTransform( D3DTS_WORLD, &mat );
892 
893     RECT rc = { rect.left, rect.top, rect.right, rect.bottom };
894     pDevice->SetScissorRect( &rc );
895   }
EndTextRendering()896   void EndTextRendering()
897   {
898     __FlushRenderCache();
899     pDevice->SetRenderState( D3DRS_SCISSORTESTENABLE, false );
900     pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, false );
901   }
902 
903   //////////////////////////////////////////////////////////////////////////
904 
GrabFrame(void * pPixelBuffer)905   bool GrabFrame( void * pPixelBuffer )
906   {
907     if (!pFrameGrabTexture)
908       return false;
909 
910     if (pDevice->GetRenderTargetData( pBackBuffer, pFrameGrabTexture ) != D3D_OK)
911       return false;
912 
913     D3DLOCKED_RECT rect;
914     if (pFrameGrabTexture->LockRect( &rect, NULL, NULL ) != D3D_OK)
915       return false;
916 
917     unsigned char* pSrc = (unsigned char*)rect.pBits;
918     unsigned char* pDst = (unsigned char*)pPixelBuffer;
919     for( int i = 0; i < nHeight; i++ )
920     {
921       unsigned int* pSrc32 = (unsigned int*)pSrc;
922       unsigned int* pDst32 = (unsigned int*)pDst;
923       for(int j=0; j < nWidth; j++)
924         pDst32[j] = (pSrc32[j] & 0x00FF00) | ((pSrc32[j] >> 16) & 0xFF) | ((pSrc32[j] & 0xFF) << 16) | 0xFF000000;
925 
926       pSrc += rect.Pitch;
927       pDst += nWidth * 4;
928     }
929 
930     pFrameGrabTexture->UnlockRect();
931 
932     return true;
933   }
934 }
935