ecere,ecereCOM: support Emscriptem platform. add new Emscripten interface driver.
[sdk] / ecere / src / gfx / DisplaySystem.ec
1 namespace gfx;
2
3 #if !defined(__EMSCRIPTEN__)
4 import "Mutex"
5 #endif
6 import "Display"
7
8 const String printingDocumentName;
9
10 public void SetPrintingDocumentName(const String name)
11 {
12    printingDocumentName = name;
13 }
14
15 public class DisplaySystemResPtr : struct
16 {
17    DisplaySystemResPtr prev, next;
18    Resource resource;
19 };
20
21 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
22 static void FreeTexture(NamedLink texture)
23 {
24    Bitmap bitmap = texture.data;
25    bitmap.Free();
26    delete bitmap;
27    delete texture.name;
28 }
29
30 static void FreeMaterial(Material material)
31 {
32    delete material.name;
33 }
34 #endif
35
36 public class DisplaySystem
37 {
38 public:
39    class_no_expansion;
40    ~DisplaySystem()
41    {
42 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
43       OldLink mesh;
44
45       materials.Free(Material::Free);
46       textures.Free(FreeTexture);
47       for(mesh = meshes.first; mesh; mesh = mesh.next)
48          ((Mesh)mesh.data).Free(0);
49       meshes.Free(null);
50 #endif
51
52       if(driverData)
53          driver.DestroyDisplaySystem(this);
54
55       if(driver.displaySystem == this)
56          driver.displaySystem = null;
57    }
58
59    bool Create(const char * driverName, void * window, bool fullScreen)
60    {
61       bool result = false;
62       subclass(DisplayDriver) displayDriver = GetDisplayDriver(driverName);
63       if(displayDriver)
64       {
65          flags.fullScreen = fullScreen;
66          this.window = window;
67          if(displayDriver.CreateDisplaySystem(this))
68             result = true;
69
70          driver = displayDriver;
71          if(!result)
72          {
73             // LogErrorCode(GERR_DISPLAY_INIT_FAILED, driver);
74             displayDriver.displaySystem = null;
75          }
76          else if(!displayDriver.displaySystem)
77          {
78             displayDriver.displaySystem = this;
79          }
80       }
81       return result;
82    }
83
84    Font LoadFont(const char * faceName, float size, FontFlags flags)
85    {
86       Font result = null;
87       subclass(DisplayDriver) driver = this ? this.driver : ((subclass(DisplayDriver))class(LFBDisplayDriver));
88       char * string = CopyString(faceName);
89       char *fonts[32];
90       if(string)
91       {
92          int numFonts = TokenizeWith(string, 32, fonts, ",", true);
93          int c;
94          for(c = 0; c<numFonts; c++)
95          {
96             TrimLSpaces(fonts[c],fonts[c]);
97             TrimRSpaces(fonts[c],fonts[c]);
98             if((result = driver.LoadFont(this, fonts[c], size, flags)))
99             {
100                break;
101             }
102          }
103          delete string;
104       }
105       return result;
106    }
107
108    void UnloadFont(Font font)
109    {
110       subclass(DisplayDriver) driver = this ? this.driver : ((subclass(DisplayDriver))class(LFBDisplayDriver));
111       driver.UnloadFont(this, font);
112    }
113
114    void FontExtent(Font font, const char * text, int len, int * width, int * height)
115    {
116       if(this && text)
117          driver.FontExtent(this, font, text, len, width, height);
118       else
119       {
120          if(width) *width = 0;
121          if(height) *height = 0;
122       }
123    }
124
125    void * LoadResource(Resource resource)
126    {
127       DisplaySystemResPtr res;
128       for(res = resources.first; res; res = res.next)
129       {
130          Resource existing = res.resource;
131
132          if(existing._class == resource._class)
133          {
134             if(resource.OnCompare(existing) == 0)
135                break;
136          }
137       }
138       if(!res)
139       {
140          // res = DisplaySystemResPtr { resource = new classof(resource) };
141          res = DisplaySystemResPtr { resource = eInstance_New(resource._class) };
142          resources.Add(res);
143
144          // This will load e.g. the Bitmap *
145          res.resource.Load(resource, this);
146       }
147       // This would copy e.g. the Bitmap *
148       incref res.resource;
149       resource.Reference(res.resource);
150
151       return res;
152    }
153
154    void UnloadResource(Resource resource, DisplaySystemResPtr res)
155    {
156       // This would clear e.g. the Bitmap *
157       resource.Dereference();
158       if(res)
159       {
160          if(res.resource._refCount == 1)
161          {
162             delete res.resource;
163             resources.Delete(res);
164          }
165          else
166             res.resource._refCount--;
167       }
168    }
169
170    bool Lock()
171    {
172       bool result = false;
173 #if !defined(__EMSCRIPTEN__)
174       mutex.Wait();
175 #endif
176
177       if(!current)
178          result = driver.LockSystem(this);
179       else
180          result = true;
181       current++;
182       return result;
183    }
184
185    void Unlock(void)
186    {
187       current--;
188       if(!current)
189          driver.UnlockSystem(this);
190
191 #if !defined(__EMSCRIPTEN__)
192       mutex.Release();
193 #endif
194    }
195 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
196    // --- Materials List Management ---
197
198    Material AddNamedMaterial(const char * name)
199    {
200       Material material = materials.FindName(name, false);
201       if(!material)
202       {
203          material = Material { };
204          if(material)
205          {
206             material.name = CopyString(name);
207             if(name)
208                materials.AddName(material);
209             else
210                materials.Add(material);
211          }
212       }
213       return material;
214    }
215
216    bool AddMaterial(Material material)
217    {
218       if(material.name)
219          materials.AddName(material);
220       else
221          materials.Add(material);
222       return true;
223    }
224
225    Material GetMaterial(const char * name)
226    {
227       return materials.FindName(name, false);
228    }
229
230    bool RemoveMaterial(Material material)
231    {
232       delete material.name;
233       materials.Delete(material);
234       return true;
235    }
236
237    void ClearMaterials()
238    {
239       materials.Free(FreeMaterial);
240    }
241
242    // --- Textures List Management ---
243
244    NamedLink AddTexture(const char * name, Bitmap bitmap)
245    {
246       NamedLink item { };
247       if(item)
248       {
249          item.data = bitmap;
250          incref bitmap;
251          item.name = new char[strlen(name) + 1];
252          strcpy(item.name, name);
253          textures.AddName(item);
254       }
255       return item;
256    }
257
258    Bitmap GetTexture(const char * name)
259    {
260       return textures.FindNamedLink(name, false);
261    }
262
263    bool RemoveTexture(const char * name)
264    {
265       NamedLink item = textures.FindName(name, false);
266       if(item)
267       {
268          FreeTexture(item);
269          textures.Delete(item);
270          return true;
271       }
272       return false;
273    }
274
275    void ClearTextures()
276    {
277       textures.Free(FreeTexture);
278    }
279
280    // --- Meshes List Management ---
281
282    OldLink AddMesh(Mesh mesh)
283    {
284       if(this)
285       {
286          OldLink item { };
287          if(item)
288          {
289             item.data = mesh;
290             mesh.displaySystem = this;
291             meshes.Add(item);
292          }
293          return item;
294       }
295       return null;
296    }
297
298    bool RemoveMesh(Mesh mesh)
299    {
300       OldLink item = meshes.FindLink(mesh);
301       if(item)
302       {
303          mesh.Free(0);
304          meshes.Delete(item);
305          return true;
306       }
307       return false;
308    }
309
310    void ClearMeshes()
311    {
312       OldLink mesh;
313       for(mesh = meshes.first; mesh; mesh = mesh.next)
314          ((Mesh)mesh.data).Free(0);
315       meshes.Free(null);
316    }
317 #endif
318
319 private:
320    subclass(DisplayDriver) driver;
321    void * data;
322    void * window;
323    public PixelFormat pixelFormat;
324    public DisplayFlags flags;
325    int numDisplays;
326
327    OldList resources;
328
329 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
330    // This will all go in resources
331    OldList materials;
332    OldList textures;
333    OldList meshes;
334 #endif
335
336    void * driverData;
337    int current;
338 #if !defined(__EMSCRIPTEN__)
339    Mutex mutex { };
340 #endif
341 };