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