deps: Took out DirectX headers
[sdk] / ecere / src / gfx / drivers / Direct3D9DisplayDriver.ec
1 namespace gfx::drivers;
2
3 import "instance"
4
5 #if defined(__WIN32__)
6
7 #ifndef D3DPRESENT_DONOTWAIT
8 #define D3DPRESENT_DONOTWAIT 0x00000001L
9 #endif
10
11 #define D3D_DEBUG_INFO  1
12
13 #define Method _Method
14 #define uint _uint
15 #define byte _byte
16 #define int64 _int64
17 #define String _String
18 #define Mutex _Mutex
19 #define Size _Size
20 #define Platform _Platform
21
22 #include <windows.h>
23
24 #if defined(__MINGW32__) && !defined(_W64)
25 #undef DECLARE_INTERFACE
26 #define DECLARE_INTERFACE(i) \
27    interface i { CONST_VTABLE struct i##Vtbl *lpVtbl; }; \
28    typedef CONST_VTABLE struct i##Vtbl i##Vtbl; \
29    CONST_VTABLE struct i##Vtbl
30 #endif
31
32 #include <d3d9.h>
33
34 #undef Method
35 #undef uint
36 #undef byte
37 #undef int64
38 #undef String
39 #undef Mutex
40 #undef Size
41 #undef Platform
42
43 import "Display"
44
45 #define MATRIX_STACK_SIZE  32
46
47 #define NUM_VERTEX_DECLS 4
48
49 static class D3DDisplay : struct
50 {
51    Box updateBox;
52    IDirect3DSwapChain9 * swapChain;
53    Matrix worldMatrixStack[MATRIX_STACK_SIZE];
54    Matrix * worldMatrix;
55    D3DMATRIX projMatrix;
56    D3DLIGHT9 lights[NumberOfLights], lightsPI[NumberOfLights];
57    D3DPRESENT_PARAMETERS d3dpp;
58    IDirect3DSurface9 * backBuffer, * depthSurface;
59    bool vSync;
60 };
61
62 static class D3DSystem : struct
63 {
64    HMODULE d3dDll;
65    IDirect3D9 * direct3D;
66    IDirect3DDevice9 * d3dDevice;
67    IDirect3D9 * (WINAPI * direct3DCreate9)(UINT);
68    uint usage;
69    D3DPRESENT_PARAMETERS d3dpp;
70
71    IDirect3DVertexDeclaration9 * decls[NUM_VERTEX_DECLS], * decl2D;
72    bool ready;
73    HWND hwnd;
74    int format;
75    bool inScene;
76 };
77
78 static class D3DSurface : struct
79 {
80    // For compatibility with LFB driver
81    Font font;
82    bool opaqueText;
83    int xOffset;
84    bool writingText;
85
86    ColorAlpha background;
87 };
88
89 static class D3DMesh : struct
90 {
91    IDirect3DVertexBuffer9 * vertices;
92    IDirect3DVertexBuffer9 * normals;
93    IDirect3DVertexBuffer9 * texCoords;
94    IDirect3DVertexBuffer9 * texCoords2;
95 };
96
97 static struct Vertex
98 {
99    float x,y,z;
100    ColorAlpha color;
101    float u,v;
102 };
103
104 static class D3DIndices : struct
105 {
106    uint16 * indices;
107    IDirect3DIndexBuffer9 * buffer;
108    int nIndices;
109 };
110
111 static int primitiveTypes[RenderPrimitiveType] =
112 {
113    D3DPT_POINTLIST, D3DPT_LINELIST, D3DPT_TRIANGLELIST, D3DPT_TRIANGLESTRIP, D3DPT_TRIANGLEFAN, D3DPT_TRIANGLEFAN, 0, D3DPT_LINESTRIP
114 };
115
116 static void SetTransformMatrix(IDirect3DDevice9 * device, Matrix matrix)
117 {
118    D3DMATRIX d3dMat =
119    {
120       {
121          {
122             (float)matrix.m[0][0], (float)matrix.m[0][1], (float)matrix.m[0][2], (float)matrix.m[0][3],
123             (float)matrix.m[1][0], (float)matrix.m[1][1], (float)matrix.m[1][2], (float)matrix.m[1][3],
124             (float)matrix.m[2][0], (float)matrix.m[2][1], (float)matrix.m[2][2], (float)matrix.m[2][3],
125             (float)matrix.m[3][0], (float)matrix.m[3][1], (float)matrix.m[3][2], (float)matrix.m[3][3]
126          }
127       }
128    };
129    IDirect3DDevice9_SetTransform(device, D3DTS_WORLD, &d3dMat);
130 }
131
132 class Direct3D9DisplayDriver : DisplayDriver
133 {
134    class_property(name) = "Direct3D";
135
136    // Utility Functions
137    bool ::LockDisplay(Display display, Surface surface, Bitmap lfbBitmap, Surface * lfbSurface)
138    {
139       bool result = false;
140       D3DDisplay d3dDisplay = display.driverData;
141
142       //if(!IDirect3DDevice9_GetBackBuffer(d3dSystem.d3dDevice, 0, 0, D3DBACKBUFFER_TYPE_MONO, &d3dDisplay.backBuffer))
143       {
144          D3DLOCKED_RECT lockedRect;
145          if(!IDirect3DSurface9_LockRect(d3dDisplay.backBuffer, &lockedRect, null, 0))
146          {
147             result = true;
148             switch(d3dDisplay.d3dpp.BackBufferFormat)
149             {
150                case D3DFMT_A8R8G8B8:
151                case D3DFMT_X8R8G8B8:
152                   lfbBitmap.pixelFormat = pixelFormat888;
153                   break;
154                case D3DFMT_R5G6B5:
155                   lfbBitmap.pixelFormat = pixelFormat565;
156                   break;
157                case D3DFMT_X1R5G5B5:
158                case D3DFMT_A1R5G5B5:
159                   lfbBitmap.pixelFormat = pixelFormat555;
160                   break;
161                case D3DFMT_A4R4G4B4:
162                case D3DFMT_X4R4G4B4:
163                   lfbBitmap.pixelFormat = pixelFormat444;
164                   break;
165                default:
166                   result = false;
167             }
168             if(result)
169             {
170                lfbBitmap.driver = null;
171                lfbBitmap.displaySystem = null;
172                lfbBitmap.picture = (byte *)lockedRect.pBits;
173                lfbBitmap.transparent = false;
174                lfbBitmap.stride = lockedRect.Pitch >> GetColorDepthShifts(lfbBitmap.pixelFormat);
175                lfbBitmap.width = display.width;
176                lfbBitmap.height = display.height;
177
178                *lfbSurface = lfbBitmap.GetSurface(surface ? surface.offset.x : 0, surface ? surface.offset.y : 0, surface ? surface.box : null);
179             }
180          }
181          if(!result)
182             IDirect3DSurface9_Release(d3dDisplay.backBuffer);
183       }
184       return result;
185    }
186
187    void ::UnlockDisplay(Display display, Surface surface)
188    {
189       D3DDisplay d3dDisplay = display.driverData;
190       if(d3dDisplay.backBuffer)
191       {
192          IDirect3DSurface9_UnlockRect(d3dDisplay.backBuffer);
193          IDirect3DSurface9_Release(d3dDisplay.backBuffer);
194       }
195       delete surface;
196    }
197
198    void ::SetViewportAndMatrices(Display display, int x, int y, Box box)
199    {
200       D3DDisplay d3dDisplay = display.driverData;
201       DisplaySystem displaySystem = display.displaySystem;
202       D3DSystem d3dSystem = displaySystem.driverData;
203       if(d3dSystem.ready)
204       {
205          D3DVIEWPORT9 viewport;
206          viewport.MinZ = 0;
207          viewport.MaxZ = 1;
208          if(box.right < box.left || box.bottom < box.top)
209          {
210             viewport.Width = viewport.Height = 1;
211             viewport.X = viewport.Y = MAXDWORD;
212          }
213          else
214          {
215             viewport.X = x + box.left;
216             viewport.Y = y + box.top;
217             viewport.Width = box.right - box.left + 1;
218             viewport.Height = box.bottom - box.top + 1;
219          }
220          if(!IDirect3DDevice9_SetViewport(d3dSystem.d3dDevice, &viewport))
221          {
222             D3DMATRIX * matProj = &d3dDisplay.projMatrix;
223             Matrix * matWorld = d3dDisplay.worldMatrix = d3dDisplay.worldMatrixStack;
224
225             matProj->m[0][0] = 2.0f / viewport.Width;
226             matProj->m[1][1] =-2.0f / viewport.Height;
227             matProj->m[2][2] = matProj->m[3][1] = matProj->m[3][3] = 1;
228             matProj->m[3][0] = -1;
229
230             IDirect3DDevice9_SetTransform(d3dSystem.d3dDevice, D3DTS_PROJECTION, matProj);
231
232             matWorld->Identity();
233             matWorld->m[3][0] =-box.left;
234             matWorld->m[3][1] =-box.top;
235
236             SetTransformMatrix(d3dSystem.d3dDevice, matWorld);
237          }
238       }
239    }
240
241    // Implementation
242    bool CreateDisplaySystem(DisplaySystem displaySystem)
243    {
244       bool result = false;
245       D3DSystem d3dSystem = displaySystem.driverData = D3DSystem { };
246       if(d3dSystem)
247       {
248          displaySystem.flags.alpha = true;
249          //if(displaySystem.flags.fullScreen)
250             displaySystem.flags.flipping = true;
251          displaySystem.pixelFormat = pixelFormat888;
252
253          d3dSystem.d3dDll = LoadLibrary("d3d9.dll");
254          if(d3dSystem.d3dDll)
255          {
256             d3dSystem.direct3DCreate9 = (void *)GetProcAddress(d3dSystem.d3dDll, "Direct3DCreate9");
257             if(d3dSystem.direct3DCreate9)
258             {
259                if((d3dSystem.direct3D = d3dSystem.direct3DCreate9(D3D_SDK_VERSION)))
260                {
261                   D3DDISPLAYMODE d3ddm;
262                   if(!IDirect3D9_GetAdapterDisplayMode(d3dSystem.direct3D, D3DADAPTER_DEFAULT, &d3ddm))
263                   {
264                      d3dSystem.d3dpp.BackBufferCount = 1;
265
266                      if(displaySystem.flags.fullScreen)
267                      {
268                         d3dSystem.d3dpp.BackBufferWidth = d3ddm.Width;
269                         d3dSystem.d3dpp.BackBufferHeight = d3ddm.Height;
270                         d3dSystem.d3dpp.hDeviceWindow = displaySystem.window;
271                      }
272                      else
273                      {
274                         d3dSystem.d3dpp.hDeviceWindow = d3dSystem.hwnd =
275                            CreateWindow("static", null, 0,0,0,0,0,null,null,null,null);
276                         d3dSystem.d3dpp.Windowed = TRUE;
277                      }
278
279                      d3dSystem.d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
280                      d3dSystem.format = d3dSystem.d3dpp.BackBufferFormat = d3ddm.Format;
281                      d3dSystem.d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
282
283                      if(!IDirect3D9_CreateDevice(d3dSystem.direct3D, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
284                         d3dSystem.d3dpp.hDeviceWindow,
285                                D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_PUREDEVICE|D3DCREATE_FPU_PRESERVE,
286                                &d3dSystem.d3dpp, &d3dSystem.d3dDevice))
287                         result = true;
288                      else
289                      {
290                         d3dSystem.usage = D3DUSAGE_SOFTWAREPROCESSING;
291                         if(!IDirect3D9_CreateDevice(d3dSystem.direct3D, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
292                               d3dSystem.d3dpp.hDeviceWindow,
293                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING|D3DCREATE_FPU_PRESERVE,
294                                   &d3dSystem.d3dpp, &d3dSystem.d3dDevice))
295                            result = true;
296                      }
297
298                      if(result)
299                      {
300                         D3DVERTEXELEMENT9 vertexDecls[NUM_VERTEX_DECLS][4] =
301                         {
302                            {
303                               { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
304                               D3DDECL_END( )
305                            },
306                            {
307                               { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
308                               { 1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0 },
309                               D3DDECL_END( )
310                            },
311                            {
312                               { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
313                               { 2, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0 },
314                               D3DDECL_END( )
315                            },
316                            {
317                               { 0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
318                               { 1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0 },
319                               { 2, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0 },
320                               D3DDECL_END( )
321                            }
322                         };
323
324                         D3DVERTEXELEMENT9 vertexDecl2D[] =
325                         {
326                            { 0, 0, D3DDECLTYPE_FLOAT3,   0, D3DDECLUSAGE_POSITION, 0 },
327                            { 0, (uint16)(3*sizeof(float)), D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0 },
328                            { 0, (uint16)(3*sizeof(float) + sizeof(uint)), D3DDECLTYPE_FLOAT2,   0, D3DDECLUSAGE_TEXCOORD, 0 },
329                            D3DDECL_END( )
330                         };
331
332                         int c;
333                         for(c = 0; c<NUM_VERTEX_DECLS; c++)
334                            if(IDirect3DDevice9_CreateVertexDeclaration(d3dSystem.d3dDevice, vertexDecls[c], &d3dSystem.decls[c]))
335                               break;
336
337                         if(c < NUM_VERTEX_DECLS ||
338                            IDirect3DDevice9_CreateVertexDeclaration(d3dSystem.d3dDevice, vertexDecl2D, &d3dSystem.decl2D))
339                            result = false;
340                      }
341                      if(result)
342                         d3dSystem.ready = false;
343                   }
344                }
345             }
346          }
347          else
348             Log("Couldn't load library d3d9.dll\n");
349             //LogErrorCode(ERR_MISSING_LIBRARY, "d3d9.dll");
350       }
351       return result;
352    }
353
354    void DestroyDisplaySystem(DisplaySystem displaySystem)
355    {
356       D3DSystem d3dSystem = displaySystem.driverData;
357       int c;
358
359       if(d3dSystem.d3dDevice)
360          IDirect3DDevice9_Release(d3dSystem.d3dDevice);
361
362       if(d3dSystem.direct3D)
363          IDirect3D9_Release(d3dSystem.direct3D);
364
365       for(c = 0; c<NUM_VERTEX_DECLS; c++)
366       {
367          if(d3dSystem.decls[c])
368             IDirect3DVertexDeclaration9_Release(d3dSystem.decls[c]);
369       }
370
371       if(d3dSystem.decl2D)
372          IDirect3DVertexDeclaration9_Release(d3dSystem.decl2D);
373
374       FreeLibrary(d3dSystem.d3dDll);
375
376       delete d3dSystem;
377       displaySystem.driverData = null;
378
379    }
380
381    void DestroyDisplay(Display display)
382    {
383       DisplaySystem displaySystem = display.displaySystem;
384       D3DSystem d3dSystem = displaySystem.driverData;
385       D3DDisplay d3dDisplay = display.driverData;
386
387       if(d3dSystem.inScene)
388       {
389          IDirect3DDevice9_EndScene(d3dSystem.d3dDevice);
390          d3dSystem.inScene = false;
391       }
392
393       if(d3dDisplay.backBuffer)
394          IDirect3DSurface9_Release(d3dDisplay.backBuffer);
395
396       if(d3dDisplay.depthSurface)
397          IDirect3DSurface9_Release(d3dDisplay.depthSurface);
398
399       if(d3dDisplay.swapChain)
400          IDirect3DSwapChain9_Release(d3dDisplay.swapChain);
401
402       delete d3dDisplay;
403       display.driverData = null;
404    }
405
406    bool CreateDisplay(Display display)
407    {
408       bool result = false;
409       DisplaySystem displaySystem = display.displaySystem;
410       D3DSystem d3dSystem = displaySystem.driverData;
411       display.driverData = D3DDisplay { };
412
413       d3dSystem.ready = false;
414
415       result = true;
416
417       return result;
418    }
419
420    bool DisplaySize(Display display, int width, int height)
421    {
422       bool result = false;
423       DisplaySystem displaySystem = display.displaySystem;
424       D3DSystem d3dSystem = displaySystem.driverData;
425       D3DDisplay d3dDisplay = display.driverData;
426       IDirect3DDevice9 * d3dDevice = d3dSystem.d3dDevice;
427
428       d3dSystem.ready = false;
429
430       if(d3dDisplay.backBuffer)
431       {
432          IDirect3DSurface9_Release(d3dDisplay.backBuffer);
433          d3dDisplay.backBuffer = null;
434       }
435
436       if(d3dDisplay.depthSurface)
437       {
438          IDirect3DSurface9_Release(d3dDisplay.depthSurface);
439          d3dDisplay.depthSurface = null;
440       }
441
442       if(d3dDisplay.swapChain)
443       {
444          IDirect3DSwapChain9_Release(d3dDisplay.swapChain);
445          d3dDisplay.swapChain = null;
446       }
447
448       if(width && height)
449       {
450
451          if(displaySystem.flags.fullScreen)
452          {
453             d3dSystem.d3dpp.BackBufferWidth = width;
454             d3dSystem.d3dpp.BackBufferHeight = height;
455
456             result = !IDirect3DDevice9_Reset(d3dSystem.d3dDevice, &d3dSystem.d3dpp);
457
458             result = !IDirect3DDevice9_GetSwapChain(d3dSystem.d3dDevice, 0, &d3dDisplay.swapChain);
459          }
460          else
461          {
462             d3dDisplay.d3dpp.MultiSampleType = D3DMULTISAMPLE_4_SAMPLES;
463             d3dDisplay.d3dpp.BackBufferWidth = width;
464             d3dDisplay.d3dpp.BackBufferHeight = height;
465             d3dDisplay.d3dpp.Windowed = TRUE;
466             //d3dDisplay.d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
467             //d3dDisplay.d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
468             d3dDisplay.d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
469
470             //d3dDisplay.d3dpp.BackBufferFormat = D3DFMT_R5G6B5;
471             d3dDisplay.d3dpp.BackBufferFormat = d3dSystem.format;
472             d3dDisplay.d3dpp.BackBufferCount = 1;
473             d3dDisplay.d3dpp.hDeviceWindow = display.window;
474             d3dDisplay.d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
475             d3dDisplay.d3dpp.PresentationInterval = d3dDisplay.vSync ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_DONOTWAIT;
476             //d3dDisplay.d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
477             //d3dDisplay.d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
478
479             result = !IDirect3DDevice9_CreateAdditionalSwapChain(d3dSystem.d3dDevice,
480                &d3dDisplay.d3dpp, &d3dDisplay.swapChain);
481
482             if(!result)
483             {
484                d3dDisplay.d3dpp.MultiSampleType = D3DMULTISAMPLE_2_SAMPLES;
485                result = !IDirect3DDevice9_CreateAdditionalSwapChain(d3dSystem.d3dDevice,
486                   &d3dDisplay.d3dpp, &d3dDisplay.swapChain);
487             }
488             if(!result)
489             {
490                d3dDisplay.d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
491                result = !IDirect3DDevice9_CreateAdditionalSwapChain(d3dSystem.d3dDevice,
492                   &d3dDisplay.d3dpp, &d3dDisplay.swapChain);
493             }
494          }
495
496          if(result)
497          {
498             if(!IDirect3DSwapChain9_GetBackBuffer(d3dDisplay.swapChain,
499                0, D3DBACKBUFFER_TYPE_MONO, &d3dDisplay.backBuffer))
500             {
501                if(!IDirect3DDevice9_CreateDepthStencilSurface(d3dSystem.d3dDevice, width, height,
502                      D3DFMT_D16, d3dDisplay.d3dpp.MultiSampleType,0,TRUE,&d3dDisplay.depthSurface, null))
503                {
504                   result = true;
505                   d3dSystem.ready = true;
506                }
507             }
508          }
509
510          if(d3dSystem.ready)
511          {
512             float fogDensity = 0;
513
514             IDirect3DDevice9_SetVertexDeclaration(d3dDevice, d3dSystem.decl2D);
515
516             //IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
517             IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_CULLMODE, D3DCULL_NONE);
518             IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_ZENABLE, FALSE);
519             IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_LIGHTING, FALSE);
520             IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_ALPHABLENDENABLE, TRUE);
521             IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
522             IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
523             IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_FOGTABLEMODE, D3DFOG_EXP);
524             IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_FOGDENSITY, RenderStateFloat { fogDensity }.ui);
525             display.ambient = Color { 50,50,50 };
526             IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_NORMALIZENORMALS, TRUE);
527             IDirect3DDevice9_SetRenderState(d3dSystem.d3dDevice, D3DRS_MULTISAMPLEANTIALIAS, FALSE);
528
529             IDirect3DDevice9_SetTextureStageState(d3dDevice, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
530             IDirect3DDevice9_SetTextureStageState(d3dDevice, 0, D3DTSS_COLORARG1, D3DTA_CURRENT);
531             IDirect3DDevice9_SetTextureStageState(d3dDevice, 0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
532             IDirect3DDevice9_SetTextureStageState(d3dDevice, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
533             IDirect3DDevice9_SetTextureStageState(d3dDevice, 0, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
534             IDirect3DDevice9_SetTextureStageState(d3dDevice, 0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
535
536             IDirect3DDevice9_SetSamplerState(d3dDevice, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
537             IDirect3DDevice9_SetSamplerState(d3dDevice, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
538             IDirect3DDevice9_SetSamplerState(d3dDevice, 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
539
540             IDirect3DDevice9_SetSamplerState(d3dDevice, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
541             IDirect3DDevice9_SetSamplerState(d3dDevice, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
542
543             IDirect3DDevice9_SetTexture(d3dDevice, 0, null);
544
545             result = true;
546          }
547       }
548       display.width = width;
549       display.height = height;
550       d3dDisplay.updateBox.left = display.width;
551       d3dDisplay.updateBox.top = display.height;
552       d3dDisplay.updateBox.right = 0;
553       d3dDisplay.updateBox.bottom = 0;
554
555       return result;
556    }
557
558    void DisplayPosition(Display display, int x, int y)
559    {
560
561    }
562
563    void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
564    {
565    }
566
567    void RestorePalette(Display display)
568    {
569    }
570
571    void StartUpdate(Display display)
572    {
573    }
574
575    void EndUpdate(Display display)
576    {
577    }
578
579    void Scroll(Display display, Box scroll, int x, int y, Extent dirty)
580    {
581    }
582
583    void Update(Display display, Box updateBox)
584    {
585       DisplaySystem displaySystem = display.displaySystem;
586       D3DSystem d3dSystem = displaySystem.driverData;
587       D3DDisplay d3dDisplay = display.driverData;
588       if(d3dSystem.ready)
589       {
590          //eSystem_Sleep(0.05);
591          IDirect3DDevice9_EndScene(d3dSystem.d3dDevice);
592
593          if(display.displaySystem.flags.flipping)
594          {
595             // IDirect3DDevice9_Present(d3dSystem.d3dDevice, null, null, null, null);
596             IDirect3DSwapChain9_Present(d3dDisplay.swapChain, null, null, null, null, 0);
597          }
598          else
599          {
600             RECT source, dest;
601
602             if(updateBox != null)
603             {
604                source.left = dest.left = updateBox.left;
605                source.top = dest.top = updateBox.top;
606                source.right = dest.right = updateBox.right+1;
607                source.bottom = dest.bottom = updateBox.bottom+1;
608             }
609             else
610             {
611                source.left = dest.left = d3dDisplay.updateBox.left;
612                source.top = dest.top = d3dDisplay.updateBox.top;
613                source.right = dest.right = d3dDisplay.updateBox.right+1;
614                source.bottom = dest.bottom = d3dDisplay.updateBox.bottom+1;
615             }
616             if(dest.bottom > dest.top && dest.right > dest.left)
617                IDirect3DDevice9_Present(d3dSystem.d3dDevice, &source, &dest, null, null);
618             if(updateBox == null)
619             {
620                d3dDisplay.updateBox.left = display.width;
621                d3dDisplay.updateBox.top = display.height;
622                d3dDisplay.updateBox.right = 0;
623                d3dDisplay.updateBox.bottom = 0;
624             }
625          }
626          d3dSystem.inScene = false;
627       }
628    }
629
630    bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
631    {
632       bool result = false;
633       Surface lfbSurface;
634       Bitmap lfbBitmap { };
635
636       if(LockDisplay(display, null, lfbBitmap, &lfbSurface))
637       {
638          Surface surface;
639          if(bitmap.pixelFormat != lfbBitmap.pixelFormat || bitmap.width < w || bitmap.height < h)
640          {
641             bitmap.Free();
642             bitmap.Allocate(null, w,h,w, lfbBitmap.pixelFormat, false);
643          }
644          surface = bitmap.GetSurface(0, 0, null);
645          if(surface)
646          {
647             ((subclass(DisplayDriver))class(LFBDisplayDriver)).Blit(null, surface, lfbBitmap, 0, 0, x, y, w, h);
648             result = true;
649          }
650          delete surface;
651          UnlockDisplay(display, lfbSurface);
652       }
653
654       lfbBitmap.picture = null;
655       delete lfbBitmap;
656
657       if(!result)
658          bitmap.Free();
659       return result;
660    }
661
662    void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
663    {
664       if(bitmap.picture)
665          IDirect3DTexture9_Release((IDirect3DTexture9 *)bitmap.picture);
666    }
667
668    bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
669    {
670       return false;
671    }
672
673    bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
674    {
675       bool result = false;
676       D3DSystem d3dSystem = displaySystem.driverData;
677       if(bitmap.Convert(null, pixelFormat888, null))
678       {
679          IDirect3DTexture9 * texture;
680          uint w = pow2i(Min(bitmap.width, 512)), h = pow2i(Min(bitmap.height, 512));
681
682          if(!IDirect3DDevice9_CreateTexture(d3dSystem.d3dDevice, w, h, mipMaps ? log2i(Max(w+1, h+1)) : 1, 0,
683                D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, null))
684          {
685             int level;
686
687             result = true;
688
689             for(level = 0; result && (w >= 1 || h >= 1); level++, w >>= 1, h >>= 1)
690             {
691                D3DSURFACE_DESC desc;
692                D3DLOCKED_RECT lockedRect;
693
694                if(!IDirect3DTexture9_GetLevelDesc(texture, level, &desc) &&
695                   !IDirect3DTexture9_LockRect(texture, level, &lockedRect, null, 0))
696                {
697                   Bitmap mipMap { };
698                   Surface mipSurface;
699
700                   mipMap.width = desc.Width;
701                   mipMap.height = desc.Height;
702                   mipMap.picture = lockedRect.pBits;
703                   switch(desc.Format)
704                   {
705                      case D3DFMT_R5G6B5:   mipMap.pixelFormat = pixelFormat565; break;
706                      case D3DFMT_A8R8G8B8: mipMap.pixelFormat = pixelFormat888; break;
707                      case D3DFMT_A1R5G5B5: mipMap.pixelFormat = pixelFormat555; break;
708                      default:
709                         result = false;
710                   }
711                   if(result)
712                   {
713                      mipMap.stride = lockedRect.Pitch >> GetColorDepthShifts(mipMap.pixelFormat);
714
715                      mipSurface = mipMap.GetSurface(0,0,null);
716                      if(mipSurface)
717                      {
718                         if(mipMap.width != bitmap.width || mipMap.height != bitmap.height)
719                            mipSurface.Filter(bitmap, 0,0, 0,0, mipMap.width, mipMap.height, bitmap.width, bitmap.height);
720                         else
721                         {
722                            //FillBytesBy4(mipMap.picture, bitmap.picture, mipMap.width * mipMap.height);
723                            mipSurface.Blit(bitmap, 0,0, 0,0, bitmap.width, bitmap.height);
724                         }
725                         delete mipSurface;
726                      }
727                   }
728
729                   IDirect3DTexture9_UnlockRect(texture, level);
730
731                   mipMap.picture = null;
732                   delete mipMap;
733                }
734                if(!mipMaps) break;
735             }
736
737             bitmap.driver.FreeBitmap(bitmap.displaySystem, bitmap);
738             bitmap.driver = displaySystem.driver;
739             bitmap.picture = (void *)texture;
740
741             if(!result)
742                FreeBitmap(displaySystem, bitmap);
743          }
744       }
745       return result;
746    }
747
748    bool GetSurface(Display display, Surface surface, int x,int y, Box clip)
749    {
750       bool result = false;
751       D3DDisplay d3dDisplay = display.driverData;
752       DisplaySystem displaySystem = display.displaySystem;
753       D3DSystem d3dSystem = displaySystem.driverData;
754       D3DSurface d3dSurface = surface.driverData = D3DSurface { };
755
756       if(d3dSurface && d3dSystem.ready)
757       {
758          surface.unclippedBox = surface.box = clip;
759          surface.offset.x = x;
760          surface.offset.y = y;
761
762          d3dDisplay.updateBox.left = Min(x + clip.left, d3dDisplay.updateBox.left);
763          d3dDisplay.updateBox.top = Min(y + clip.top, d3dDisplay.updateBox.top);
764          d3dDisplay.updateBox.right = Max(x + clip.right, d3dDisplay.updateBox.right);
765          d3dDisplay.updateBox.bottom = Max(y + clip.bottom, d3dDisplay.updateBox.bottom);
766
767          SetViewportAndMatrices(display, x,y, surface.box);
768
769          result = true;
770       }
771       return result;
772    }
773
774    bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x, int y, Box clip)
775    {
776       return false;
777    }
778
779    void ReleaseSurface(Display display, Surface surface)
780    {
781       delete surface.driverData;
782    }
783
784    void Clip(Display display, Surface surface, Box clip)
785    {
786       Box box;
787
788       if(clip != null)
789       {
790          box = clip;
791          box.Clip(surface.unclippedBox);
792          surface.box = box;
793       }
794       else
795          box = surface.box = surface.unclippedBox;
796
797       SetViewportAndMatrices(display, surface.offset.x, surface.offset.y, box);
798    }
799
800    void SetForeground(Display display, Surface surface, ColorAlpha color)
801    {
802
803    }
804
805    void SetBackground(Display display, Surface surface, ColorAlpha color)
806    {
807       D3DSurface d3dSurface = surface.driverData;
808       d3dSurface.background = color;
809    }
810
811    ColorAlpha GetPixel(Display display, Surface surface,int x,int y)
812    {
813       return 0;
814    }
815
816    void PutPixel(Display display, Surface surface,int x, int y)
817    {
818       DisplaySystem displaySystem = display.displaySystem;
819       D3DSystem d3dSystem = displaySystem.driverData;
820       Vertex vertex { (float)x, (float)y, 1.0f, surface.foreground, 0, 0 };
821
822       IDirect3DDevice9_DrawPrimitiveUP(d3dSystem.d3dDevice, D3DPT_POINTLIST, 1,
823          &vertex, sizeof(Vertex));
824    }
825
826    void DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
827    {
828       DisplaySystem displaySystem = display.displaySystem;
829       D3DSystem d3dSystem = displaySystem.driverData;
830       Vertex vertex[2] =
831       {
832          { (float)x1, (float)y1, 1.0f, surface.foreground, 0, 0 },
833          { (float)x2, (float)y2, 1.0f, surface.foreground, 0, 0 }
834       };
835
836       if(x1 == x2)
837       {
838          /*
839          vertex[0].y-= 0.5f;
840          vertex[1].y+= 0.5f;
841          */
842          vertex[1].y+= 1.0f;
843       }
844       else if(y1 == y2)
845       {
846          /*
847          vertex[0].x-= 0.5f;
848          vertex[1].x+= 0.5f;
849          */
850          vertex[1].x+= 1.0f;
851       }
852
853       IDirect3DDevice9_DrawPrimitiveUP(d3dSystem.d3dDevice, D3DPT_LINESTRIP, 1,
854          vertex, sizeof(Vertex));
855    }
856
857    void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
858    {
859       DisplaySystem displaySystem = display.displaySystem;
860       D3DSystem d3dSystem = displaySystem.driverData;
861       Vertex vertex[5] =
862       {
863          { (float)x1, (float)y1, 1.0f, surface.foreground, 0, 0 },
864          { (float)x2, (float)y1, 1.0f, surface.foreground, 0, 0 },
865          { (float)x2, (float)y2, 1.0f, surface.foreground, 0, 0 },
866          { (float)x1, (float)y2, 1.0f, surface.foreground, 0, 0 },
867          { (float)x1, (float)y1, 1.0f, surface.foreground, 0, 0 }
868       };
869
870       IDirect3DDevice9_DrawPrimitiveUP(d3dSystem.d3dDevice, D3DPT_LINESTRIP, 4,
871          vertex, sizeof(Vertex));
872
873    }
874
875    void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
876    {
877       DisplaySystem displaySystem = display.displaySystem;
878       D3DSystem d3dSystem = displaySystem.driverData;
879       D3DSurface d3dSurface = surface.driverData;
880       Vertex vertex[4] =
881       {
882          /*
883          { (float)x1, (float)y1, 1.0f, d3dSurface.background, 0, 0 },
884          { (float)x2 + 1.0f, (float)y1, 1.0f, d3dSurface.background, 0, 0 },
885          { (float)x1, (float)y2, 1.0f, d3dSurface.background, 0, 0 },
886          { (float)x2 + 1.0f, (float)y2, 1.0f, d3dSurface.background, 0, 0 }
887          */
888          { (float)x1, (float)y1 - 0.5f, 1.0f, d3dSurface.background, 0, 0 },
889          { (float)x2 + 1.0f, (float)y1 - 0.5f, 1.0f, d3dSurface.background, 0, 0 },
890          { (float)x1, (float)y2 + 1.5f, 1.0f, d3dSurface.background, 0, 0 },
891          { (float)x2 + 1.0f, (float)y2 + 1.5f, 1.0f, d3dSurface.background, 0, 0 }
892       };
893
894       IDirect3DDevice9_DrawPrimitiveUP(d3dSystem.d3dDevice, D3DPT_TRIANGLESTRIP, 2,
895          vertex, sizeof(Vertex));
896    }
897
898    void Clear(Display display, Surface surface, ClearType type)
899    {
900       DisplaySystem displaySystem = display.displaySystem;
901       D3DSystem d3dSystem = displaySystem.driverData;
902       D3DSurface d3dSurface = surface.driverData;
903       IDirect3DDevice9_Clear(d3dSystem.d3dDevice, 0, null,
904          ((type == depthBuffer) ? 0 : D3DCLEAR_TARGET) |
905          ((type == colorBuffer) ? 0 : D3DCLEAR_ZBUFFER),
906          d3dSurface.background, 1,0);
907    }
908
909    bool ConvertBitmap(DisplaySystem displaySystem, Bitmap bitmap, PixelFormat format, ColorAlpha * palette)
910    {
911       return true;
912    }
913
914    void Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
915    {
916       DisplaySystem displaySystem = display.displaySystem;
917       D3DSystem d3dSystem = displaySystem.driverData;
918       D3DSurface d3dSurface = surface.driverData;
919       Color foreground = d3dSurface.writingText ? surface.foreground : white;
920       Vertex vertex[4] =
921       {
922          { (float)dx, (float)dy, 1.0f, foreground,
923             (float)sx / (src.width-1), (float)sy/ (src.height-1) },
924          { (float)(dx+w), (float)dy, 1.0f, foreground,
925             (float)(sx+w)/ (src.width-1), (float)sy/ (src.height-1) },
926          { (float)dx, (float)(dy+h), 1.0f, foreground,
927             (float)sx/ (src.width-1), (float)(sy+h)/ (src.height-1) },
928          { (float)(dx+w), (float)(dy+h), 1.0f, foreground,
929             (float)(sx+w) / (src.width-1), (float)(sy+h)/ (src.height-1) }
930       };
931
932       IDirect3DDevice9_SetTexture(d3dSystem.d3dDevice, 0, (IDirect3DBaseTexture9 *)src.picture);
933       IDirect3DDevice9_DrawPrimitiveUP(d3dSystem.d3dDevice, D3DPT_TRIANGLESTRIP, 2,
934          vertex, sizeof(Vertex));
935       IDirect3DDevice9_SetTexture(d3dSystem.d3dDevice, 0, null);
936    }
937
938    void Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
939    {
940       DisplaySystem displaySystem = display.displaySystem;
941       D3DSystem d3dSystem = displaySystem.driverData;
942       Vertex vertex[4] =
943       {
944          { (float)dx, (float)dy, 1.0f, surface.foreground,
945             (float)sx / (src.width-1), (float)sy/ (src.height-1) },
946          { (float)(dx+w), (float)dy, 1.0f, surface.foreground,
947             (float)(sx+sw)/ (src.width-1), (float)sy/ (src.height-1) },
948          { (float)dx, (float)(dy+h), 1.0f, surface.foreground,
949             (float)sx/ (src.width-1), (float)(sy+sh)/ (src.height-1) },
950          { (float)(dx+w), (float)(dy+h), 1.0f, surface.foreground,
951             (float)(sx+sw) / (src.width-1), (float)(sy+sh)/ (src.height-1) }
952       };
953
954       IDirect3DDevice9_SetTexture(d3dSystem.d3dDevice, 0, (IDirect3DBaseTexture9 *)src.picture);
955       IDirect3DDevice9_DrawPrimitiveUP(d3dSystem.d3dDevice, D3DPT_TRIANGLESTRIP, 2,
956          vertex, sizeof(Vertex));
957       IDirect3DDevice9_SetTexture(d3dSystem.d3dDevice, 0, null);
958    }
959
960    void Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
961    {
962       Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
963    }
964
965    void StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
966    {
967       Surface lfbSurface;
968       Bitmap lfbBitmap { };
969       if(LockDisplay(display, surface, lfbBitmap, &lfbSurface))
970       {
971          ((subclass(DisplayDriver))class(LFBDisplayDriver)).Stretch(null, lfbSurface, src, dx, dy, sx, sy, w, h, sw, sh);
972          UnlockDisplay(display, lfbSurface);
973       }
974       lfbBitmap.picture = null;
975       delete lfbBitmap;
976    }
977
978    void BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
979    {
980       Surface lfbSurface;
981       Bitmap lfbBitmap { };
982       if(LockDisplay(display, surface, lfbBitmap, &lfbSurface))
983       {
984          ((subclass(DisplayDriver))class(LFBDisplayDriver)).Blit(null, lfbSurface, src, dx, dy, sx, sy, w, h);
985          UnlockDisplay(display, lfbSurface);
986       }
987       lfbBitmap.picture = null;
988       delete lfbBitmap;
989    }
990
991    void FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
992    {
993       StretchDI(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
994    }
995
996    void UnloadFont(DisplaySystem displaySystem, Font font)
997    {
998       ((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, font);
999    }
1000
1001    Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
1002    {
1003       return ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags);
1004    }
1005
1006    void TextFont(Display display, Surface surface, Font font)
1007    {
1008       ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextFont(display, surface, font);
1009    }
1010
1011    void TextOpacity(Display display, Surface surface, bool opaque)
1012    {
1013       D3DSurface d3dSurface = surface.driverData;
1014       d3dSurface.opaqueText = opaque;
1015    }
1016
1017    void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height)
1018    {
1019       ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(displaySystem, font, text, len, width, height);
1020    }
1021
1022    void WriteText(Display display, Surface surface, int x, int y, const char * text, int len)
1023    {
1024       DisplaySystem displaySystem = display.displaySystem;
1025       D3DSystem d3dSystem = displaySystem.driverData;
1026       D3DSurface d3dSurface = surface.driverData;
1027
1028       if(surface.textOpacity)
1029       {
1030          int w, h;
1031          FontExtent(display.displaySystem, surface.font, text, len, &w, &h);
1032          {
1033             int x1 = x, y1 = y, x2 = x+w-1, y2 = y+h-1;
1034             Vertex vertex[4] =
1035             {
1036                { (float)x1, (float)y1 /*- 0.5*/, 1.0f, d3dSurface.background, 0, 0 },
1037                { (float)x2 + 1.0f, (float)y1 /*- 0.5*/, 1.0f, d3dSurface.background, 0, 0 },
1038                { (float)x1, (float)y2 /*+ 1.5f*/, 1.0f, d3dSurface.background, 0, 0 },
1039                { (float)x2 + 1.0f, (float)y2 /*+ 1.5f*/, 1.0f, d3dSurface.background, 0, 0 }
1040             };
1041
1042             IDirect3DDevice9_DrawPrimitiveUP(d3dSystem.d3dDevice, D3DPT_TRIANGLESTRIP, 2,
1043                vertex, sizeof(Vertex));
1044          }
1045          //display.displaySystem.driver.Area(display, surface, x, y, x+w-1, y+h-1);
1046       }
1047
1048       IDirect3DDevice9_SetSamplerState(d3dSystem.d3dDevice, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
1049       IDirect3DDevice9_SetSamplerState(d3dSystem.d3dDevice, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
1050       IDirect3DDevice9_SetSamplerState(d3dSystem.d3dDevice, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
1051       d3dSurface.writingText = true;
1052
1053       ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len);
1054
1055       d3dSurface.writingText = false;
1056       IDirect3DDevice9_SetSamplerState(d3dSystem.d3dDevice, 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
1057       IDirect3DDevice9_SetSamplerState(d3dSystem.d3dDevice, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
1058       IDirect3DDevice9_SetSamplerState(d3dSystem.d3dDevice, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
1059    }
1060
1061    void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height)
1062    {
1063       ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextExtent(display, surface, text, len, width, height);
1064    }
1065
1066    void DrawingChar(Display display, Surface surface, char character)
1067    {
1068
1069    }
1070
1071    void LineStipple(Display display, Surface surface, uint stipple)
1072    {
1073       /*
1074       IDirect3DDevice9_SetRenderState(d3dSystem.d3dDevice, D3DRS_LINEPATTERN,
1075          stipple?Muint(1,stipple):0);
1076       */
1077    }
1078
1079
1080    void SetRenderState(Display display, RenderState state, uint value)
1081    {
1082       DisplaySystem displaySystem = display.displaySystem;
1083       D3DSystem d3dSystem = displaySystem.driverData;
1084       D3DDisplay d3dDisplay = display.driverData;
1085       switch(state)
1086       {
1087          case antiAlias:
1088             IDirect3DDevice9_SetRenderState(d3dSystem.d3dDevice, D3DRS_MULTISAMPLEANTIALIAS, value ? TRUE : FALSE);
1089             break;
1090          case fillMode:
1091             IDirect3DDevice9_SetRenderState(d3dSystem.d3dDevice, D3DRS_FILLMODE,
1092                ((FillModeValue)value == solid) ? D3DFILL_SOLID : D3DFILL_WIREFRAME);
1093             break;
1094          case depthTest:
1095             // IDirect3DDevice9_SetRenderState(d3dSystem.d3dDevice, D3DRS_ZENABLE, value ? D3DZB_USEW : D3DZB_FALSE);
1096             IDirect3DDevice9_SetRenderState(d3dSystem.d3dDevice, D3DRS_ZENABLE, value ? D3DZB_TRUE : D3DZB_FALSE);
1097             break;
1098          case depthWrite:
1099             IDirect3DDevice9_SetRenderState(d3dSystem.d3dDevice, D3DRS_ZWRITEENABLE, value);
1100             break;
1101          case fogColor:
1102             IDirect3DDevice9_SetRenderState(d3dSystem.d3dDevice, D3DRS_FOGCOLOR, value);
1103             break;
1104          case fogDensity:
1105          {
1106             float fogDensity = RenderStateFloat { ui = value }.f;
1107             IDirect3DDevice9_SetRenderState(d3dSystem.d3dDevice, D3DRS_FOGDENSITY, RenderStateFloat { fogDensity }.ui);
1108             break;
1109          }
1110          case blend:
1111             IDirect3DDevice9_SetRenderState(d3dSystem.d3dDevice, D3DRS_ALPHABLENDENABLE, value);
1112             break;
1113          case ambient:
1114             IDirect3DDevice9_SetRenderState(d3dSystem.d3dDevice, D3DRS_AMBIENT, value);
1115             break;
1116          case vSync:
1117          {
1118             if(d3dDisplay.vSync != (bool)value)
1119             {
1120                d3dDisplay.vSync = (bool)value;
1121                DisplaySize(display, display.width, display.height);
1122             }
1123             break;
1124          }
1125       }
1126    }
1127
1128    void SetLight(Display display, int id, Light light)
1129    {
1130       DisplaySystem displaySystem = display.displaySystem;
1131       D3DSystem d3dSystem = displaySystem.driverData;
1132       D3DDisplay d3dDisplay = display.driverData;
1133       if(light != null)
1134       {
1135          D3DLIGHT9 d3dLight =
1136          {
1137             // Opacity on the light?
1138             D3DLIGHT_DIRECTIONAL,
1139             { light.diffuse.r, light.diffuse.g, light.diffuse.b,     1.0f },
1140             { light.specular.r, light.specular.g, light.specular.b,  1.0f },
1141             { light.ambient.r, light.ambient.g, light.ambient.b,     1.0f }
1142          };
1143          Vector3Df vector {0,0,1};
1144          Vector3Df vectorPI {0,0,-1};
1145          Vector3Df direction;
1146          Matrix mat;
1147          Vector3Df * lightDirection = (Vector3Df *)&d3dLight.Direction;
1148
1149          mat.RotationQuaternion(light.orientation);
1150
1151          direction.MultMatrix(vector, mat);
1152          if(!display.display3D || !display.display3D.camera)
1153          {
1154             d3dLight.Direction.x = direction.x;
1155             d3dLight.Direction.y = direction.y;
1156             d3dLight.Direction.z =-direction.z;
1157          }
1158          else
1159             lightDirection->MultMatrix(direction, d3dDisplay.worldMatrix);
1160
1161          d3dDisplay.lights[id] = d3dLight;
1162
1163          IDirect3DDevice9_LightEnable(d3dSystem.d3dDevice, id, TRUE);
1164          IDirect3DDevice9_SetLight(d3dSystem.d3dDevice, id, &d3dDisplay.lights[id] /*d3dLight*/);
1165
1166          direction.MultMatrix(vectorPI, mat);
1167          lightDirection->MultMatrix(direction, d3dDisplay.worldMatrix);
1168
1169          d3dDisplay.lightsPI[id] = d3dLight;
1170       }
1171       else
1172       {
1173          IDirect3DDevice9_LightEnable(d3dSystem.d3dDevice, id, FALSE);
1174          d3dDisplay.lights[id].Type = 0;
1175       }
1176    }
1177
1178    void SetCamera(Display display, Surface surface, Camera camera)
1179    {
1180       DisplaySystem displaySystem = display.displaySystem;
1181       D3DSystem d3dSystem = displaySystem.driverData;
1182       D3DDisplay d3dDisplay = display.driverData;
1183       IDirect3DDevice9 * d3dDevice = d3dSystem.d3dDevice;
1184       if(camera)
1185       {
1186          Point topLeft {surface.box.left + surface.offset.x, surface.box.top + surface.offset.y};
1187          Point downRight {surface.box.right + surface.offset.x, surface.box.bottom  + surface.offset.y};
1188          Point origin
1189          {
1190             surface.offset.x + camera.origin.x,
1191             surface.offset.y + camera.origin.y
1192          };
1193          D3DMATRIX matProj;
1194          Matrix matrix;
1195          float l = (topLeft.x - origin.x) * camera.zMin / camera.focalX;
1196          float r = (downRight.x - origin.x) * camera.zMin / camera.focalX;
1197          float b = (downRight.y - origin.y) * camera.zMin / camera.focalY;
1198          float t = (topLeft.y - origin.y) * camera.zMin / camera.focalY;
1199          float n = camera.zMin;
1200          float f = camera.zMax;
1201
1202          matProj.m[0][0] = 2 * n / (r - l);
1203          matProj.m[0][1] = 0;
1204          matProj.m[0][2] = 0;
1205          matProj.m[0][3] = 0;
1206
1207          matProj.m[1][0] = 0;
1208          matProj.m[1][1] = 2 * n / (t - b);
1209          matProj.m[1][2] = 0;
1210          matProj.m[1][3] = 0;
1211
1212          matProj.m[2][0] = (l + r) / (r - l);
1213          matProj.m[2][1] = (t + b) / (t - b);
1214          matProj.m[2][2] = f / (n - f);
1215          matProj.m[2][3] = -1;
1216
1217          matProj.m[3][0] = 0;
1218          matProj.m[3][1] = 0;
1219          matProj.m[3][2] = n * f / (n - f);
1220          matProj.m[3][3] = 0;
1221
1222          IDirect3DDevice9_SetTransform(d3dDevice, D3DTS_PROJECTION, &matProj);
1223
1224          // *** View Matrix ***
1225          if(!display.display3D.camera)
1226             d3dDisplay.worldMatrix++;
1227
1228          matrix.Identity();
1229          matrix.Scale(1.0f, 1.0f, -1.0f);
1230          d3dDisplay.worldMatrix->Multiply(camera.viewMatrix, matrix);
1231
1232          SetTransformMatrix(d3dDevice, d3dDisplay.worldMatrix);
1233
1234          IDirect3DDevice9_SetVertexDeclaration(d3dDevice, d3dSystem.decls[0]);
1235
1236          // IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_ZENABLE, D3DZB_USEW);
1237          IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_ZENABLE, D3DZB_TRUE);
1238          IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_ZWRITEENABLE, TRUE);
1239          IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_ALPHABLENDENABLE, FALSE);
1240          IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_LIGHTING, TRUE);
1241          IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_SPECULARENABLE, TRUE);
1242
1243          IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_CULLMODE, D3DCULL_CW);
1244
1245          IDirect3DDevice9_SetRenderState(d3dSystem.d3dDevice, D3DRS_MULTISAMPLEANTIALIAS, TRUE);
1246       }
1247       else if(display.display3D.camera)
1248       {
1249          d3dDisplay.worldMatrix = d3dDisplay.worldMatrixStack;
1250          SetTransformMatrix(d3dDevice, d3dDisplay.worldMatrix);
1251          IDirect3DDevice9_SetTransform(d3dDevice, D3DTS_PROJECTION, &d3dDisplay.projMatrix);
1252
1253          IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_CULLMODE, D3DCULL_NONE);
1254          IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_ZENABLE, FALSE);
1255          IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_LIGHTING, FALSE);
1256          IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_ALPHABLENDENABLE, TRUE);
1257          IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_FOGENABLE, FALSE);
1258          IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_SPECULARENABLE, FALSE);
1259
1260          IDirect3DDevice9_SetSamplerState(d3dDevice, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1261          IDirect3DDevice9_SetSamplerState(d3dDevice, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1262
1263          IDirect3DDevice9_SetVertexDeclaration(d3dDevice, d3dSystem.decl2D);
1264
1265          IDirect3DDevice9_SetTexture(d3dDevice, 0, null);
1266
1267          IDirect3DDevice9_SetRenderState(d3dSystem.d3dDevice, D3DRS_MULTISAMPLEANTIALIAS, FALSE);
1268       }
1269    }
1270
1271    void ApplyMaterial(Display display, Material material, Mesh mesh)
1272    {
1273       DisplaySystem displaySystem = display.displaySystem;
1274       D3DSystem d3dSystem = displaySystem.driverData;
1275       IDirect3DDevice9 * d3dDevice = d3dSystem.d3dDevice;
1276       D3DMesh d3dMesh = mesh.data;
1277
1278       // Fog
1279       IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_FOGENABLE, (material.flags.noFog) ? FALSE : TRUE);
1280
1281       // Maps
1282       if(material.baseMap && d3dMesh.texCoords && material.baseMap.driver.displaySystem == displaySystem)
1283       {
1284          Bitmap map = material.baseMap;
1285
1286          IDirect3DDevice9_SetTexture(d3dDevice, 0, (IDirect3DBaseTexture9 *)map.picture);
1287
1288          if(material.flags.tile)
1289          {
1290             IDirect3DDevice9_SetSamplerState(d3dDevice, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
1291             IDirect3DDevice9_SetSamplerState(d3dDevice, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
1292          }
1293          else
1294          {
1295             IDirect3DDevice9_SetSamplerState(d3dDevice, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1296             IDirect3DDevice9_SetSamplerState(d3dDevice, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1297          }
1298       }
1299       else
1300          IDirect3DDevice9_SetTexture(d3dDevice, 0, null);
1301
1302       {
1303          D3DMATERIAL9 d3dMaterial;
1304
1305          d3dMaterial.Diffuse.r = material.diffuse.r;
1306          d3dMaterial.Diffuse.g = material.diffuse.g;
1307          d3dMaterial.Diffuse.b = material.diffuse.b;
1308          d3dMaterial.Diffuse.a = material.opacity;
1309
1310          d3dMaterial.Ambient.r = material.ambient.r;
1311          d3dMaterial.Ambient.g = material.ambient.g;
1312          d3dMaterial.Ambient.b = material.ambient.b;
1313          d3dMaterial.Ambient.a = 1;
1314
1315          d3dMaterial.Specular.r = material.specular.r;
1316          d3dMaterial.Specular.g = material.specular.g;
1317          d3dMaterial.Specular.b = material.specular.b;
1318          d3dMaterial.Specular.a = 1;
1319
1320          d3dMaterial.Emissive.r = material.emissive.r;
1321          d3dMaterial.Emissive.g = material.emissive.g;
1322          d3dMaterial.Emissive.b = material.emissive.b;
1323          d3dMaterial.Emissive.a = 1;
1324
1325          d3dMaterial.Power = material.power;
1326
1327          IDirect3DDevice9_SetMaterial(d3dDevice, &d3dMaterial);   //(D3DMATERIAL9 *)&material.diffuse
1328       }
1329    }
1330
1331    void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
1332    {
1333       D3DMesh d3dMesh = mesh.data;
1334       if(d3dMesh)
1335       {
1336          if(!(mesh.flags.vertices))
1337          {
1338             if(d3dMesh.vertices)
1339             {
1340                IDirect3DVertexBuffer9_Release(d3dMesh.vertices);
1341                d3dMesh.vertices = null;
1342             }
1343             delete mesh.vertices;
1344          }
1345          if(!(mesh.flags.normals))
1346          {
1347             if(d3dMesh.normals)
1348             {
1349                IDirect3DVertexBuffer9_Release(d3dMesh.normals);
1350                d3dMesh.normals = null;
1351             }
1352             delete mesh.normals;
1353          }
1354          if(!(mesh.flags.texCoords1))
1355          {
1356             if(d3dMesh.texCoords)
1357             {
1358                IDirect3DVertexBuffer9_Release(d3dMesh.texCoords);
1359                d3dMesh.texCoords = null;
1360             }
1361             delete mesh.texCoords;
1362          }
1363          if(!(mesh.flags.texCoords2))
1364          {
1365             if(d3dMesh.texCoords2)
1366             {
1367                IDirect3DVertexBuffer9_Release(d3dMesh.texCoords2);
1368                d3dMesh.texCoords2 = null;
1369             }
1370             // delete mesh.texCoords2;
1371          }
1372          if(!mesh.flags)
1373          {
1374             delete d3dMesh;
1375             mesh.data = null;
1376          }
1377       }
1378    }
1379
1380    bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh)
1381    {
1382       D3DSystem d3dSystem = displaySystem.driverData;
1383       bool result = false;
1384       IDirect3DDevice9 * d3dDevice = d3dSystem.d3dDevice;
1385
1386       if(!mesh.data)
1387          mesh.data = D3DMesh { };
1388       if(mesh.data)
1389       {
1390          D3DMesh d3dMesh = mesh.data;
1391          result = true;
1392          if((mesh.flags.vertices) && !d3dMesh.vertices)
1393          {
1394             mesh.vertices = new Vector3Df[mesh.nVertices];
1395             if(IDirect3DDevice9_CreateVertexBuffer(d3dDevice, sizeof(Vector3Df) * mesh.nVertices,
1396                d3dSystem.usage, 0, D3DPOOL_MANAGED, &d3dMesh.vertices, null))
1397                result = false;
1398          }
1399          if((mesh.flags.normals) && !d3dMesh.normals)
1400          {
1401             mesh.normals = new Vector3Df[mesh.nVertices];
1402             if(IDirect3DDevice9_CreateVertexBuffer(d3dDevice, sizeof(Vector3Df) * mesh.nVertices,
1403                d3dSystem.usage, 0, D3DPOOL_MANAGED, &d3dMesh.normals, null))
1404                result = false;
1405          }
1406          if((mesh.flags.texCoords1) && !d3dMesh.texCoords)
1407          {
1408             mesh.texCoords = new Pointf[mesh.nVertices];
1409             if(IDirect3DDevice9_CreateVertexBuffer(d3dDevice, sizeof(Pointf) * mesh.nVertices,
1410                d3dSystem.usage, 0, D3DPOOL_MANAGED, &d3dMesh.texCoords, null))
1411                result = false;
1412          }
1413       }
1414       return result;
1415    }
1416
1417    void UnlockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags)
1418    {
1419       D3DMesh d3dMesh = mesh.data;
1420       if(!flags) flags = mesh.flags;
1421
1422       if(flags.vertices && mesh.vertices)
1423       {
1424          Vector3Df * vertices;
1425          if(!IDirect3DVertexBuffer9_Lock(d3dMesh.vertices, 0, 0, (void **) &vertices, 0))
1426          {
1427             memcpy(vertices, mesh.vertices, mesh.nVertices * sizeof(Vector3Df));
1428             IDirect3DVertexBuffer9_Unlock(d3dMesh.vertices);
1429          }
1430       }
1431       if(flags.normals && mesh.normals)
1432       {
1433          Vector3Df * normals;
1434          if(!IDirect3DVertexBuffer9_Lock(d3dMesh.normals, 0, 0, (void **) &normals, 0))
1435          {
1436             memcpy(normals, mesh.normals, mesh.nVertices * sizeof(Vector3Df));
1437             IDirect3DVertexBuffer9_Unlock(d3dMesh.normals);
1438          }
1439       }
1440       if(flags.texCoords1 && mesh.texCoords)
1441       {
1442          Pointf * texCoords;
1443          if(!IDirect3DVertexBuffer9_Lock(d3dMesh.texCoords, 0, 0, (void **) &texCoords, 0))
1444          {
1445             memcpy(texCoords, mesh.texCoords, mesh.nVertices * sizeof(Pointf));
1446             IDirect3DVertexBuffer9_Unlock(d3dMesh.texCoords);
1447          }
1448       }
1449    }
1450
1451    bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags)
1452    {
1453
1454       return true;
1455    }
1456
1457    void FreeIndices(DisplaySystem displaySystem, D3DIndices d3dIndices)
1458    {
1459       if(d3dIndices)
1460       {
1461          if(d3dIndices.buffer)
1462             IDirect3DIndexBuffer9_Release(d3dIndices.buffer);
1463          delete d3dIndices.indices;
1464          delete d3dIndices;
1465       }
1466    }
1467
1468    D3DIndices AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
1469    {
1470       D3DSystem d3dSystem = displaySystem.driverData;
1471       IDirect3DDevice9 * d3dDevice = d3dSystem.d3dDevice;
1472       D3DIndices d3dIndices { };
1473       if(d3dIndices && nIndices)
1474       {
1475          d3dIndices.indices = (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
1476          IDirect3DDevice9_CreateIndexBuffer(d3dDevice, (indices32bit ? sizeof(uint32) : sizeof(uint16)) * nIndices, 0, indices32bit ? D3DFMT_INDEX32 : D3DFMT_INDEX16,
1477             D3DPOOL_MANAGED, &d3dIndices.buffer, null);
1478          d3dIndices.nIndices = nIndices;
1479       }
1480       return d3dIndices;
1481    }
1482
1483    void UnlockIndices(DisplaySystem displaySystem, D3DIndices d3dIndices, bool indices32bit, int nIndices)
1484    {
1485       uint16 * indexBuffer = null;
1486       if(!IDirect3DIndexBuffer9_Lock(d3dIndices.buffer, 0, 0, (void **)&indexBuffer, 0))
1487       {
1488          memcpy(indexBuffer, d3dIndices.indices, (indices32bit ? sizeof(uint32) : sizeof(uint16)) * d3dIndices.nIndices);
1489          IDirect3DIndexBuffer9_Unlock(d3dIndices.buffer);
1490       }
1491    }
1492
1493    uint16 * LockIndices(DisplaySystem displaySystem, D3DIndices d3dIndices)
1494    {
1495       return d3dIndices.indices;
1496    }
1497
1498    void SelectMesh(Display display, Mesh mesh)
1499    {
1500       DisplaySystem displaySystem = display.displaySystem;
1501       D3DSystem d3dSystem = displaySystem.driverData;
1502       IDirect3DDevice9 * d3dDevice = d3dSystem.d3dDevice;
1503
1504       if(mesh && mesh.data)
1505       {
1506          int decl = 0;
1507          D3DMesh d3dMesh = mesh.data;
1508
1509          IDirect3DDevice9_SetStreamSource(d3dDevice, 0, d3dMesh.vertices, 0, sizeof(Vector3Df));
1510          if(d3dMesh.normals)
1511          {
1512             IDirect3DDevice9_SetStreamSource(d3dDevice, 1, d3dMesh.normals, 0, sizeof(Vector3Df));
1513             decl |= 1;
1514          }
1515          else
1516             IDirect3DDevice9_SetStreamSource(d3dDevice, 1, null, 0, sizeof(Vector3Df));
1517          if(d3dMesh.texCoords)
1518          {
1519             IDirect3DDevice9_SetStreamSource(d3dDevice, 2, d3dMesh.texCoords, 0, sizeof(Pointf));
1520             decl |= 2;
1521          }
1522          else
1523             IDirect3DDevice9_SetStreamSource(d3dDevice, 2, null, 0, sizeof(Pointf));
1524
1525          IDirect3DDevice9_SetVertexDeclaration(d3dDevice, d3dSystem.decls[decl]);
1526       }
1527    }
1528
1529    void DrawPrimitives(Display display, PrimitiveSingle * primitive, Mesh mesh)
1530    {
1531       DisplaySystem displaySystem = display.displaySystem;
1532       D3DSystem d3dSystem = displaySystem.driverData;
1533       D3DDisplay d3dDisplay = display.driverData;
1534       IDirect3DDevice9 * d3dDevice = d3dSystem.d3dDevice;
1535
1536       if(primitiveTypes[primitive->type.primitiveType])
1537       {
1538          int numPrimitives = (primitive->type.vertexRange) ? primitive->nVertices : primitive->nIndices;
1539          int c;
1540
1541          switch(primitive->type.primitiveType)
1542          {
1543             case lines:     numPrimitives /= 2; break;
1544             case triangles: numPrimitives /= 3; break;
1545             case triStrip:
1546             case triFan:
1547                numPrimitives -= 2;
1548                break;
1549             case lineStrip:
1550                numPrimitives --;
1551                break;
1552             case quads:
1553                numPrimitives /= 4;
1554                break;
1555          }
1556          if(primitive->type.vertexRange)
1557          {
1558             if(primitive->type.primitiveType == quads)
1559             {
1560                for(c = 0; c<numPrimitives; c++)
1561                   IDirect3DDevice9_DrawPrimitive(d3dDevice, primitiveTypes[primitive->type.primitiveType], primitive->first+c*4, 2);
1562             }
1563             else
1564                IDirect3DDevice9_DrawPrimitive(d3dDevice, primitiveTypes[primitive->type.primitiveType], primitive->first, numPrimitives);
1565          }
1566          else
1567          {
1568             D3DIndices indices = primitive->data;
1569             IDirect3DDevice9_SetIndices(d3dDevice, indices.buffer);
1570             if(primitive->type.primitiveType == quads)
1571             {
1572                for(c = 0; c<numPrimitives; c++)
1573                   IDirect3DDevice9_DrawIndexedPrimitive(d3dDevice, primitiveTypes[primitive->type.primitiveType], 0, 0, mesh.nVertices, c*4, 2);
1574             }
1575             else
1576                IDirect3DDevice9_DrawIndexedPrimitive(d3dDevice, primitiveTypes[primitive->type.primitiveType], 0, 0, mesh.nVertices, 0, numPrimitives);
1577          }
1578
1579          if(display.display3D.material.flags.doubleSided)
1580          {
1581             IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_CULLMODE, D3DCULL_CCW);
1582             if(!display.display3D.material.flags.singleSideLight)
1583             {
1584                for(c = 0; c<NumberOfLights; c++)
1585                   if(d3dDisplay.lights[c].Type)
1586                      IDirect3DDevice9_SetLight(d3dDevice, c, &d3dDisplay.lightsPI[c]);
1587             }
1588
1589             if(primitive->type.vertexRange)
1590             {
1591                if(primitive->type.primitiveType == quads)
1592                {
1593                   for(c = 0; c<numPrimitives; c++)
1594                      IDirect3DDevice9_DrawPrimitive(d3dDevice, primitiveTypes[primitive->type.primitiveType], primitive->first+c*4, 2);
1595                }
1596                else
1597                   IDirect3DDevice9_DrawPrimitive(d3dDevice, primitiveTypes[primitive->type.primitiveType], primitive->first, numPrimitives);
1598             }
1599             else
1600             {
1601                D3DIndices indices = primitive->data;
1602                IDirect3DDevice9_SetIndices(d3dDevice, indices.buffer);
1603                if(primitive->type.primitiveType == quads)
1604                {
1605                   for(c = 0; c<numPrimitives; c++)
1606                      IDirect3DDevice9_DrawIndexedPrimitive(d3dDevice, primitiveTypes[primitive->type.primitiveType], 0, 0, mesh.nVertices, c*4, 2);
1607                }
1608                else
1609                   IDirect3DDevice9_DrawIndexedPrimitive(d3dDevice, primitiveTypes[primitive->type.primitiveType], 0, 0, mesh.nVertices, 0, numPrimitives);
1610             }
1611             if(!display.display3D.material.flags.singleSideLight)
1612             {
1613                for(c = 0; c<NumberOfLights; c++)
1614                   if(d3dDisplay.lights[c].Type)
1615                      IDirect3DDevice9_SetLight(d3dDevice, c, &d3dDisplay.lights[c]);
1616             }
1617
1618             IDirect3DDevice9_SetRenderState(d3dDevice, D3DRS_CULLMODE, D3DCULL_CW);
1619          }
1620       }
1621    }
1622
1623    void PushMatrix(Display display)
1624    {
1625       D3DDisplay d3dDisplay = display.driverData;
1626       *(d3dDisplay.worldMatrix+1) = *(d3dDisplay.worldMatrix);
1627       d3dDisplay.worldMatrix++;
1628    }
1629
1630    void PopMatrix(Display display, bool setMatrix)
1631    {
1632       D3DDisplay d3dDisplay = display.driverData;
1633       DisplaySystem displaySystem = display.displaySystem;
1634       D3DSystem d3dSystem = displaySystem.driverData;
1635       d3dDisplay.worldMatrix--;
1636       if(setMatrix)
1637          SetTransformMatrix(d3dSystem.d3dDevice, d3dDisplay.worldMatrix);
1638    }
1639
1640    void SetTransform(Display display, Matrix transMatrix, bool viewSpace, bool useCamera)
1641    {
1642       DisplaySystem displaySystem = display.displaySystem;
1643       D3DSystem d3dSystem = displaySystem.driverData;
1644       Camera camera = useCamera ? display.display3D.camera : null;
1645       D3DDisplay d3dDisplay = display.driverData;
1646       IDirect3DDevice9 * d3dDevice = d3dSystem.d3dDevice;
1647
1648       Matrix matrix = transMatrix, temp;
1649
1650       if(viewSpace)
1651       {
1652          matrix.Scale(1.0f, 1.0f, -1.0f);
1653          *(d3dDisplay.worldMatrix) = matrix;
1654       }
1655       else
1656       {
1657          if(camera)
1658             matrix.Translate(
1659                - camera.cPosition.x,
1660                - camera.cPosition.y,
1661                - camera.cPosition.z);
1662          temp.Multiply(matrix, d3dDisplay.worldMatrix);
1663          *(d3dDisplay.worldMatrix) = temp;
1664       }
1665
1666       SetTransformMatrix(d3dDevice, d3dDisplay.worldMatrix);
1667    }
1668
1669    bool Lock(Display display)
1670    {
1671       DisplaySystem displaySystem = display.displaySystem;
1672       D3DSystem d3dSystem = displaySystem.driverData;
1673       D3DDisplay d3dDisplay = display.driverData;
1674
1675       if(d3dDisplay.backBuffer)
1676       {
1677          IDirect3DDevice9_SetDepthStencilSurface(d3dSystem.d3dDevice, d3dDisplay.depthSurface);
1678          IDirect3DDevice9_SetRenderTarget(d3dSystem.d3dDevice, 0, d3dDisplay.backBuffer);
1679          IDirect3DDevice9_BeginScene(d3dSystem.d3dDevice);
1680
1681          d3dSystem.inScene = true;
1682       }
1683       return true;
1684    }
1685
1686    void Unlock(Display display)
1687    {
1688       DisplaySystem displaySystem = display.displaySystem;
1689       D3DSystem d3dSystem = displaySystem.driverData;
1690
1691       if(d3dSystem.inScene)
1692       {
1693          IDirect3DDevice9_EndScene(d3dSystem.d3dDevice);
1694          d3dSystem.inScene = false;
1695       }
1696    }
1697 };
1698
1699 #endif