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