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