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