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