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