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