ecere/gfx/drivers/OpenGL: Shaders improvements; GLCapabilities Tweaks
[sdk] / ecere / src / gfx / drivers / OpenGLDisplayDriver.ec
1 #if defined(__WIN32__) || defined(__unix__) || defined(__APPLE__)
2
3 // #define DIAGNOSTICS
4 #if defined(_DEBUG) && !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
5  #define GL_DEBUGGING
6 #endif
7
8 import "Display"
9
10 import "glab"
11 import "immediate"
12 import "matrixStack"
13 import "shading"
14
15 namespace gfx::drivers;
16
17 #include "glHelpers.h"
18
19 // **********   GL PLATFORMS INCLUDES   **********
20 // UNIX
21 #if defined(__unix__) || defined(__APPLE__)
22
23    // EGL
24    #if defined(__ANDROID__) || defined(__ODROID__)
25       import "egl"
26
27       #if defined(__ANDROID__)
28          #include <android/native_activity.h>
29          #include <android/log.h>
30          #define printf(...)  ((void)__android_log_print(ANDROID_LOG_VERBOSE, "ecere-app", __VA_ARGS__))
31       #endif
32
33    // Emscripten
34    #elif defined(__EMSCRIPTEN__)
35       #define property _property
36       #define uint _uint
37
38       #include <emscripten/emscripten.h>
39       #include <emscripten/html5.h>
40
41       #undef property
42       #undef uint
43
44    // GLX
45    #elif !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
46       #define pointer _pointer
47       #define GL_GLEXT_PROTOTYPES
48
49       #define property _property
50       #define new _new
51       #define class _class
52
53       #define Window    X11Window
54       #define Cursor    X11Cursor
55       #define Font      X11Font
56       #define Display   X11Display
57       #define Time      X11Time
58       #define KeyCode   X11KeyCode
59       #define Picture   X11Picture
60       #define Glyph     X11Glyph
61       #define uint _uint
62
63       #include <X11/Xlib.h>
64       #include <X11/Xutil.h>
65       #include <GL/glx.h>
66       #include <X11/extensions/XShm.h>
67       #include <sys/ipc.h>
68       #include <sys/shm.h>
69       #include <X11/extensions/Xrender.h>
70       #include <X11/extensions/shape.h>
71
72       #undef Window
73       #undef Cursor
74       #undef Font
75       #undef Display
76       #undef Time
77       #undef KeyCode
78       #undef Picture
79       #undef Glyph
80       #undef uint
81       #undef new
82       #undef property
83       #undef class
84       #undef pointer
85
86       #if !defined(__APPLE__)
87       GLAPI void APIENTRY glLockArraysEXT (GLint first, GLsizei count);
88       GLAPI void APIENTRY glUnlockArraysEXT (void);
89       #endif
90
91       import "XInterface"
92
93       // We were using PBUFFER for alpha compositing on Linux before, but it does not seem to work, nor be required anymore.
94       // #define USEPBUFFER
95
96    #endif
97
98 // Apple
99 #elif defined(__APPLE__)
100    #include <OpenGl/gl.h>
101
102 // WGL
103 #elif defined(__WIN32__)
104    //#define WIN32_LEAN_AND_MEAN
105    #undef _WIN32_WINNT
106    #define _WIN32_WINNT 0x0502
107    #define String Sting_
108    #include <windows.h>
109    #undef String
110
111    #include "wglDefs.h"
112 #endif
113
114 #if defined(__WIN32__)
115 #elif !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
116 default:
117 private:
118 #endif
119
120 /*                                                            OpenGL Versions Features Quick Reference
121
122                                  | OpenGL 1.1  | OpenGL 1.5  | GL ES 1.1  |  OpenGL 2  | GL 3 (Compat) | GL 3 (Core) |  GL ES 2    |  WebGL 1   |  GL ES 3   |   WebGL 2
123    =======================================================================================================================================================================
124    glBegin()                     |      X      |      X      |     -      |     X      |       X       |      -      |      -      |     -      |     -      |     -
125    glLoadMatrix()                |      X      |      X      |     -      |     X      |       X       |      -      |      -      |     -      |     -      |     -
126    glLineWidth()                 |      X      |      X      |     -      |     X      |       X       |      -      |      -      |     -      |     -      |     -
127    glPointSize()                 |      X      |      X      |     -      |     X      |       X       |      -      |      -      |     -      |     -      |     -
128    glLineStipple()               |      X      |      X      |     -      |     X      |       X       |      -      |      -      |     -      |     -      |     -
129    glPolygonStipple()            |      X      |      X      |     -      |     X      |       X       |      -      |      -      |     -      |     -      |     -
130    glColorMaterial()             |      X      |      X      |     -      |     X      |       X       |      -      |      -      |     -      |     -      |     -
131    GL_QUADS                      |      X      |      X      |     -      |     X      |       X       |      -      |      -      |     -      |     -      |     -
132    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
133    GL_INT / GL_DOUBLE            |      X      |      X      |     -      |     X      |       X       |      X      |      -      |     -      |     -      |     -
134    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
135    GL_SELECT                     |      X      |      X      |     -      |   (Slow)   |     (Slow)    |    (Slow)   |      -      |     -      |     -      |     -
136    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
137    Non ² Textures                |      -      |      -      |     -      |     X      |       X       |      X      |      -      |     -      |     -      |     -
138    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
139    glVertexPointer()       (PTR) |      X      |      X      |     X      |     X      |       X       |      -      |      -      |     -      |     -      |     -
140    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
141    glVertexPointer()       (VBO) |      -      |      X      |     X      |     X      |       X       |      -      |      -      |     -      |     -      |     -
142    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
143    glBufferData()                |      -      |      X      |     X      |     X      |       X       |      X      |      X      |     X      |     X      |     X
144    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
145    glMapBuffer()                 |      -      |      X      |   OES x    |     X      |       X       |      X      |    OES x    |     -      |    OES x   |     -
146    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
147    glBindFramebuffer()           |      -      |      -      |   OES x    |     -      |       X       |      X      |      X      |     X      |     X      |     X
148    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
149    glVertexAttribPointer() (PTR) |      -      |      -      |     -      |     X      |       X       |      X      |      X      |     -      |     X      |     -
150    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
151    glVertexAttribPointer() (VBO) |      -      |      -      |     -      |     X      |       X       |      X      |      X      |     X      |     X      |     X
152    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
153    GLSL Version                  |      -      |      -      |     -      |    1.10    |     1.30      |    1.30     |     1.00    |    1.00    |    3.00    |    3.00
154    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
155    bool legacy          :1; //   |      X      |      X      |     -      |     X      |       X       |      -      |      -      |     -      |     -      |     -
156    bool shaders         :1; //   |      -      |      -      |     -      |     X      |       X       |      X      |      X      |     X      |     X      |     X
157    bool nonPow2Textures :1; //   |      -      |      -      |     -      |     X      |       X       |      X      |      -      |     -      |     -      |     -
158    bool vertexBuffer    :1; //   |      -      |      X      |     X      |     X      |       X       |      X      |      X      |     X      |     X      |     X
159    bool frameBuffer     :1; //   |      -      |      -      |     ~      |     -      |       X       |      X      |      X      |     X      |     X      |     X
160 // bool mapBuffer       :1; //   |      -      |      X      |     ~      |     X      |       X       |      X      |      ~      |     -      |     ~      |     -
161 */
162
163 default:
164 // Capabilities Global set to capabilities of Display being rendered to
165 GLCapabilities glcaps;
166 // Requiring Graphics Reload:
167 bool glcaps_nonPow2Textures, glcaps_vertexBuffer, glcaps_quads, glcaps_intAndDouble;
168 // Might toggle without Reload:
169 bool glcaps_shaders, glcaps_fixedFunction, glcaps_immediate, glcaps_legacy, glcaps_pointSize, glcaps_frameBuffer;
170 // bool mapBuffer;
171 private:
172
173
174 // **********   Errors and Debugging   **********
175 /*
176 void CheckGLErrors()
177 {
178    int e, nCount = 0;
179    while((e = glGetError()) && nCount++ < 10)
180       printf("GL error %d!\n", e);
181 }
182 */
183 #ifdef GL_DEBUGGING
184 #ifndef APIENTRY
185    #define APIENTRY
186 #endif
187 static void APIENTRY openglCallbackFunction(GLenum source,
188                                            GLenum type,
189                                            GLuint id,
190                                            GLenum severity,
191                                            GLsizei length,
192                                            const GLchar* message,
193                                            const void* userParam)
194 {
195    if(severity == GL_DEBUG_SEVERITY_NOTIFICATION)
196       return;
197    PrintLn("---------------------opengl-callback-start------------");
198    PrintLn("message: ", message);
199    PrintLn("type: ");
200    switch (type)
201    {
202       case GL_DEBUG_TYPE_ERROR: PrintLn("ERROR"); break;
203       case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: PrintLn("DEPRECATED_BEHAVIOR"); break;
204       case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: PrintLn("UNDEFINED_BEHAVIOR"); break;
205       case GL_DEBUG_TYPE_PORTABILITY: PrintLn("PORTABILITY"); break;
206       case GL_DEBUG_TYPE_PERFORMANCE: PrintLn("PERFORMANCE"); break;
207       case GL_DEBUG_TYPE_OTHER: PrintLn("OTHER"); break;
208    }
209
210    PrintLn("id: ", id);
211    Print("severity: ");
212    switch (severity)
213    {
214       case GL_DEBUG_SEVERITY_LOW: PrintLn("LOW"); break;
215       case GL_DEBUG_SEVERITY_MEDIUM: PrintLn("MEDIUM"); break;
216       case GL_DEBUG_SEVERITY_HIGH: PrintLn("HIGH"); break;
217       default: PrintLn("(other)");
218    }
219    PrintLn("---------------------opengl-callback-end--------------");
220 }
221
222 static void setupDebugging()
223 {
224    if(glDebugMessageCallback)
225    {
226       GLuint unusedIds = 0;
227
228       glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
229
230       glDebugMessageCallback(openglCallbackFunction, null);
231       glDebugMessageControl(GL_DONT_CARE,
232           GL_DONT_CARE,
233           GL_DONT_CARE,
234           0,
235           &unusedIds,
236           GL_TRUE);
237    }
238 }
239 #endif
240
241
242 static GLuint stippleTexture;
243 static bool stippleEnabled;
244
245                               // TOCHECK: Do we really need to pass glcaps_shaders?
246 public void glsupLineStipple( int i, unsigned short j )
247 {
248    uint texture[1*16];
249    int x;
250    for(x = 0; x < 16; x++)
251    {
252       bool v = (j & (1 << x)) != 0;
253       texture[x] = v ? 0xFFFFFFFF : 0;
254    }
255    if(!stippleTexture)
256       glGenTextures(1, &stippleTexture);
257    glBindTexture(GL_TEXTURE_2D, stippleTexture);
258    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
259
260    // TOOD: Special shading code for stippling?
261    GLSetupTexturing(true);
262    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
263    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
264    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
265    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
266    GLMatrixMode(GL_TEXTURE);
267    GLLoadIdentity();
268    //glTranslated(1.0/backAttrib->texW/2.0f, 1.0/backAttrib->texH/2.0f, 0.0f);
269    GLScaled(i/16.0, 1, 1.0f);
270    GLTranslated(0.5, 0.5, 0);
271    GLMatrixMode(MatrixMode::projection);
272 }
273
274    // Exported to build _GLES version...
275    public void glsupLightModeli( unsigned int pname, int param )
276    {
277 #if ENABLE_GL_FFP
278       if(pname == GL_LIGHT_MODEL_TWO_SIDE)
279          glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, param);
280 #endif
281    }
282
283 #ifdef _GLES
284    void glFogi( unsigned int pname, int param ) { }
285    void glPolygonMode( unsigned int i, unsigned int j ) { }
286    void glBlendFuncSeparate(int a, int b, int c, int d)
287    {
288       glBlendFunc(a, b);
289    }
290
291 #endif
292
293 #if defined(_GLES) || defined(_GLES2)
294 void glClearDepth( double depth ) { glClearDepthf((float)depth); }
295 #endif
296
297 #if !ENABLE_GL_SELECT
298
299 // *** Picking won't be supported for now ***
300 void glPushName( unsigned int i ) { }
301 void glLoadName( unsigned int i ) { }
302 void glPopName() { }
303
304 #endif
305
306 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
307 static inline uint getPrimitiveType(RenderPrimitiveType type)
308 {
309    static int primitiveTypes[RenderPrimitiveType] =
310    {
311       GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN,
312       GLIMTKMode::quads,
313       GLIMTKMode::quadStrip,
314       GL_LINE_STRIP
315    };
316    // NOTE: This will only work for single quads
317    return (type == quads && !glcaps_quads) ? GL_TRIANGLE_FAN : primitiveTypes[type];
318 }
319
320 public void GLSetupTexturing(bool enable)
321 {
322 #if ENABLE_GL_SHADERS
323    if(glcaps_shaders)
324       shader_texturing(enable);
325 #endif
326
327 #if ENABLE_GL_FFP
328    if(!glcaps_shaders)
329       (enable ? glEnable : glDisable)(GL_TEXTURE_2D);
330 #endif
331 }
332
333 public void GLSetupFog(bool enable)
334 {
335 #if ENABLE_GL_SHADERS
336    if(glcaps_shaders)
337       shader_fog(enable);
338 #endif
339
340 #if ENABLE_GL_FFP
341    if(!glcaps_shaders)
342       (enable ? glEnable : glDisable)(GL_FOG);
343 #endif
344 }
345
346 bool lightingEnabled;
347
348 public void GLSetupLighting(bool enable)
349 {
350    lightingEnabled = enable;
351 #if ENABLE_GL_SHADERS
352    if(glcaps_shaders)
353       shader_lighting(enable);
354 #endif
355
356 #if ENABLE_GL_FFP
357    if(!glcaps_shaders)
358       (enable ? glEnable : glDisable)(GL_LIGHTING);
359 #endif
360 }
361 #endif
362
363 static int displayWidth, displayHeight;
364
365 #define GL_CLAMP_TO_EDGE 0x812F
366
367 static bool useSingleGLContext = false;
368 class OGLDisplay : struct
369 {
370 #if defined(__WIN32__)
371    HDC hdc;
372    HGLRC glrc;
373
374    HBITMAP memBitmap;
375    HDC memDC;
376    byte * picture;
377    uint stride;
378    void * pBuffer;
379    /*
380    int imageBuffers[2];
381    byte * pboMemory1, * pboMemory2;
382    */
383 #elif !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
384    GLXContext glContext;
385
386    Pixmap pixmap;
387    XShmSegmentInfo shminfo;
388    XImage * image;
389    XShmSegmentInfo shminfoShape;
390    XImage * shapeImage;
391    byte * picture;
392    uint stride;
393    GLXPbuffer pBuffer;
394    X11Picture windowPicture;
395    X11Picture pixmapPicture;
396    Pixmap shapePixmap;
397    X11Picture shapePicture;
398 #endif
399
400    GLCapabilities capabilities, originalCapabilities;
401
402    ColorAlpha * flippingBuffer;
403    int flipBufH, flipBufW;
404    bool depthWrite;
405    int x, y;
406 };
407
408 class OGLSystem : struct
409 {
410    int maxTextureSize;
411    bool loadingFont;
412 #if ENABLE_GL_SHADERS
413    int shadingProgram;
414    int vertexShader;
415    int fragmentShader;
416 #endif
417 #if defined(__WIN32__)
418    PIXELFORMATDESCRIPTOR pfd;
419    int format;
420    HDC hdc;
421    HGLRC glrc;
422    HWND hwnd;
423 #elif defined(__EMSCRIPTEN__)
424    EMSCRIPTEN_WEBGL_CONTEXT_HANDLE glc;
425 #elif !defined(__ANDROID__) && !defined(__ODROID__)
426    XVisualInfo * visualInfo;
427    GLXContext glContext;
428    GLXDrawable glxDrawable;
429 #endif
430    GLCapabilities capabilities;
431 };
432
433 class OGLSurface : struct
434 {
435    Font font;
436    bool opaqueText;
437    int xOffset;
438    bool writingText;
439    bool writingOutline;
440
441    float foreground[4], background[4], bitmapMult[4];
442 } OGLSurface;
443
444 class OGLMesh : struct
445 {
446    GLAB vertices;
447    GLAB normals;
448    GLAB texCoords;
449    GLAB texCoords2;
450    GLAB colors;
451 };
452
453 class OGLIndices : struct
454 {
455    uint16 * indices;
456    GLEAB buffer;
457    uint nIndices;
458 };
459
460 int current;
461 void * previous;
462
463 #if defined(__WIN32__)
464 static HGLRC winCreateContext(HDC hdc, int * contextVersion, bool * isCompatible)
465 {
466    HGLRC result = 0;
467    if(wglCreateContextAttribsARB)
468    {
469       int versions[12][2] =
470       {
471          { 4, 5 }, { 4, 4 }, { 4, 3 }, { 4, 2 }, { 4, 1 }, { 4, 0 },
472                              { 3, 3 }, { 3, 2 }, { 3, 1 }, { 3, 0 },
473                                                  { 2, 1 }, { 2, 0 }
474       };
475
476       bool tryingCompat = true;
477       int v = 0;
478       while(!result)
479       {
480          for(v = 0; !result && v < sizeof(versions) / sizeof(versions[0]); v++)
481          {
482             int v0 = versions[v][0], v1 = versions[v][1];
483             if(!tryingCompat || v0 >= 3)
484             {
485                bool coreNotion = v0 > 3 || (v0 == 3 && v1 >= 3);
486                int attribs[] =
487                {
488                   WGL_CONTEXT_MAJOR_VERSION_ARB, v0, WGL_CONTEXT_MINOR_VERSION_ARB, v1,
489          #ifdef _DEBUG
490                   WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB,
491          #endif
492                   coreNotion ? WGL_CONTEXT_PROFILE_MASK_ARB : 0, coreNotion ? (tryingCompat ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : WGL_CONTEXT_CORE_PROFILE_BIT_ARB) : 0,
493                   0,0
494                };
495                result = wglCreateContextAttribsARB(hdc, null, attribs);
496                if(result)
497                {
498                   if(contextVersion) *contextVersion = v0;
499                   if(isCompatible)   *isCompatible = tryingCompat || !coreNotion;
500                }
501             }
502          }
503          if(tryingCompat)
504             tryingCompat = false;
505          else
506             break;
507       }
508    }
509    if(!result)
510    {
511       if(contextVersion) *contextVersion = 1;
512       if(isCompatible)   *isCompatible = true;
513       result = wglCreateContext(hdc);
514    }
515    return result;
516 }
517 #endif
518
519 class OpenGLDisplayDriver : DisplayDriver
520 {
521    class_property(name) = "OpenGL";
522
523    bool LockSystem(DisplaySystem displaySystem)
524    {
525 #if defined(__EMSCRIPTEN__)
526       OGLSystem oglSystem = displaySystem.driverData;
527       emscripten_webgl_make_context_current(oglSystem.glc);
528 #elif !defined(__ANDROID__) && !defined(__ODROID__)
529       OGLSystem oglSystem = displaySystem.driverData;
530       if(useSingleGLContext) return true;
531    #if defined(__WIN32__)
532       wglMakeCurrent(oglSystem.hdc, oglSystem.glrc);
533    #elif defined(__unix__) || defined(__APPLE__)
534       //if(previous) return true;
535       // printf("Making SYSTEM current\n");
536       glXMakeCurrent(xGlobalDisplay, (GLXDrawable)oglSystem.glxDrawable, oglSystem.glContext);
537       //previous = oglSystem.glContext;
538    #endif
539 #endif
540       GLABBindBuffer(GL_ARRAY_BUFFER, 0);
541       GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
542       return true;
543    }
544
545    void UnlockSystem(DisplaySystem displaySystem)
546    {
547       if(useSingleGLContext) return;
548    #if defined(__WIN32__)
549       wglMakeCurrent(null, null);
550    #elif defined(__unix__) || defined(__APPLE__)
551       // printf("Making NULL current\n");
552       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
553       #else
554       glXMakeCurrent(xGlobalDisplay, None, null);
555       #endif
556       // previous = null;
557    #endif
558    }
559
560    bool Lock(Display display)
561    {
562 #if !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
563       OGLDisplay oglDisplay = display.driverData;
564       if(useSingleGLContext) return true;
565    #if defined(__WIN32__)
566       wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
567    #elif defined(__unix__) || defined(__APPLE__)
568       // if(previous) glXMakeCurrent(xGlobalDisplay, None, null);
569       // printf("   Making DISPLAY current\n");
570       glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext);
571    #endif
572 #endif
573       GLABBindBuffer(GL_ARRAY_BUFFER, 0);
574       GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
575       return true;
576    }
577
578    void Unlock(Display display)
579    {
580       if(useSingleGLContext) return;
581       //printf("   Making NULL current\n");
582       //glXMakeCurrent(xGlobalDisplay, None, null);
583       // if(previous)
584          LockSystem(display.displaySystem);
585    }
586
587    void DestroyDisplay(Display display)
588    {
589       OGLDisplay oglDisplay = display.driverData;
590
591       if(oglDisplay)
592       {
593    #if defined(__WIN32__)
594          wglMakeCurrent( null, null );
595
596          if(oglDisplay.glrc)
597             wglDeleteContext(oglDisplay.glrc);
598
599          if(oglDisplay.hdc && oglDisplay.pBuffer)
600             wglReleasePbufferDCARB(oglDisplay.pBuffer, oglDisplay.hdc);
601
602          if(oglDisplay.pBuffer)
603             wglDestroyPbufferARB(oglDisplay.pBuffer);
604
605          if(oglDisplay.hdc)
606             ReleaseDC(display.window, oglDisplay.hdc);
607
608          if(oglDisplay.memDC) DeleteDC(oglDisplay.memDC);
609          if(oglDisplay.memBitmap) DeleteObject(oglDisplay.memBitmap);
610
611    #elif defined(__unix__) || defined(__APPLE__)
612       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
613       #else
614          if(oglDisplay.shapePixmap)
615             XFreePixmap(xGlobalDisplay, oglDisplay.shapePixmap);
616          if(oglDisplay.pixmap)
617             XFreePixmap(xGlobalDisplay, oglDisplay.pixmap);
618          if(oglDisplay.image)
619          {
620             if(oglDisplay.shminfoShape.shmid != -1)
621             {
622                XShmDetach(xGlobalDisplay, &oglDisplay.shminfo);
623                if(oglDisplay.shminfo.shmaddr != (void *)-1)
624                   shmdt(oglDisplay.shminfo.shmaddr);
625                shmctl(oglDisplay.shminfo.shmid, IPC_RMID, 0);
626             }
627          }
628          if(oglDisplay.shapeImage)
629          {
630             if(oglDisplay.shminfoShape.shmid != -1)
631             {
632                XShmDetach(xGlobalDisplay, &oglDisplay.shminfoShape);
633                if(oglDisplay.shminfoShape.shmaddr != (void *)-1)
634                   shmdt(oglDisplay.shminfoShape.shmaddr);
635                shmctl(oglDisplay.shminfoShape.shmid, IPC_RMID, 0);
636             }
637             XDestroyImage(oglDisplay.shapeImage);
638             oglDisplay.shapeImage = None;
639          }
640
641          glXMakeCurrent(xGlobalDisplay, None, null);
642
643          if(oglDisplay.glContext)
644             glXDestroyContext(xGlobalDisplay, oglDisplay.glContext);
645       #endif
646    #endif
647          delete oglDisplay.flippingBuffer;
648          delete oglDisplay;
649          display.driverData = null;
650       }
651    }
652
653 #if !defined(__EMSCRIPTEN__)
654    void ::CheckCapabilities(OGLSystem oglSystem, OGLDisplay oglDisplay)
655    {
656       GLCapabilities capabilities;
657 #if !defined(_GLES2)
658       const char * extensions = (const char *)glGetString(GL_EXTENSIONS);
659 #endif
660 #ifdef DIAGNOSTICS
661       printf("extensions: %s\n", extensions);
662 #endif
663
664       glGetIntegerv(GL_MAX_TEXTURE_SIZE, &oglSystem.maxTextureSize);
665
666 #if defined(_GLES)
667       capabilities = { fixedFunction = true, vertexBuffer = true, pointSize = true, frameBuffer = extensions && strstr(extensions, "GL_OES_framebuffer_object") };
668 #elif defined(_GLES2)
669       capabilities = { glcaps_shaders = true, vertexBuffer = true, pointSize = true, frameBuffer = true };
670 #else
671       capabilities =
672       {
673          nonPow2Textures = extensions && strstr(extensions, "GL_ARB_texture_non_power_of_two");
674          intAndDouble = true;
675          pointSize = true;
676 #if ENABLE_GL_LEGACY
677          legacy         = glBegin != null;
678          immediate      = glBegin != null;
679          fixedFunction  = glBegin != null;
680          quads          = glBegin != null;
681 #endif
682 #if ENABLE_GL_SHADERS
683          shaders = glCreateProgram != null;
684 #endif
685 #if ENABLE_GL_FBO
686          shaders = glBindFramebuffer != null;
687 #endif
688          vertexBuffer = glBindBuffer != null;
689          // mapBuffer = glMapBuffer != null;
690       };
691 #endif
692
693 #ifdef DIAGNOSTICS
694       PrintLn("max texture size: ", oglSystem.maxTextureSize);
695 #endif
696       if(oglDisplay) oglDisplay.capabilities = capabilities;
697       if(oglSystem)  oglSystem.capabilities = capabilities;
698    }
699 #endif
700
701    bool CreateDisplaySystem(DisplaySystem displaySystem)
702    {
703       bool result = false;
704       OGLSystem oglSystem = displaySystem.driverData = OGLSystem { };
705
706 #ifdef _GLES
707       oglSystem.capabilities = { fixedFunction = true, vertexBuffer = true, frameBuffer = true, pointSize = true };
708 #elif defined(_GLES2)
709       oglSystem.capabilities = { shaders = true, vertexBuffer = true, frameBuffer = true, pointSize = true };
710 #else
711       oglSystem.capabilities = { shaders = true, fixedFunction = true, immediate = true, legacy = true, pointSize = true, quads = true, intAndDouble = true, vertexBuffer = true, frameBuffer = true, nonPow2Textures = true };
712 #endif
713
714 #ifdef DIAGNOSTICS
715       PrintLn("OpenGL driver's CreateDisplaySystem()");
716 #endif
717
718    #ifdef __WIN32__
719       oglSystem.hwnd = CreateWindow("static", null, 0,0,0,0,0,null,null,null,null);
720
721       oglSystem.hdc = GetDC(oglSystem.hwnd);
722       if(oglSystem.hdc)
723       {
724
725          oglSystem.pfd.nSize = (short)sizeof(oglSystem.pfd);
726          oglSystem.pfd.nVersion = 1;
727          oglSystem.pfd.dwFlags = PFD_DRAW_TO_WINDOW /*PFD_DRAW_TO_BITMAP*/ | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
728          oglSystem.pfd.iPixelType = PFD_TYPE_RGBA;
729          oglSystem.pfd.cColorBits = 24;
730          oglSystem.pfd.cAlphaBits = 8;
731          oglSystem.pfd.cDepthBits = 24;
732          oglSystem.pfd.iLayerType = PFD_MAIN_PLANE;
733
734          oglSystem.format = ChoosePixelFormat(oglSystem.hdc, &oglSystem.pfd);
735          DescribePixelFormat(oglSystem.hdc, oglSystem.format, sizeof(oglSystem.pfd), &oglSystem.pfd);
736
737          if(oglSystem.pfd.cColorBits > 8)
738          {
739             SetPixelFormat(oglSystem.hdc, oglSystem.format, &oglSystem.pfd);
740             oglSystem.glrc = wglCreateContext(oglSystem.hdc);
741             if(oglSystem.glrc)
742             {
743                wglMakeCurrent(oglSystem.hdc, oglSystem.glrc);
744
745                wglChoosePixelFormatARB = (void *) wglGetProcAddress("wglChoosePixelFormatARB");
746                wglGetExtensionsStringARB = (void *)wglGetProcAddress("wglGetExtensionsStringARB");
747                wglCreatePbufferARB = (void *)wglGetProcAddress("wglCreatePbufferARB");
748                wglGetPbufferDCARB = (void *)wglGetProcAddress("wglGetPbufferDCARB");
749                wglQueryPbufferARB = (void *)wglGetProcAddress("wglQueryPbufferARB");
750                wglDestroyPbufferARB = (void *)wglGetProcAddress("wglDestroyPbufferARB");
751                wglReleasePbufferDCARB = (void *)wglGetProcAddress("wglReleasePbufferDCARB");
752                wglBindTexImageARB = (void *)wglGetProcAddress("wglBindTexImageARB");
753                wglReleaseTexImageARB = (void *)wglGetProcAddress("wglReleaseTexImageARB");
754                wglSwapIntervalEXT = (void *)wglGetProcAddress("wglSwapIntervalEXT");
755                wglCreateContextAttribsARB = (void *)wglGetProcAddress("wglCreateContextAttribsARB");
756
757                glLockArraysEXT = (void *) wglGetProcAddress("glLockArraysEXT" );
758                glUnlockArraysEXT = (void *) wglGetProcAddress("glUnlockArraysEXT");
759
760                // eSystem_LoggingMode(LOG_MSGBOX, null);
761
762                if(wglChoosePixelFormatARB)
763                {
764                   int pixelFormat;
765                   int valid;
766                   int numFormats;
767                   float fAttributes[] = {0,0};
768                   int iAttributes[] =
769                   {
770                      WGL_DRAW_TO_WINDOW_ARB,GL_TRUE,
771                      WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
772                      WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
773                      WGL_COLOR_BITS_ARB,24,
774                      WGL_ALPHA_BITS_ARB,8,
775                      WGL_DEPTH_BITS_ARB,16,
776                      WGL_STENCIL_BITS_ARB,0,
777                      WGL_DOUBLE_BUFFER_ARB,GL_TRUE,
778                      WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
779                      WGL_SAMPLES_ARB, 4,                  // Check For 4x Multisampling
780                      0,0
781                   };
782
783                   //Log("Found wglChoosePixelFormatARB\n");
784
785                   valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
786                   if(!valid || !numFormats)
787                   {
788                      //Log("Can't find 4x multi sampling\n");
789                      iAttributes[19] = 2;
790                      valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
791                      if(!valid || !numFormats)
792                      {
793                         // Log("Can't find 2x multi sampling\n");
794                         iAttributes[16] = 0;
795                         iAttributes[17] = 0;
796                         valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
797                      }
798                   }
799                   if(valid && numFormats)
800                   {
801                      oglSystem.format = pixelFormat;
802                      wglMakeCurrent(null, null);
803                      wglDeleteContext(oglSystem.glrc);
804
805                      // *** DescribePixelFormat does not support WGL pixel formats! ***
806                      //DescribePixelFormat(oglSystem.hdc, oglSystem.format, sizeof(oglSystem.pfd), &oglSystem.pfd);
807                      SetPixelFormat(oglSystem.hdc, oglSystem.format, &oglSystem.pfd);
808                      //Log("Successfully set pixel format\n");
809
810 #ifdef DIAGNOSTICS
811                      PrintLn("winCreateContext()");
812 #endif
813                      oglSystem.glrc = winCreateContext(oglSystem.hdc, null, null);
814 #ifdef DIAGNOSTICS
815                      PrintLn("wglMakeCurrent()");
816 #endif
817                      if(oglSystem.glrc)
818                         wglMakeCurrent(oglSystem.hdc, oglSystem.glrc);
819                   }
820                }
821                /*else
822                   eSystem_Logf("Can't find wglChoosePixelFormatARB\n");*/
823
824                result = true;
825
826                wglMakeCurrent(null, null);
827
828                //eSystem_DumpErrors(true);
829             }
830          }
831       }
832    #elif defined(__unix__) || defined(__APPLE__)
833       #if defined(__ANDROID__) || defined(__ODROID__)
834          #if defined(__ANDROID__)
835          egl_init_display(guiApp.desktop.windowHandle);
836          #elif defined(__ODROID__)
837          egl_init_display((uint)displaySystem.window);
838          #endif
839          CheckCapabilities(oglSystem, null);
840
841          // TODO: Clean this up? Needed here?
842          GLEnableClientState(VERTICES);
843          /*
844          // Initialize GL state.
845          glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
846          glEnable(GL_CULL_FACE);
847          glShadeModel(GL_SMOOTH);
848          glDisable(GL_DEPTH_TEST);
849          */
850          glDisable(GL_CULL_FACE);
851          glDisable(GL_DEPTH_TEST);
852
853          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
854          glEnable(GL_BLEND);
855
856          matrixStack[0][0].Identity();
857          matrixStack[1][0].Identity();
858          matrixStack[2][0].Identity();
859
860          GLMatrixMode(GL_MODELVIEW);
861          GLScaled(1.0, 1.0, -1.0);
862          GLMatrixMode(GL_PROJECTION);
863          glShadeModel(GL_FLAT);
864
865 #if !defined(_GLES)
866          if(!glcaps_shaders)
867             GLLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
868 #endif
869          glFogi(GL_FOG_MODE, GL_EXP);
870          glFogf(GL_FOG_DENSITY, 0);
871          glEnable(GL_NORMALIZE);
872          glDepthFunc(GL_LESS);
873          glClearDepth(1.0);
874          glDisable(GL_MULTISAMPLE);
875
876          glViewport(0,0,eglWidth,eglHeight);
877          GLLoadIdentity();
878          GLOrtho(0,eglWidth,eglHeight,0,0.0,1.0);
879
880          glabCurArrayBuffer = 0;
881          glabCurElementBuffer = 0;
882
883          result = true;
884       #elif defined(__EMSCRIPTEN__)
885          {
886             EmscriptenWebGLContextAttributes attribs = { 0 };
887             attribs.depth = 1;
888             attribs.antialias = 1;
889
890             /*
891               EM_BOOL alpha;
892               EM_BOOL depth;
893               EM_BOOL stencil;
894               EM_BOOL antialias;
895               EM_BOOL premultipliedAlpha;
896               EM_BOOL preserveDrawingBuffer;
897               EM_BOOL preferLowPowerToHighPerformance;
898               EM_BOOL failIfMajorPerformanceCaveat;
899               int majorVersion;
900               int minorVersion;
901               EM_BOOL enableExtensionsByDefault;
902               */
903
904             emscripten_webgl_init_context_attributes(&attribs);
905             oglSystem.maxTextureSize = 16384;
906             oglSystem.glc = emscripten_webgl_create_context("canvas", &attribs);
907             if(emscripten_webgl_make_context_current(oglSystem.glc) == EMSCRIPTEN_RESULT_SUCCESS)
908                result = true;
909
910             /*glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
911             glEnable(GL_BLEND);*/
912          }
913       #else
914       {
915          X11Window root = RootWindow( xGlobalDisplay, DefaultScreen( xGlobalDisplay ) );
916          XSetWindowAttributes attr;
917          unsigned long mask;
918
919          int attrList[] =
920          {
921       #ifndef ECERE_MINIGLX
922             GLX_USE_GL, GLX_DEPTH_SIZE, 1,
923       #endif
924             GLX_RGBA,
925             GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
926             GLX_DOUBLEBUFFER,
927             None
928          };
929          oglSystem.visualInfo = glXChooseVisual( xGlobalDisplay,  DefaultScreen( xGlobalDisplay ), attrList );
930          attr.background_pixel = 0;
931          attr.border_pixel = 0;
932          attr.colormap = XCreateColormap( xGlobalDisplay, root, oglSystem.visualInfo->visual, AllocNone);
933          attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
934          mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
935
936          oglSystem.glxDrawable = XCreateWindow( xGlobalDisplay, root, 0, 0, 1, 1, 0, oglSystem.visualInfo->depth, InputOutput,
937             oglSystem.visualInfo->visual, mask, &attr );
938       }
939       if(oglSystem.visualInfo)
940       {
941          oglSystem.glContext = glXCreateContext(xGlobalDisplay, oglSystem.visualInfo, null, True);
942          if(oglSystem.glContext)
943          {
944             glXMakeCurrent(xGlobalDisplay, oglSystem.glxDrawable, oglSystem.glContext);
945             glXMakeCurrent(xGlobalDisplay, None, null);
946             result = true;
947          }
948       }
949       #endif
950    #endif
951
952       displaySystem.flags.alpha = true;
953       displaySystem.flags.flipping = true;
954       displaySystem.pixelFormat = pixelFormat888;
955       return result;
956    }
957
958    void DestroyDisplaySystem(DisplaySystem displaySystem)
959    {
960       OGLSystem oglSystem = displaySystem.driverData;
961       if(stippleTexture)
962       {
963          glDeleteTextures(1, &stippleTexture);
964          stippleTexture = 0;
965       }
966
967 #if ENABLE_GL_SHADERS
968       if(oglSystem.shadingProgram)
969          glDeleteProgram(oglSystem.shadingProgram);
970       if(oglSystem.fragmentShader)
971          glDeleteShader(oglSystem.fragmentShader);
972       if(oglSystem.vertexShader)
973          glDeleteShader(oglSystem.vertexShader);
974 #endif
975
976       glimtkTerminate();
977
978    #if defined(__WIN32__)
979       wglMakeCurrent( null, null );
980
981       if(oglSystem.glrc)
982          wglDeleteContext(oglSystem.glrc);
983
984       if(oglSystem.hdc)
985          ReleaseDC(oglSystem.hwnd, oglSystem.hdc);
986       DestroyWindow(oglSystem.hwnd);
987
988    #elif defined(__unix__) || defined(__APPLE__)
989       #if defined(__ANDROID__) || defined(__ODROID__)
990          egl_term_display();
991       #elif defined(__EMSCRIPTEN__)
992          emscripten_webgl_destroy_context(oglSystem.glc);
993       #else
994       if(oglSystem.visualInfo)
995       {
996    #ifdef   ECERE_MINIGLX
997          __miniglx_XFree(oglSystem.visualInfo);
998    #else
999          XFree(oglSystem.visualInfo);
1000    #endif
1001       }
1002
1003       if(oglSystem.glxDrawable)
1004       {
1005          XDestroyWindow(xGlobalDisplay, oglSystem.glxDrawable);
1006          oglSystem.glxDrawable = 0;
1007       }
1008       #endif
1009    #endif
1010       delete oglSystem;
1011    }
1012
1013    /*static */bool ::initialDisplaySetup(Display display)
1014    {
1015       OGLDisplay oglDisplay = display.driverData;
1016       OGLSystem oglSystem = display.displaySystem.driverData;
1017       bool result = true;
1018
1019       oglSystem.capabilities = oglDisplay.capabilities;
1020       SETCAPS(oglDisplay.capabilities);
1021
1022 #if ENABLE_GL_SHADERS
1023       if(glcaps_shaders)
1024          loadShaders(display.displaySystem, "<:ecere>shaders/fixed.vertex", "<:ecere>shaders/fixed.frag");
1025 #if ENABLE_GL_LEGACY
1026       else
1027       {
1028          glDisableVertexAttribArray(GLBufferContents::color);
1029          glDisableVertexAttribArray(GLBufferContents::normal);
1030          glDisableVertexAttribArray(GLBufferContents::texCoord);
1031          glDisableVertexAttribArray(GLBufferContents::vertex);
1032          glUseProgram(0);
1033       }
1034 #endif
1035
1036 #endif
1037       GLEnableClientState(VERTICES);
1038
1039       GLABBindBuffer(GL_ARRAY_BUFFER, 0);
1040       GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1041
1042 #if defined(__WIN32__)
1043       if(glBlendFuncSeparate)
1044          glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1045       else
1046          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1047 #else
1048       glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1049 #endif
1050       glEnable(GL_BLEND);
1051
1052       GLMatrixMode(MatrixMode::texture);
1053       GLLoadIdentity();
1054
1055       GLMatrixMode(MatrixMode::modelView);
1056       GLLoadIdentity(); // For setting up GLES stack
1057       GLScaled(1.0, 1.0, -1.0);
1058       // glTranslatef(0.375f, 0.375f, 0.0f);
1059       // glTranslatef(-0.625f, -0.625f, 0.0f);
1060       GLMatrixMode(MatrixMode::projection);
1061       GLLoadIdentity();
1062       if(display.width && display.height)
1063          GLOrtho(0,display.width,display.height,0,0.0,1.0);
1064
1065 #if ENABLE_GL_FFP
1066       if(!glcaps_shaders)
1067       {
1068          glShadeModel(GL_FLAT);
1069          /*
1070          #define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
1071          GLLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1072          */
1073 #if !defined(_GLES)
1074          GLLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1075 #endif
1076          glFogi(GL_FOG_MODE, GL_EXP);
1077          glFogf(GL_FOG_DENSITY, 0);
1078          glEnable(GL_NORMALIZE);
1079       }
1080 #endif
1081       glDepthFunc(GL_LESS);
1082       glClearDepth(1.0);
1083 #if !defined(__EMSCRIPTEN__)
1084       glDisable(GL_MULTISAMPLE);
1085 #endif
1086
1087 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
1088       display.ambient = Color { 50,50,50 };
1089 #endif
1090       return result;
1091    }
1092
1093    bool CreateDisplay(Display display)
1094    {
1095       bool result = false;
1096       OGLDisplay oglDisplay = display.driverData;
1097       OGLSystem oglSystem = display.displaySystem.driverData;
1098
1099       if(!oglDisplay)
1100          oglDisplay = display.driverData = OGLDisplay { };
1101       oglDisplay.capabilities = oglSystem.capabilities;
1102
1103 #if defined(__WIN32__) || defined(USEPBUFFER)
1104       if(!display.alphaBlend)
1105 #endif
1106       {
1107 #if defined(__WIN32__)
1108          oglDisplay.hdc = GetDC(display.window);
1109          SetPixelFormat(oglDisplay.hdc, oglSystem.format, &oglSystem.pfd);
1110          if((oglDisplay.glrc = winCreateContext(oglDisplay.hdc, null, null)))
1111          {
1112             wglShareLists(oglSystem.glrc, oglDisplay.glrc);
1113             wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
1114             result = true;
1115          }
1116          else
1117             ReleaseDC(display.window, oglDisplay.hdc);
1118 #elif defined(__unix__) || defined(__APPLE__)
1119 #  if defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__ODROID__)
1120          result = true;
1121 #  else
1122          XVisualInfo * visualInfo = ((XWindowData)display.windowDriverData).visual;
1123          /*
1124 #if defined(__APPLE__)
1125          XVisualInfo template = { 0 };
1126          XWindowAttributes winAttr;
1127          int n;
1128          XGetWindowAttributes(xGlobalDisplay, (X11Window)display.window, &winAttr);
1129          template.visualid = XVisualIDFromVisual(winAttr.visual);
1130          visualInfo = XGetVisualInfo(xGlobalDisplay, VisualIDMask, &template, &n);
1131 #ifdef _DEBUG
1132          printf("XGetVisualInfo visual ID = %d\n", template.visualid);
1133          printf("visualInfo visual ID = %d\n", visualInfo->visualid);
1134          printf("oglSystem.visualInfo visual ID = %d\n", oglSystem.visualInfo->visualid);
1135          printf("((XWindowData)display.windowDriverData).visual visual ID = %d\n", ((XWindowData)display.windowDriverData).visual->visualid);
1136 #endif
1137          // visualInfo = oglSystem.visualInfo;
1138 //#endif
1139          */
1140          if(visualInfo)
1141          {
1142             //printf("visualInfo is not null\n");
1143             // printf("Creating Display Context, sharing with %x!\n", oglSystem.glContext);
1144             oglDisplay.glContext = glXCreateContext(xGlobalDisplay, visualInfo, oglSystem.glContext, True);
1145             //XFree(visualInfo);
1146          }
1147
1148          // oglDisplay.glContext = glXCreateContext(xGlobalDisplay, oglSystem.visualInfo, oglSystem.glContext, True);
1149          if(oglDisplay.glContext)
1150          {
1151             //printf("CreateDisplay Got a Context\n");
1152             glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext);
1153             result = true;
1154          }
1155 #  endif
1156 #endif
1157       }
1158 #if defined(__WIN32__) || defined(USEPBUFFER)
1159       else
1160       {
1161          result = true;
1162          wglMakeCurrent(oglSystem.hdc, oglSystem.glrc);
1163       }
1164 #endif
1165       if(result)
1166       {
1167 #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
1168
1169 #ifdef DIAGNOSTICS
1170          PrintLn("Calling ogl_LoadFunctions() in CreateDisplay()");
1171 #endif
1172          if(ogl_LoadFunctions() == ogl_LOAD_FAILED)
1173             PrintLn("ogl_LoadFunctions() failed!");
1174
1175 #ifdef DIAGNOSTICS
1176          PrintLn("CheckCapabilities()");
1177 #endif
1178          CheckCapabilities(oglSystem, oglDisplay);
1179
1180 #ifdef DIAGNOSTICS
1181          PrintLn("vboAvailable is: ", vboAvailable);
1182 #endif
1183
1184 #  ifdef GL_DEBUGGING
1185          setupDebugging();
1186 #  endif
1187
1188 #endif
1189
1190 #if defined(__EMSCRIPTEN__)
1191          emscripten_webgl_make_context_current(oglSystem.glc);
1192 #endif
1193
1194          if(result)
1195          {
1196             GLCapabilities capabilities = *&display.glCapabilities;
1197             // PrintLn("Available OpenGL Capabilities: ", oglDisplay.capabilities);
1198             // PrintLn("Desired OpenGL Capabilities: ", capabilities);
1199
1200             oglDisplay.originalCapabilities = oglDisplay.capabilities;
1201
1202             // Re-enable glcaps_shaders if no fixed function support
1203             if(!oglDisplay.capabilities.fixedFunction)
1204                capabilities.shaders = true;
1205             // Re-enable fixed function if no glcaps_shaders support
1206             if(!oglDisplay.capabilities.shaders)
1207             {
1208                capabilities.fixedFunction = true;
1209                capabilities.shaders = false;
1210             }
1211
1212             // Disable things that don't work with glcaps_shaders
1213             if(capabilities.shaders)
1214             {
1215                capabilities.fixedFunction = false;
1216                capabilities.legacy = false;
1217                capabilities.immediate = false;
1218             }
1219
1220             #if !ENABLE_GL_POINTER
1221             // Re-enable vertex buffer if no pointer support
1222             capabilities.vertexBuffer = true;
1223             #endif
1224
1225             oglDisplay.capabilities &= capabilities;
1226
1227             // PrintLn("Selected OpenGL Capabilities: ", oglDisplay.capabilities);
1228             oglSystem.capabilities = oglDisplay.capabilities;
1229          }
1230
1231          initialDisplaySetup(display);
1232       }
1233
1234       if(!useSingleGLContext)
1235       {
1236    #if defined(__WIN32__)
1237          wglMakeCurrent(null, null);
1238    #elif defined(__unix__) || defined(__APPLE__)
1239       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
1240          result = true;
1241       #else
1242          glXMakeCurrent(xGlobalDisplay, None, null);
1243       #endif
1244    #endif
1245       }
1246       else
1247       {
1248       #if defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__ODROID__)
1249          result = true;
1250       #endif
1251       }
1252       return result;
1253    }
1254
1255    bool DisplaySize(Display display, int width, int height)
1256    {
1257       OGLDisplay oglDisplay = display.driverData;
1258       bool result = false;
1259
1260 #if defined(__WIN32__) || defined(USEPBUFFER)
1261       OGLSystem oglSystem = display.displaySystem.driverData;
1262       if(display.alphaBlend)
1263       {
1264 #if defined(__WIN32__)
1265          const int attributes[]=
1266          {
1267             /*WGL_TEXTURE_FORMAT_ARB, WGL_TEXTURE_RGBA_ARB,
1268             WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_2D_ARB, */0
1269          };
1270          int pixelFormat = 0;
1271          if(wglChoosePixelFormatARB)
1272          {
1273             int valid;
1274             int numFormats;
1275             float fAttributes[] = {0,0};
1276             int iAttributes[] =
1277             {
1278                //WGL_DRAW_TO_BITMAP_ARB, GL_TRUE,
1279                WGL_DRAW_TO_PBUFFER_ARB,GL_TRUE,
1280                WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
1281                WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
1282                WGL_COLOR_BITS_ARB,24,
1283                WGL_ALPHA_BITS_ARB,8,
1284                WGL_DEPTH_BITS_ARB,16,
1285                WGL_STENCIL_BITS_ARB,0,
1286                WGL_DOUBLE_BUFFER_ARB,GL_FALSE,
1287                WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
1288                WGL_SAMPLES_ARB, 4,                  // Check For 4x Multisampling
1289                0,0
1290             };
1291
1292             //Log("Found wglChoosePixelFormatARB\n");
1293
1294             valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
1295             if(!valid || !numFormats)
1296             {
1297                //Log("Can't find 4x multi sampling\n");
1298                iAttributes[19] = 2;
1299                valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
1300                if(!valid || !numFormats)
1301                {
1302                   // Log("Can't find 2x multi sampling\n");
1303                   iAttributes[16] = 0;
1304                   iAttributes[17] = 0;
1305                   valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
1306                   if(!valid || !numFormats)
1307                   {
1308                      int iAttributes[] =
1309                      {
1310                         WGL_DRAW_TO_PBUFFER_ARB,GL_TRUE,
1311                         //WGL_DRAW_TO_BITMAP_ARB,GL_TRUE,
1312                         WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
1313                         WGL_COLOR_BITS_ARB,24,
1314                         WGL_ALPHA_BITS_ARB,8,
1315                         WGL_DEPTH_BITS_ARB,16,
1316                         0,0
1317                      };
1318                      valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
1319                   }
1320                }
1321             }
1322             if(valid && numFormats)
1323             {
1324                wglMakeCurrent(null, null);
1325             }
1326          }
1327
1328          wglMakeCurrent( null, null );
1329          wglMakeCurrent( oglDisplay.hdc, oglDisplay.glrc );
1330          if(oglDisplay.hdc && oglDisplay.pBuffer)
1331             wglReleasePbufferDCARB(oglDisplay.pBuffer, oglDisplay.hdc);
1332
1333          wglDestroyPbufferARB(oglDisplay.pBuffer);
1334
1335          if(!useSingleGLContext)
1336             wglMakeCurrent( null, null );
1337
1338          if(oglDisplay.glrc)
1339             wglDeleteContext(oglDisplay.glrc);
1340
1341          oglDisplay.pBuffer = wglCreatePbufferARB(oglSystem.hdc, pixelFormat, width, height, attributes);
1342          oglDisplay.hdc = wglGetPbufferDCARB(oglDisplay.pBuffer);
1343          if((oglDisplay.glrc = winCreateContext(oglDisplay.hdc, null, null)))
1344          {
1345             BITMAPINFO * info;
1346             HDC hdc = GetDC(display.window);
1347
1348             wglShareLists(oglSystem.glrc, oglDisplay.glrc);
1349             wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
1350
1351             //wglQueryPbufferARB(pBuffer, WGL_PBUFFER_WIDTH_ARB, &width);
1352             //wglQueryPbufferARB(pBuffer, WGL_PBUFFER_HEIGHT_ARB, &height);
1353
1354             // glDeleteBuffersARB(2, oglDisplay.imageBuffers);
1355
1356             if((info = (BITMAPINFO *)new0 byte[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256]))
1357             {
1358                HBITMAP newBitmap;
1359
1360                if(oglDisplay.memDC) DeleteDC(oglDisplay.memDC);
1361                oglDisplay.memDC = CreateCompatibleDC(hdc);
1362                SetMapMode(oglDisplay.memDC, MM_TEXT);
1363                info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1364                info->bmiHeader.biPlanes = 1;
1365                info->bmiHeader.biCompression = BI_RGB;
1366                info->bmiHeader.biBitCount = 32; //(uint16)GetDeviceCaps(hdc, BITSPIXEL);
1367                info->bmiHeader.biWidth = width;
1368                info->bmiHeader.biHeight = height;
1369                newBitmap = CreateDIBSection(hdc, info, DIB_RGB_COLORS, &oglDisplay.picture, null, 0);
1370                if(newBitmap)
1371                {
1372                   SelectObject(oglDisplay.memDC, newBitmap);
1373                   if(oglDisplay.memBitmap) DeleteObject(oglDisplay.memBitmap);
1374                   /*
1375                   {
1376                      PIXELFORMATDESCRIPTOR pfd = { 0 };
1377                      pfd.nSize = (short)sizeof(pfd);
1378                      pfd.nVersion = 1;
1379                      pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL;
1380                      pfd.iPixelType = PFD_TYPE_RGBA;
1381                      pfd.cColorBits = 32;
1382                      //pfd.cAlphaBits = 8;
1383                      pfd.cDepthBits = 24;
1384                      pfd.iLayerType = PFD_MAIN_PLANE;
1385
1386                      oglDisplay.hdc = oglDisplay.memDC;
1387
1388                      pixelFormat = ChoosePixelFormat(oglSystem.hdc, &pfd);
1389                      DescribePixelFormat(oglDisplay.hdc, pixelFormat, sizeof(pfd), &pfd);
1390                      SetPixelFormat(oglDisplay.hdc, pixelFormat, &pfd);
1391
1392                      oglDisplay.glrc = wglCreateContext(oglDisplay.hdc);
1393                      wglShareLists(oglSystem.glrc, oglDisplay.glrc);
1394                      wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
1395                   }
1396                   */
1397                   /*
1398                   {
1399                      const int imageSize = width * height * 4;
1400
1401                      glGenBuffersARB(2, oglDisplay.imageBuffers);
1402
1403                      glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[0]);
1404                      glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, imageSize, null, GL_STREAM_READ);
1405                      // glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[1]);
1406                      // glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, imageSize / 2, null, GL_STREAM_READ);
1407                   }
1408                   */
1409                   oglDisplay.memBitmap = newBitmap;
1410                   oglDisplay.stride = width;
1411
1412                   result = true;
1413                }
1414                delete info;
1415             }
1416             ReleaseDC(display.window, hdc);
1417          }
1418 #elif defined(__unix__) || defined(__APPLE__)
1419       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
1420          result = true;
1421       #else
1422          int attrib[] =
1423          {
1424             GLX_DOUBLEBUFFER,  True,
1425             GLX_DEPTH_SIZE,    1,
1426             GLX_RED_SIZE,      8,
1427             GLX_GREEN_SIZE,    8,
1428             GLX_BLUE_SIZE,     8,
1429             GLX_ALPHA_SIZE,    8,
1430             GLX_STENCIL_SIZE,  1,
1431             //GLX_DEPTH_SIZE,    24,
1432             GLX_RENDER_TYPE,   GLX_RGBA_BIT,
1433             GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT,
1434             None
1435          };
1436
1437          int PBattrib[] =
1438          {
1439             GLX_PBUFFER_WIDTH,   width,
1440             GLX_PBUFFER_HEIGHT,  height,
1441             GLX_LARGEST_PBUFFER, False,
1442             None
1443          };
1444
1445          // choose a pixel format that meets our minimum requirements
1446          int count = 0;
1447
1448          GLXFBConfig *config = glXChooseFBConfig(xGlobalDisplay, DefaultScreen(xGlobalDisplay), attrib, &count);
1449          if(config)
1450          {
1451             if(oglDisplay.pixmap)
1452             {
1453                XFreePixmap(xGlobalDisplay, oglDisplay.pixmap);
1454                oglDisplay.pixmap = None;
1455             }
1456             if(oglDisplay.shapePixmap)
1457             {
1458                XFreePixmap(xGlobalDisplay, oglDisplay.shapePixmap);
1459                oglDisplay.shapePixmap = None;
1460             }
1461
1462             // Free Shared Memory Pixmap
1463             if(oglDisplay.image)
1464             {
1465                if(oglDisplay.shminfoShape.shmid != -1)
1466                {
1467                   XShmDetach(xGlobalDisplay, &oglDisplay.shminfo);
1468                   if(oglDisplay.shminfo.shmaddr != (void *)-1)
1469                      shmdt(oglDisplay.shminfo.shmaddr);
1470                   shmctl(oglDisplay.shminfo.shmid, IPC_RMID, 0);
1471                }
1472                XDestroyImage(oglDisplay.image);
1473                oglDisplay.image = None;
1474             }
1475             if(oglDisplay.shapeImage)
1476             {
1477                if(oglDisplay.shminfoShape.shmid != -1)
1478                {
1479                   XShmDetach(xGlobalDisplay, &oglDisplay.shminfoShape);
1480                   if(oglDisplay.shminfoShape.shmaddr != (void *)-1)
1481                      shmdt(oglDisplay.shminfoShape.shmaddr);
1482                   shmctl(oglDisplay.shminfoShape.shmid, IPC_RMID, 0);
1483                }
1484                XDestroyImage(oglDisplay.shapeImage);
1485                oglDisplay.shapeImage = None;
1486             }
1487
1488             if(oglDisplay.windowPicture)
1489                XRenderFreePicture(xGlobalDisplay, oglDisplay.windowPicture);
1490             if(oglDisplay.pixmapPicture)
1491                XRenderFreePicture(xGlobalDisplay, oglDisplay.pixmapPicture);
1492
1493             if(oglDisplay.pixmap)
1494                XFreePixmap(xGlobalDisplay, oglDisplay.pixmap);
1495
1496             if(oglDisplay.glContext)
1497               glXDestroyContext(xGlobalDisplay, oglDisplay.glContext);
1498             if(oglDisplay.pBuffer)
1499                glXDestroyPbuffer(xGlobalDisplay, oglDisplay.pBuffer);
1500
1501             oglDisplay.pBuffer = glXCreatePbuffer(xGlobalDisplay, config[0], PBattrib);
1502             if(oglDisplay.pBuffer)
1503             {
1504                oglDisplay.glContext = glXCreateNewContext(xGlobalDisplay, config[0], GLX_RGBA_TYPE, oglSystem.glContext, True);
1505                if(oglDisplay.glContext)
1506                {
1507                   glXMakeCurrent(xGlobalDisplay, None, null);
1508                   glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext);
1509
1510                   // Initialize Shared Memory Pixmap
1511                   oglDisplay.image = XShmCreateImage(xGlobalDisplay, DefaultVisual(xGlobalDisplay, DefaultScreen(xGlobalDisplay)), 32,
1512                      ZPixmap, null, &oglDisplay.shminfo, width, height);
1513                   if(oglDisplay.image)
1514                   {
1515                      oglDisplay.shminfo.shmid = shmget(IPC_PRIVATE,
1516                         oglDisplay.image->bytes_per_line * oglDisplay.image->height, IPC_CREAT|0777);
1517                      if(oglDisplay.shminfo.shmid != -1)
1518                      {
1519                         oglDisplay.shminfo.shmaddr = shmat(oglDisplay.shminfo.shmid, 0, 0);
1520                         if(oglDisplay.shminfo.shmaddr != (void *)-1)
1521                         {
1522                            oglDisplay.shminfo.readOnly = False;
1523                            if(XShmAttach(xGlobalDisplay, &oglDisplay.shminfo))
1524                            {
1525                               oglDisplay.pixmap = XShmCreatePixmap(xGlobalDisplay, (X11Window)display.window, oglDisplay.shminfo.shmaddr,
1526                                  &oglDisplay.shminfo, width, height, 32);
1527
1528                               // Initialize Shared Memory Shape Pixmap
1529                               oglDisplay.shapeImage = XShmCreateImage(xGlobalDisplay, DefaultVisual(xGlobalDisplay, DefaultScreen(xGlobalDisplay)), 1,
1530                                  ZPixmap, null, &oglDisplay.shminfoShape, width, height);
1531                               if(oglDisplay.shapeImage)
1532                               {
1533                                  oglDisplay.shminfoShape.shmid = shmget(IPC_PRIVATE,
1534                                     oglDisplay.shapeImage->bytes_per_line * oglDisplay.shapeImage->height, IPC_CREAT|0777);
1535                                  if(oglDisplay.shminfoShape.shmid != -1)
1536                                  {
1537                                     oglDisplay.shminfoShape.shmaddr = shmat(oglDisplay.shminfoShape.shmid, 0, 0);
1538                                     if(oglDisplay.shminfoShape.shmaddr != (void *)-1)
1539                                     {
1540                                        oglDisplay.shminfoShape.readOnly = False;
1541                                        if(XShmAttach(xGlobalDisplay, &oglDisplay.shminfoShape))
1542                                        {
1543                                           oglDisplay.shapePixmap = XShmCreatePixmap(xGlobalDisplay, (X11Window)display.window, oglDisplay.shminfoShape.shmaddr,
1544                                              &oglDisplay.shminfoShape, width, height, 1);
1545                                           //oglDisplay.shapePixmap = XCreatePixmap(xGlobalDisplay, (X11Window)display.window, width, height, 1);
1546
1547                                           {
1548                                              XRenderPictureAttributes attributes = { 0 };
1549                                              XRenderPictFormat * format = XRenderFindStandardFormat(xGlobalDisplay, /*PictStandardRGB24*/ PictStandardARGB32);
1550                                              #if !defined(__APPLE__)
1551                                              attributes.repeat = RepeatNormal;
1552                                              #else
1553                                              attributes.repeat = 1;
1554                                              #endif
1555                                              oglDisplay.pixmapPicture = XRenderCreatePicture(xGlobalDisplay, oglDisplay.pixmap, format, CPRepeat, &attributes);
1556                                              oglDisplay.windowPicture = XRenderCreatePicture(xGlobalDisplay, (X11Window)display.window, format, 0, &attributes);
1557                                              oglDisplay.shapePicture = XRenderCreatePicture(xGlobalDisplay, oglDisplay.shapePixmap,
1558                                                 XRenderFindStandardFormat(xGlobalDisplay, PictStandardA1), 0, &attributes);
1559                                           }
1560
1561                                           oglDisplay.picture = oglDisplay.shminfo.shmaddr;
1562                                           oglDisplay.stride = oglDisplay.image->bytes_per_line / 4;
1563
1564                                           result = true;
1565                                        }
1566                                     }
1567                                  }
1568                               }
1569                            }
1570                         }
1571                      }
1572                   }
1573                }
1574             }
1575             XFree(config);
1576          }
1577      #endif
1578 #endif
1579          CreateDisplay(display);
1580 #if defined(__WIN32__)
1581          wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
1582 #elif defined(__unix__) || defined(__APPLE__)
1583       #if defined(__ANDROID__) || defined(__ODROID__)
1584          width = eglWidth;
1585          height = eglHeight;
1586       #elif defined(__EMSCRIPTEN__)
1587          emscripten_webgl_make_context_current(oglSystem.glc);
1588       #else
1589          glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext);
1590       #endif
1591 #endif
1592       }
1593       else
1594 #endif
1595          result = true;
1596
1597       SETCAPS(oglDisplay.capabilities);
1598
1599       if(display.alphaBlend && result)
1600          initialDisplaySetup(display);
1601
1602       if(!result && display.alphaBlend)
1603       {
1604          printf("Alpha blending windows not supported on this display\n");
1605       }
1606       if(!result)
1607          return false;
1608
1609       result = false;
1610
1611       glViewport(0,0,width,height);
1612       GLMatrixMode(MatrixMode::projection);
1613       GLLoadIdentity();
1614       GLOrtho(0,width,height,0,0.0,1.0);
1615       displayWidth = display.width = width;
1616       displayHeight = display.height = height;
1617
1618       if(!oglDisplay.flippingBuffer || oglDisplay.flipBufW < width || oglDisplay.flipBufH < height)
1619       {
1620          oglDisplay.flipBufW = width;
1621          oglDisplay.flipBufH = height;
1622 #if defined(_GLES) || defined(_GLES2)
1623          result = true;
1624 #else
1625          oglDisplay.flippingBuffer = renew oglDisplay.flippingBuffer ColorAlpha [width * height];
1626 #endif
1627       }
1628       if(oglDisplay.flippingBuffer || !width || !height)
1629          result = true;
1630
1631       return result;
1632    }
1633
1634    void DisplayPosition(Display display, int x, int y)
1635    {
1636       OGLDisplay oglDisplay = display.driverData;
1637
1638       oglDisplay.x = x;
1639       oglDisplay.y = y;
1640    }
1641
1642    void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
1643    {
1644    }
1645
1646    void RestorePalette(Display display)
1647    {
1648    }
1649
1650    void StartUpdate(Display display)
1651    {
1652    }
1653
1654    void EndUpdate(Display display)
1655    {
1656    }
1657
1658    void Scroll(Display display, Box scroll, int x, int y, Extent dirty)
1659    {
1660    }
1661
1662    void Update(Display display, Box updateBox)
1663    {
1664 #if defined(__WIN32__) || defined(USEPBUFFER)
1665       OGLDisplay oglDisplay = display.driverData;
1666 #endif
1667
1668 #if !defined(__ANDROID__)
1669       /*glFlush();
1670       glFinish();*/
1671 #endif
1672
1673 #if defined(__WIN32__) || defined(USEPBUFFER)
1674       if(display.alphaBlend)
1675       {
1676          glPixelStorei(GL_PACK_ALIGNMENT, 4);
1677          glPixelStorei(GL_PACK_ROW_LENGTH, oglDisplay.stride);
1678          glPixelStorei(GL_PACK_SKIP_ROWS, 0);
1679          glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
1680          glReadPixels(0,0,display.width,display.height,GL_BGRA_EXT,GL_UNSIGNED_BYTE, oglDisplay.picture);
1681
1682          {
1683 #if defined(__WIN32__)
1684             HDC hdc = GetDC(0);
1685             POINT point = { oglDisplay.x, oglDisplay.y};
1686             POINT srcPoint = { 0, 0 };
1687             BLENDFUNCTION blend = { 0 };
1688             SIZE size;
1689             size.cx = display.width;
1690             size.cy = display.height;
1691             blend.BlendOp = AC_SRC_OVER;
1692             blend.BlendFlags = 0;
1693             blend.SourceConstantAlpha = 255;
1694             blend.AlphaFormat = AC_SRC_ALPHA;
1695
1696             /*
1697             // Process partial images.  Mapping the buffer waits for
1698             // outstanding DMA transfers into the buffer to finish.
1699             glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[0]);
1700             oglDisplay.pboMemory1 = (byte *)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
1701
1702             // glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[1]);
1703             // oglDisplay.pboMemory2 = (byte *)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB,GL_READ_ONLY);
1704
1705
1706             memcpy(oglDisplay.picture, oglDisplay.pboMemory1, display.width * display.height * 4);
1707             //memcpy(oglDisplay.picture + display.width * display.height * 4 / 2, oglDisplay.pboMemory2, display.width * display.height * 4/ 2);
1708             */
1709
1710             UpdateLayeredWindow(display.window, hdc, &point, &size, oglDisplay.memDC, &srcPoint, 0, &blend, ULW_ALPHA);
1711             /*
1712
1713             // Unmap the image buffers
1714             glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[0]);
1715             glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
1716
1717             // glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[1]);
1718             // glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
1719
1720             // Bind two different buffer objects and start the glReadPixels
1721             // asynchronously. Each call will return directly after
1722             // starting the DMA transfer.
1723             glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[0]);
1724             glReadPixels(0, 0, display.width, display.height, GL_BGRA, GL_UNSIGNED_BYTE, 0);
1725
1726             // glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[1]);
1727             // glReadPixels(0, display.height/2, display.width, display.height/2, GL_BGRA, GL_UNSIGNED_BYTE, 0);
1728             */
1729
1730             ReleaseDC(0, hdc);
1731 #elif defined(__unix__) || defined(__APPLE__)
1732       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
1733       #else
1734             XTransform transform =
1735             {
1736                {
1737                   { (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)),  (int)(0 * (1 << 16)) },
1738                   { (int)(0.0f),           (int)(-1.0f * (1<<16)), (int)(0 * (1<<16)) },
1739                   { (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)),  (int)(1.0f * (1<<16)) }
1740                }
1741             };
1742             XRenderSetPictureTransform(xGlobalDisplay, oglDisplay.pixmapPicture, &transform);
1743             XRenderComposite(xGlobalDisplay, PictOpSrc, oglDisplay.pixmapPicture, None, oglDisplay.shapePicture, 0, 0, 0, 0, 0, 0, display.width, display.height);
1744             XRenderComposite(xGlobalDisplay, PictOpSrc, oglDisplay.pixmapPicture, None, oglDisplay.windowPicture, 0, 0, 0, 0, 0, 0, display.width, display.height);
1745             #if !defined(__APPLE__)
1746             XShapeCombineMask(xGlobalDisplay, (X11Window)display.window, ShapeInput, 0, 0, oglDisplay.shapePixmap, ShapeSet);
1747             #else
1748             XShapeCombineMask(xGlobalDisplay, display.window, 2, 0, 0, oglDisplay.shapePixmap, ShapeSet);
1749             #endif
1750             XFlush(xGlobalDisplay);
1751      #endif
1752 #endif
1753          }
1754       }
1755       else
1756 #endif
1757       {
1758 #if defined(__WIN32__)
1759          //wglSwapLayerBuffers(oglDisplay.hdc,WGL_SWAP_MAIN_PLANE);
1760          SwapBuffers(oglDisplay.hdc);
1761          //ecere::sys::Sleep(0.1);
1762 #elif defined(__unix__) || defined(__APPLE__)
1763       #if defined(__ANDROID__) || defined(__ODROID__)
1764          egl_swap_buffers();
1765       #elif defined(__EMSCRIPTEN__)
1766       #else
1767          glXSwapBuffers(xGlobalDisplay, (GLXDrawable)display.window);
1768       #endif
1769 #endif
1770       }
1771    }
1772
1773    void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
1774    {
1775       if(bitmap.driverData)
1776       {
1777          GLuint tex = (GLuint)(uintptr)bitmap.driverData;
1778          glDeleteTextures(1, &tex);
1779          bitmap.driverData = 0;
1780       }
1781       bitmap.driver = ((subclass(DisplayDriver))class(LFBDisplayDriver));
1782    }
1783
1784    bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
1785    {
1786       OGLSystem oglSystem = displaySystem.driverData;
1787       GLCapabilities capabilities = oglSystem.capabilities;
1788       bool result = false;
1789       Bitmap mipMap { };
1790       GLuint glBitmap = 0;
1791
1792       uint w = width, h = height;
1793       if(!capabilities.nonPow2Textures)
1794       {
1795          w = pow2i(w);
1796          h = pow2i(h);
1797       }
1798       w = Min(w, oglSystem.maxTextureSize);
1799       h = Min(h, oglSystem.maxTextureSize);
1800
1801       glGenTextures(1, &glBitmap);
1802       glBindTexture(GL_TEXTURE_2D, glBitmap);
1803
1804       glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
1805
1806       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1807       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1808
1809       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1810       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1811
1812 #if ENABLE_GL_FFP
1813       if(!capabilities.shaders)
1814          glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1815 #endif
1816
1817       mipMap.Allocate(null, w, h, w, pixelFormatRGBA, false);
1818
1819       // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture);
1820       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture);
1821
1822       delete mipMap;
1823
1824       bitmap.driverData = (void *)(uintptr)glBitmap;
1825       bitmap.driver = displaySystem.driver;
1826       bitmap.width = w;
1827       bitmap.height = h;
1828
1829       result = true;
1830       return result;
1831    }
1832
1833    bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
1834    {
1835       bool result = false;
1836       OGLSystem oglSystem = displaySystem.driverData;
1837       GLCapabilities capabilities = oglSystem.capabilities;
1838       Bitmap convBitmap = bitmap;
1839       if(bitmap.keepData)
1840       {
1841          convBitmap = { };
1842          convBitmap.Copy(bitmap);
1843       }
1844
1845       // Pre process the bitmap... First make it 32 bit
1846       if(/*bitmap.pixelFormat == pixelFormatRGBA || */convBitmap.Convert(null, pixelFormat888, null))
1847       {
1848          int c, level;
1849          uint w = bitmap.width, h = bitmap.height;
1850          GLuint glBitmap = 0;
1851          if(!capabilities.nonPow2Textures)
1852          {
1853             w = pow2i(w);
1854             h = pow2i(h);
1855          }
1856          w = Min(w, oglSystem.maxTextureSize);
1857          h = Min(h, oglSystem.maxTextureSize);
1858
1859          if(mipMaps)
1860          {
1861             while(w * 2 < h) w *= 2;
1862             while(h * 2 < w) h *= 2;
1863          }
1864
1865          // Switch ARGB to RGBA
1866          //if(bitmap.format != pixelFormatRGBA)
1867          {
1868             for(c=0; c<bitmap.size; c++)
1869             {
1870                // ((ColorRGBA *)bitmap.picture)[c] = ((ColorAlpha *)bitmap.picture)[c];
1871                // TODO:
1872                ColorAlpha color = ((ColorAlpha *)convBitmap.picture)[c];
1873                ((ColorRGBA *)convBitmap.picture)[c] = ColorRGBA { color.color.r, color.color.g, color.color.b, color.a };
1874             }
1875          }
1876          // convBitmap.pixelFormat = pixelFormat888;
1877
1878          glGetError();
1879          glGenTextures(1, &glBitmap);
1880          if(glBitmap == 0)
1881          {
1882             //int error = glGetError();
1883             return false;
1884          }
1885
1886          glBindTexture(GL_TEXTURE_2D, glBitmap);
1887          glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
1888
1889          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mipMaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
1890          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1891
1892          //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1893
1894          //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1895          //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1896
1897          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1898          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1899 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
1900          glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0 );
1901 #endif
1902
1903 #if ENABLE_GL_FFP
1904       if(!capabilities.shaders)
1905          glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1906 #endif
1907
1908          result = true;
1909
1910          for(level = 0; result && (w >= 1 || h >= 1); level++, w >>= 1, h >>= 1)
1911          {
1912             Bitmap mipMap;
1913             if(!w) w = 1;
1914             if(!h) h = 1;
1915             if(bitmap.width != w || bitmap.height != h)
1916             {
1917                mipMap = Bitmap { };
1918                if(mipMap.Allocate(null, w, h, w, convBitmap.pixelFormat, false))
1919                {
1920                   Surface mipSurface = mipMap.GetSurface(0,0,null);
1921                   mipSurface.Filter(convBitmap, 0,0,0,0, w, h, convBitmap.width, convBitmap.height);
1922                   delete mipSurface;
1923                }
1924                else
1925                {
1926                   result = false;
1927                   delete mipMap;
1928                }
1929             }
1930             else
1931                mipMap = convBitmap;
1932
1933             if(result)
1934             {
1935                int error;
1936                //int width = 0;
1937                glGetError();
1938                // glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture);
1939                glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture);
1940                //printf("Calling glTexImage2D\n");
1941                //glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, &width);
1942                //printf("width = %d (Should be %d, %d)\n", width, w, h);
1943                if((error = glGetError()))
1944                {
1945                   //Logf("OpenGL Bitmap MakeDD error: %d...\n", error);
1946                   //printf("OpenGL Bitmap MakeDD error: %d...\n", error);
1947                   result = false;
1948                }
1949             }
1950             if(mipMap != convBitmap)
1951                delete mipMap;
1952             if(!mipMaps) break;
1953          }
1954
1955          convBitmap.driver.FreeBitmap(convBitmap.displaySystem, convBitmap);
1956          bitmap.driverData = (void *)(uintptr)glBitmap;
1957          bitmap.driver = displaySystem.driver;
1958          if(bitmap.keepData)
1959             delete convBitmap;
1960
1961          if(!result)
1962             FreeBitmap(displaySystem, bitmap);
1963          else if(oglSystem.loadingFont)
1964          {
1965             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1966             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1967             oglSystem.loadingFont = false;
1968          }
1969       }
1970       return result;
1971    }
1972
1973    void ReleaseSurface(Display display, Surface surface)
1974    {
1975       glDisable(GL_SCISSOR_TEST);
1976       delete surface.driverData;
1977       surface.driverData = null;
1978    }
1979
1980    bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x, int y, Box clip)
1981    {
1982       return false;
1983    }
1984
1985    bool GetSurface(Display display, Surface surface, int x,int y, Box clip)
1986    {
1987       bool result = false;
1988       OGLDisplay oglDisplay = display.driverData;
1989       OGLSurface oglSurface = surface.driverData = OGLSurface { };
1990       if(oglSurface)
1991       {
1992          SETCAPS(oglDisplay.capabilities);
1993          if(displayWidth != display.width || displayHeight != display.height)
1994          {
1995             displayWidth = display.width;
1996             displayHeight = display.height;
1997
1998             glViewport(0,0,display.width,display.height);
1999             GLLoadIdentity();
2000             GLOrtho(0,display.width,display.height,0,0.0,1.0);
2001          }
2002
2003          surface.offset.x = x;
2004          surface.offset.y = y;
2005          surface.unclippedBox = surface.box = clip;
2006          oglSurface.bitmapMult[0] = 1;
2007          oglSurface.bitmapMult[1] = 1;
2008          oglSurface.bitmapMult[2] = 1;
2009          oglSurface.bitmapMult[3] = 1;
2010
2011          glEnable(GL_SCISSOR_TEST);
2012          glScissor(
2013             x+clip.left,
2014             (display.height) -(y+clip.bottom)-1,
2015             clip.right-clip.left+1,
2016             clip.bottom-clip.top+1);
2017          result = true;
2018       }
2019       return result;
2020    }
2021
2022    void Clip(Display display, Surface surface, Box clip)
2023    {
2024       Box box;
2025
2026       if(clip != null)
2027       {
2028          box = clip;
2029          box.Clip(surface.unclippedBox);
2030          surface.box = box;
2031       }
2032       else
2033          box = surface.box = surface.unclippedBox;
2034       box.left += surface.offset.x;
2035       box.top  += surface.offset.y;
2036       box.right+= surface.offset.x;
2037       box.bottom += surface.offset.y;
2038
2039       glScissor(
2040          box.left,display.height - box.bottom - 1,
2041          box.right-box.left+1, box.bottom-box.top+1);
2042    }
2043
2044    bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
2045    {
2046       bool result = false;
2047       OGLDisplay oglDisplay = display.driverData;
2048       ColorAlpha * flippingBuffer = oglDisplay.flippingBuffer;
2049
2050       if(oglDisplay.flippingBuffer)
2051       {
2052          if(bitmap.pixelFormat != pixelFormat888 || bitmap.width < w || bitmap.height < h)
2053          {
2054             bitmap.Free();
2055             bitmap.Allocate(null, w,h,w, pixelFormat888, false);
2056          }
2057          if(bitmap)
2058          {
2059             uint row;
2060
2061             glPixelStorei(GL_PACK_ALIGNMENT, 4);
2062 #if ENABLE_GL_LEGACY
2063             glPixelStorei(GL_PACK_ROW_LENGTH, bitmap.stride);
2064             glPixelStorei(GL_PACK_SKIP_ROWS, 0);
2065             glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
2066 #endif
2067             glReadPixels(x,display.height-h-y,w,h,GL_BGRA_EXT,GL_UNSIGNED_BYTE, flippingBuffer);
2068
2069             // Need a flip...
2070             for(row = 0; row<h; row++)
2071                CopyBytesBy4(((ColorAlpha *)bitmap.picture) + row * w, ((ColorAlpha *)flippingBuffer) + (h-row-1) * w, w);
2072             result = true;
2073          }
2074       }
2075       return result;
2076    }
2077
2078    void SetForeground(Display display, Surface surface, ColorAlpha color)
2079    {
2080       OGLSurface oglSurface = surface.driverData;
2081
2082       oglSurface.foreground[0] = color.color.r/255.0f;
2083       oglSurface.foreground[1] = color.color.g/255.0f;
2084       oglSurface.foreground[2] = color.color.b/255.0f;
2085       //oglSurface.foreground[3] = 1.0f;
2086       oglSurface.foreground[3] = color.a/255.0f;
2087
2088       //if(!oglSurface.foreground[3])printf("bug");
2089    }
2090
2091    void SetBackground(Display display, Surface surface, ColorAlpha color)
2092    {
2093       OGLSurface oglSurface = surface.driverData;
2094
2095       oglSurface.background[0] = color.color.r/255.0f;
2096       oglSurface.background[1] = color.color.g/255.0f;
2097       oglSurface.background[2] = color.color.b/255.0f;
2098       //oglSurface.background[3] = 1.0;
2099       oglSurface.background[3] = color.a/255.0f;
2100    }
2101
2102    void SetBlitTint(Display display, Surface surface, ColorAlpha color)
2103    {
2104       OGLSurface oglSurface = surface.driverData;
2105
2106       oglSurface.bitmapMult[0] = color.color.r/255.0f;
2107       oglSurface.bitmapMult[1] = color.color.g/255.0f;
2108       oglSurface.bitmapMult[2] = color.color.b/255.0f;
2109       oglSurface.bitmapMult[3] = color.a/255.0f;
2110    }
2111
2112    ColorAlpha GetPixel(Display display, Surface surface,int x,int y)
2113    {
2114       return 0;
2115    }
2116
2117    void PutPixel(Display display, Surface surface,int x,int y)
2118    {
2119       OGLSurface oglSurface = surface.driverData;
2120       GLColor4fv(oglSurface.foreground);
2121       GLBegin(GL_POINTS);
2122       // glVertex2i(x+surface.offset.x, y+surface.offset.y);
2123       GLVertex2f(x+surface.offset.x + 0.5f, y+surface.offset.y + 0.5f);
2124       GLEnd();
2125    }
2126
2127    void DrawLine(Display display, Surface surface, int _x1, int _y1, int _x2, int _y2)
2128    {
2129       OGLSurface oglSurface = surface.driverData;
2130       float x1 = _x1, x2 = _x2, y1 = _y1, y2 = _y2;
2131       if(_x1 == _x2)
2132       {
2133          if(_y2 >= _y1)
2134             y2 += 1;
2135          else
2136             y1 += 1;
2137       }
2138       else if(_y1 == _y2)
2139       {
2140          if(_x2 >= _x1)
2141             x2 += 1;
2142          else
2143             x1 += 1;
2144       }
2145       x1 += surface.offset.x;
2146       y1 += surface.offset.y;
2147       x2 += surface.offset.x;
2148       y2 += surface.offset.y;
2149
2150       GLColor4fv(oglSurface.foreground);
2151       GLBegin(GL_LINES);
2152       if(stippleEnabled)
2153       {
2154          GLTexCoord2f(0.5f, 0);
2155          GLVertex2f(x1 + 0.5f, y1 + 0.5f);
2156          GLTexCoord2f(Max(x2-x1, y2-y1) + 0.5f, 0);
2157          GLVertex2f(x2 + 0.5f, y2 + 0.5f);
2158       }
2159       else
2160       {
2161          /*
2162          GLVertex2i(x1, y1);
2163          GLVertex2i(x2, y2);
2164          */
2165          GLVertex2f(x1 + 0.5f, y1 + 0.5f);
2166          GLVertex2f(x2 + 0.5f, y2 + 0.5f);
2167       }
2168
2169       GLEnd();
2170    }
2171
2172    void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
2173    {
2174       OGLSurface oglSurface = surface.driverData;
2175       x1 += surface.offset.x;
2176       y1 += surface.offset.y;
2177       x2 += surface.offset.x;
2178       y2 += surface.offset.y;
2179
2180       GLColor4fv(oglSurface.foreground);
2181       if(stippleEnabled)
2182       {
2183          GLBegin(GL_LINES);
2184
2185          GLTexCoord2f(0.5f, 0);
2186          GLVertex2f(x1 + 0.5f, y1 + 0.5f);
2187          GLTexCoord2f(y2-y1 + 0.5f, 0);
2188          GLVertex2f(x1 + 0.5f, y2 + 0.5f);
2189
2190          GLTexCoord2f(0.5f, 0);
2191          GLVertex2f(x1 + 0.5f, y2 + 0.5f);
2192          GLTexCoord2f(x2 - x1 + 0.5f, 0);
2193          GLVertex2f(x2 + 0.5f, y2 + 0.5f);
2194
2195          GLTexCoord2f(0.5f, 0);
2196          GLVertex2f(x2 + 0.5f, y2 + 0.5f);
2197          GLTexCoord2f(y1 - y2 + 0.5f, 0);
2198          GLVertex2f(x2 + 0.5f, y1 + 0.5f);
2199
2200          GLTexCoord2f(0.5f, 0);
2201          GLVertex2f(x2 + 0.5f, y1 + 0.5f);
2202          GLTexCoord2f(x1 - x2 + 0.5f, 0);
2203          GLVertex2f(x1 + 0.5f, y1 + 0.5f);
2204       }
2205       else
2206       {
2207          GLBegin(GL_LINE_LOOP);
2208          /*
2209          glVertex2i(x1, y1);
2210          glVertex2i(x1, y2);
2211          glVertex2i(x2, y2);
2212          glVertex2i(x2, y1);
2213          */
2214          GLVertex2f(x1 + 0.5f, y1 + 0.5f);
2215          GLVertex2f(x1 + 0.5f, y2 + 0.5f);
2216          GLVertex2f(x2 + 0.5f, y2 + 0.5f);
2217          GLVertex2f(x2 + 0.5f, y1 + 0.5f);
2218       }
2219       GLEnd();
2220    }
2221
2222    void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
2223    {
2224       OGLSurface oglSurface = surface.driverData;
2225
2226       GLColor4fv(oglSurface.background);
2227
2228       GLRecti(x1+surface.offset.x, y1+surface.offset.y,
2229               x2+surface.offset.x + 1, y2+surface.offset.y + 1);
2230       /*
2231       GLRectf(x1+surface.offset.x, y1+surface.offset.y,
2232               x2+surface.offset.x + 1, y2+surface.offset.y + 1);
2233       */
2234    }
2235
2236    void Clear(Display display, Surface surface, ClearType type)
2237    {
2238       OGLDisplay oglDisplay = display.driverData;
2239       OGLSurface oglSurface = surface.driverData;
2240
2241       //Logf("Clear\n");
2242       if(type != depthBuffer)
2243          glClearColor(oglSurface.background[0], oglSurface.background[1], oglSurface.background[2], oglSurface.background[3]);
2244       if(type != colorBuffer && !oglDisplay.depthWrite)
2245       {
2246          glDepthMask((byte)bool::true);
2247       }
2248       glClear(((type != depthBuffer) ? GL_COLOR_BUFFER_BIT : 0) |
2249               ((type != colorBuffer) ? GL_DEPTH_BUFFER_BIT : 0));
2250       if(type != colorBuffer && !oglDisplay.depthWrite)
2251       {
2252          glDepthMask((byte)bool::false);
2253       }
2254    }
2255
2256    bool ConvertBitmap(DisplaySystem displaySystem, Bitmap bitmap, PixelFormat format, ColorAlpha * palette)
2257    {
2258       return true;
2259    }
2260
2261    void Blit(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h)
2262    {
2263       OGLSurface oglSurface = surface.driverData;
2264
2265       if(!oglSurface.writingText)
2266       {
2267          // glTranslatef(-0.375f, -0.375f, 0.0f);
2268          GLSetupTexturing(true);
2269          GLColor4fv(oglSurface.bitmapMult);
2270       }
2271       else if(oglSurface.xOffset)
2272          GLTranslated(oglSurface.xOffset / 64.0/*-0.375*/, 0.0, 0.0);
2273
2274       glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)bitmap.driverData);
2275       GLBegin(GLIMTKMode::quads);
2276
2277       if(h < 0)
2278       {
2279          GLTexCoord2f((float)sx/ bitmap.width, (float)(sy-h)/ bitmap.height);
2280          GLVertex2i(dx+surface.offset.x, dy+surface.offset.y);
2281          GLTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy-h)/ bitmap.height);
2282          GLVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
2283          GLTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height);
2284          GLVertex2i(dx+w+surface.offset.x, dy-h+surface.offset.y);
2285          GLTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height);
2286          GLVertex2i(dx+surface.offset.x, dy-h+surface.offset.y);
2287       }
2288       else
2289       {
2290          /*
2291          GLTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height);
2292          GLVertex2i(dx+surface.offset.x, dy+surface.offset.y);
2293          GLTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height);
2294          GLVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
2295          GLTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy+h)/ bitmap.height);
2296          GLVertex2i(dx+w+surface.offset.x, dy+h+surface.offset.y);
2297          GLTexCoord2f((float)sx/ bitmap.width, (float)(sy+h)/ bitmap.height);
2298          GLVertex2i(dx+surface.offset.x, dy+h+surface.offset.y);
2299          */
2300
2301          GLTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height);
2302          GLVertex2f((float)dx+surface.offset.x, (float)dy+surface.offset.y);
2303          GLTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height);
2304          GLVertex2f((float)dx+w+surface.offset.x, (float)dy+surface.offset.y);
2305          GLTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy+h)/ bitmap.height);
2306          GLVertex2f((float)dx+w+surface.offset.x, (float)dy+h+surface.offset.y);
2307          GLTexCoord2f((float)sx/ bitmap.width, (float)(sy+h)/ bitmap.height);
2308          GLVertex2f((float)dx+surface.offset.x, (float)dy+h+surface.offset.y);
2309       }
2310       GLEnd();
2311
2312       if(!oglSurface.writingText)
2313       {
2314          GLSetupTexturing(false);
2315
2316          //glTranslate(0.375, 0.375, 0.0);
2317       }
2318       else if(oglSurface.xOffset)
2319          GLTranslated(-oglSurface.xOffset / 64.0/*+0.375*/, 0.0, 0.0);
2320    }
2321
2322    void Stretch(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2323    {
2324       OGLSurface oglSurface = surface.driverData;
2325
2326       //glTranslate(-0.375, -0.375, 0.0);
2327
2328       GLSetupTexturing(true);
2329       glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)bitmap.driverData);
2330
2331       GLColor4fv(oglSurface.bitmapMult);
2332
2333       GLBegin(GLIMTKMode::quads);
2334
2335       if(h < 0)
2336       {
2337          GLTexCoord2f((float)(sx)/ bitmap.width, (float)(sy+sh)/ bitmap.height);
2338          GLVertex2i(dx+surface.offset.x, dy+surface.offset.y);
2339
2340          GLTexCoord2f((float)(sx+sw) / bitmap.width, (float)(sy+sh)/ bitmap.height);
2341          GLVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
2342
2343          GLTexCoord2f((float)(sx+sw)/ bitmap.width, (float)(sy)/ bitmap.height);
2344          GLVertex2i(dx+w+surface.offset.x, dy-h+surface.offset.y);
2345
2346          GLTexCoord2f((float)(sx) / bitmap.width, (float)(sy)/ bitmap.height);
2347          GLVertex2i(dx+surface.offset.x, dy-h+surface.offset.y);
2348       }
2349       else
2350       {
2351          GLTexCoord2f((float)(sx) / bitmap.width, (float)(sy)/ bitmap.height);
2352          GLVertex2i(dx+surface.offset.x, dy+surface.offset.y);
2353
2354          GLTexCoord2f((float)(sx+sw)/ bitmap.width, (float)(sy)/ bitmap.height);
2355          GLVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
2356
2357          GLTexCoord2f((float)(sx+sw) / bitmap.width, (float)(sy+sh)/ bitmap.height);
2358          GLVertex2i(dx+w+surface.offset.x, dy+h+surface.offset.y);
2359
2360          GLTexCoord2f((float)(sx)/ bitmap.width, (float)(sy+sh)/ bitmap.height);
2361          GLVertex2i(dx+surface.offset.x, dy+h+surface.offset.y);
2362       }
2363
2364       GLEnd();
2365
2366       GLSetupTexturing(false);
2367
2368       //glTranslate(0.375, 0.375, 0.0);
2369    }
2370
2371    void Filter(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2372    {
2373       Stretch(display, surface, bitmap, dx, dy, sx, sy, w, h, sw, sh);
2374    }
2375
2376    void StretchDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2377    {
2378       float s2dw,s2dh,d2sw,d2sh;
2379       //bool flipX = false, flipY = false;
2380
2381       if(Sgn(w) != Sgn(sw))
2382       {
2383          w = Abs(w);
2384          sw = Abs(sw);
2385          //flipX = true;
2386       }
2387       if(Sgn(h) != Sgn(sh))
2388       {
2389          h = Abs(h);
2390          sh = Abs(sh);
2391          //flipY = true;
2392       }
2393
2394       s2dw=(float)w / sw;
2395       s2dh=(float)h / sh;
2396       d2sw=(float)sw / w;
2397       d2sh=(float)sh / h;
2398
2399       //Clip against the edges of the source
2400       if(sx<0)
2401       {
2402          dx+=(int)((0-sx) * s2dw);
2403          w-=(int)((0-sx) * s2dw);
2404          sw-=0-sx;
2405          sx=0;
2406       }
2407       if(sy<0)
2408       {
2409          dy+=(int)((0-sy) * s2dh);
2410          h-=(int)((0-sy) * s2dh);
2411
2412          sh-=0-sy;
2413          sy=0;
2414       }
2415       if(sx+sw>bitmap.width-1)
2416       {
2417          w-=(int)((sx+sw-(bitmap.width-1)-1)*s2dw);
2418          sw-=sx+sw-(bitmap.width-1)-1;
2419       }
2420       if(sy+sh>(bitmap.height-1))
2421       {
2422          h-=(int)((sy+sh-(bitmap.height-1)-1)*s2dh);
2423          sh-=sy+sh-(bitmap.height-1)-1;
2424       }
2425       //Clip against the edges of the surfaceination
2426       if(dx<surface.box.left)
2427       {
2428          //if(!flip)
2429          sx+=(int)((surface.box.left-dx)*d2sw);
2430          sw-=(int)((surface.box.left-dx)*d2sw);
2431          w-=surface.box.left-dx;
2432          dx=surface.box.left;
2433       }
2434       if(dy<surface.box.top)
2435       {
2436          sy+=(int)((surface.box.top-dy)*d2sh);
2437          sh-=(int)((surface.box.top-dy)*d2sh);
2438          h-=surface.box.top-dy;
2439          dy=surface.box.top;
2440       }
2441       if(dx+w>surface.box.right)
2442       {
2443          //if(flip) sx+=(int)((dx+w-surface.box.right-1)*d2sw);
2444          sw-=(int)((dx+w-surface.box.right-1)*d2sw);
2445          w-=dx+w-surface.box.right-1;
2446       }
2447       if(dy+h>surface.box.bottom)
2448       {
2449          sh-=(int)((dy+h-surface.box.bottom-1)*d2sh);
2450          h-=dy+h-surface.box.bottom-1;
2451       }
2452       if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2453
2454       dx += surface.offset.x;
2455       dy += surface.offset.y;
2456
2457       if(bitmap.pixelFormat == pixelFormat888 && !bitmap.paletteShades)
2458       {
2459          glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
2460 #if ENABLE_GL_LEGACY
2461          if(glcaps_legacy)
2462          {
2463             glPixelStorei(GL_UNPACK_ROW_LENGTH, bitmap.stride);
2464             glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx);
2465             glPixelStorei(GL_UNPACK_SKIP_ROWS, sy);
2466             glRasterPos2d(dx,dy);
2467             //glPixelZoom(flipX ? -s2dw : s2dw, flipY ? s2dh : -s2dh);
2468             glPixelZoom(s2dw, -s2dh);
2469             glDrawPixels(sw,sh,GL_BGRA_EXT,GL_UNSIGNED_BYTE, bitmap.picture);
2470             glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
2471             glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
2472             glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
2473          }
2474 #endif
2475          glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2476       }
2477    }
2478
2479    void BlitDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h)
2480    {
2481       //Clip against the edges of the source
2482       if(sx<0)
2483       {
2484          dx+=-sx;
2485          w-=-sx;
2486          sx=0;
2487       }
2488       if(sy<0)
2489       {
2490          dy+=0-sy;
2491          h-=0-sy;
2492          sy=0;
2493       }
2494       if(sx+w>bitmap.width-1)
2495          w-=sx+w-(bitmap.width-1)-1;
2496       if(sy+h>bitmap.height-1)
2497          h-=sy+h-(bitmap.height-1)-1;
2498       //Clip against the edges of the surfaceination
2499       if(dx<surface.box.left)
2500       {
2501          //if(!flip)
2502          sx+=surface.box.left-dx;
2503          w-=surface.box.left-dx;
2504          dx=surface.box.left;
2505       }
2506       if(dy<surface.box.top)
2507       {
2508          sy+=surface.box.top-dy;
2509          h-=surface.box.top-dy;
2510          dy=surface.box.top;
2511       }
2512       if(dx+w>surface.box.right)
2513       {
2514          //if(flip) sx+=dx+w-surface.box.right-1;
2515          w-=dx+w-surface.box.right-1;
2516       }
2517       if(dy+h>surface.box.bottom)
2518          h-=dy+h-surface.box.bottom-1;
2519       if((w<=0)||(h<=0))
2520          return;
2521
2522       dx += surface.offset.x;
2523       dy += surface.offset.y;
2524
2525       if(bitmap.pixelFormat == pixelFormat888 && !bitmap.paletteShades)
2526       {
2527          glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
2528 #if ENABLE_GL_LEGACY
2529          if(glcaps_legacy)
2530          {
2531             glPixelStorei(GL_UNPACK_ROW_LENGTH, bitmap.stride);
2532             glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx);
2533             glPixelStorei(GL_UNPACK_SKIP_ROWS, sy);
2534             glRasterPos2d(dx,dy);
2535             glPixelZoom(1,-1);
2536             glDrawPixels(w,h,GL_BGRA_EXT,GL_UNSIGNED_BYTE, bitmap.picture);
2537             glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
2538             glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
2539             glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
2540          }
2541 #endif
2542          glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2543       }
2544    }
2545
2546    void FilterDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2547    {
2548       StretchDI(display, surface, bitmap, dx, dy, sx, sy, w, h, sw, sh);
2549    }
2550
2551    void UnloadFont(DisplaySystem displaySystem, Font font)
2552    {
2553       ((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, font);
2554    }
2555
2556    Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
2557    {
2558       Font font;
2559       OGLSystem oglSystem = displaySystem.driverData;
2560       oglSystem.loadingFont = true;
2561       font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags, outlineSize, outlineFade);
2562       return font;
2563    }
2564
2565    void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * adv)
2566    {
2567       ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(displaySystem, font, text, len, width, height, prevGlyph, rPrevGlyph, adv);
2568    }
2569
2570    void WriteText(Display display, Surface surface, int x, int y, const char * text, int len, int prevGlyph, int * rPrevGlyph)
2571    {
2572       OGLSurface oglSurface = surface.driverData;
2573       OGLSystem oglSystem = display.displaySystem.driverData;
2574       oglSystem.loadingFont = true;
2575
2576       //glTranslated(-0.375, -0.375, 0.0);
2577
2578       if(surface.textOpacity)
2579       {
2580          int w = 0, h, adv = 0;
2581          FontExtent(display.displaySystem, surface.font, text, len, &w, &h, 0, null, &adv);
2582          w += adv;
2583          display.displaySystem.driver.Area(display, surface,x,y,x+w-1,y+h-1);
2584       }
2585
2586       oglSurface.writingText = true;
2587
2588       GLSetupTexturing(true);
2589
2590       if(surface.font.outlineSize)
2591       {
2592          ColorAlpha outlineColor = surface.outlineColor;
2593          GLColor4ub(outlineColor.color.r, outlineColor.color.g, outlineColor.color.b, outlineColor.a);
2594          oglSurface.writingOutline = true;
2595          ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len, prevGlyph, rPrevGlyph);
2596          oglSurface.writingOutline = false;
2597       }
2598       GLColor4fv(oglSurface.foreground);
2599
2600       ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len, prevGlyph, rPrevGlyph);
2601       oglSurface.writingText = false;
2602       oglSystem.loadingFont = false;
2603
2604       GLSetupTexturing(false);
2605
2606       //glTranslated(0.375, 0.375, 0.0);
2607    }
2608
2609    void TextFont(Display display, Surface surface, Font font)
2610    {
2611       ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextFont(display, surface, font);
2612    }
2613
2614    void TextOpacity(Display display, Surface surface, bool opaque)
2615    {
2616       OGLSurface oglSurface = surface.driverData;
2617       oglSurface.opaqueText = opaque;
2618    }
2619
2620    void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * adv)
2621    {
2622       OGLSurface oglSurface = surface.driverData;
2623       OGLSystem oglSystem = display.displaySystem.driverData;
2624       oglSystem.loadingFont = true;
2625       FontExtent(display.displaySystem, oglSurface.font, text, len, width, height, prevGlyph, rPrevGlyph, adv);
2626       oglSystem.loadingFont = false;
2627    }
2628
2629    void DrawingChar(Display display, Surface surface, char character)
2630    {
2631
2632    }
2633
2634    void LineStipple(Display display, Surface surface, uint32 stipple)
2635    {
2636       if(stipple)
2637       {
2638 #if ENABLE_GL_LEGACY
2639          if(glcaps_legacy)
2640          {
2641             glLineStipple(1, (uint16)stipple);
2642             glEnable(GL_LINE_STIPPLE);
2643          }
2644          else
2645 #endif
2646          {
2647             stippleEnabled = true;
2648             glsupLineStipple(1, (uint16)stipple);
2649          }
2650       }
2651       else
2652       {
2653 #if ENABLE_GL_LEGACY
2654          if(glcaps_legacy)
2655             glDisable(GL_LINE_STIPPLE);
2656          else
2657 #endif
2658          {
2659             stippleEnabled = false;
2660             GLMatrixMode(GL_TEXTURE);
2661             GLLoadIdentity();
2662             GLMatrixMode(MatrixMode::projection);
2663             GLSetupTexturing(false);   // TODO: Special shading code for stipple?
2664          }
2665       }
2666    }
2667
2668 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
2669    void SetRenderState(Display display, RenderState state, uint value)
2670    {
2671       OGLDisplay oglDisplay = display.driverData;
2672       switch(state)
2673       {
2674          case antiAlias:
2675 #ifndef __EMSCRIPTEN__
2676             if(value)
2677                glEnable(GL_MULTISAMPLE);
2678             else
2679                glDisable(GL_MULTISAMPLE);
2680 #endif
2681             break;
2682          case fillMode:
2683 #if ENABLE_GL_LEGACY
2684             if(glcaps_legacy)
2685                glPolygonMode(GL_FRONT_AND_BACK, ((FillModeValue)value == solid) ? GL_FILL : GL_LINE);
2686 #endif
2687             break;
2688          case depthTest:
2689             if(value) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
2690             break;
2691          case depthWrite:
2692             if(value) glDepthMask((byte)bool::true); else glDepthMask((byte)bool::false);
2693             oglDisplay.depthWrite = (bool)value;
2694             break;
2695          case fogColor:
2696          {
2697             float color[4] = { ((Color)value).r/255.0f, ((Color)value).g/255.0f, ((Color)value).b/255.0f, 1.0f };
2698 #if ENABLE_GL_SHADERS
2699             if(glcaps_shaders)
2700                shader_fogColor(color[0], color[1], color[2]);
2701 #endif
2702
2703 #if ENABLE_GL_FFP
2704             if(!glcaps_shaders)
2705                glFogfv(GL_FOG_COLOR, (float *)&color);
2706 #endif
2707             break;
2708          }
2709          case fogDensity:
2710 #if ENABLE_GL_SHADERS
2711             if(glcaps_shaders)
2712                shader_fogDensity((float)(RenderStateFloat { ui = value }.f * nearPlane));
2713 #endif
2714
2715 #if ENABLE_GL_FFP
2716             if(!glcaps_shaders)
2717                glFogf(GL_FOG_DENSITY, (float)(RenderStateFloat { ui = value }.f * nearPlane));
2718 #endif
2719             break;
2720          case blend:
2721 //#if !defined(__EMSCRIPTEN__)
2722             if(value) glEnable(GL_BLEND); else glDisable(GL_BLEND);
2723 //#endif
2724             break;
2725          case ambient:
2726          {
2727 #if ENABLE_GL_SHADERS
2728             if(glcaps_shaders)
2729                shader_setGlobalAmbient(((Color)value).r / 255.0f, ((Color)value).g / 255.0f, ((Color)value).b / 255.0f, 1.0f);
2730 #endif
2731
2732 #if ENABLE_GL_FFP
2733             if(!glcaps_shaders)
2734             {
2735                float ambient[4] = { ((Color)value).r/255.0f, ((Color)value).g/255.0f, ((Color)value).b/255.0f, 1.0f };
2736                glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
2737             }
2738 #endif
2739             break;
2740          }
2741          case alphaWrite:
2742          {
2743             if(value) glColorMask(1,1,1,1); else glColorMask(1,1,1,0);
2744             break;
2745          }
2746          case vSync:
2747          {
2748 #if defined(__WIN32__)
2749             if(wglSwapIntervalEXT)
2750                wglSwapIntervalEXT(value ? 1 : 0);
2751 #endif
2752             break;
2753          }
2754       }
2755    }
2756
2757    void SetLight(Display display, int id, Light light)
2758    {
2759 #if ENABLE_GL_SHADERS
2760       if(glcaps_shaders)
2761          shader_setLight(display, id, light);
2762 #endif
2763
2764 #if ENABLE_GL_FFP
2765       if(!glcaps_shaders)
2766       {
2767          if(light != null)
2768          {
2769             Object lightObject = light.lightObject;
2770             float position[4] = { 0, 0, 0, 0 };
2771             float color[4] = { 0, 0, 0, 1 };
2772
2773             glEnable(GL_LIGHT0 + id);
2774
2775             if(!light.multiplier) light.multiplier = 1.0f;
2776
2777             color[0] = light.diffuse.r * light.multiplier;
2778             color[1] = light.diffuse.g * light.multiplier;
2779             color[2] = light.diffuse.b * light.multiplier;
2780             glLightfv(GL_LIGHT0 + id, GL_DIFFUSE, color);
2781
2782             color[0] = light.ambient.r * light.multiplier;
2783             color[1] = light.ambient.g * light.multiplier;
2784             color[2] = light.ambient.b * light.multiplier;
2785             glLightfv(GL_LIGHT0 + id, GL_AMBIENT, color);
2786             color[0] = light.specular.r * light.multiplier;
2787             color[1] = light.specular.g * light.multiplier;
2788             color[2] = light.specular.b * light.multiplier;
2789             glLightfv(GL_LIGHT0 + id, GL_SPECULAR,color);
2790
2791             if(lightObject)
2792             {
2793                Vector3D positionVector;
2794                if(light.flags.spot)
2795                {
2796                   if(lightObject.flags.root || !lightObject.parent)
2797                   {
2798                      positionVector = lightObject.transform.position;
2799                      positionVector.Subtract(positionVector, display.display3D.camera.cPosition);
2800                   }
2801                   else
2802                   {
2803                      positionVector.MultMatrix(lightObject.transform.position, lightObject.parent.matrix);
2804                      if(display.display3D.camera)
2805                         positionVector.Subtract(positionVector, display.display3D.camera.cPosition);
2806                   }
2807                   position[3] = 1;
2808                }
2809                else
2810                {
2811                   if(!light.direction.x && !light.direction.y && !light.direction.z)
2812                   {
2813                      Vector3Df vector { 0,0,-1 };
2814                      Matrix mat;
2815                      mat.RotationQuaternion(light.orientation);
2816                      positionVector.MultMatrixf(vector, mat);
2817                   }
2818                   else
2819                   {
2820                      positionVector = light.direction;
2821                      position[3] = 1;
2822                   }
2823                }
2824
2825                position[0] = (float)positionVector.x;
2826                position[1] = (float)positionVector.y;
2827                position[2] = (float)positionVector.z;
2828
2829                glLightfv(GL_LIGHT0 + id, GL_POSITION, position);
2830
2831                /*
2832                // Display Light Position
2833                glDisable(GL_LIGHTING);
2834                glDisable(GL_DEPTH_TEST);
2835                glColor3f(1,1,1);
2836                glPointSize(10);
2837                glBegin(GL_POINTS);
2838                glVertex3fv(position);
2839                glEnd();
2840                glEnable(GL_DEPTH_TEST);
2841                glEnable(GL_LIGHTING);
2842
2843
2844                // Display Target
2845                if(lightObject.flags.root || !lightObject.parent)
2846                {
2847                   positionVector = light.target.transform.position;
2848                   positionVector.Subtract(positionVector, display.camera.cPosition);
2849                }
2850                else
2851                {
2852                   positionVector.MultMatrix(light.target.transform.position,
2853                      lightObject.light.target.parent.matrix);
2854                   positionVector.Subtract(positionVector, display.camera.cPosition);
2855                }
2856
2857                position[0] = positionVector.x;
2858                position[1] = positionVector.y;
2859                position[2] = positionVector.z;
2860
2861                glDisable(GL_LIGHTING);
2862                glDisable(GL_DEPTH_TEST);
2863                glColor3f(1,1,0);
2864                glPointSize(10);
2865                glBegin(GL_POINTS);
2866                glVertex3fv(position);
2867                glEnd();
2868                glEnable(GL_DEPTH_TEST);
2869                glEnable(GL_LIGHTING);
2870                */
2871
2872                if(light.flags.attenuation)
2873                {
2874                   glLightf(GL_LIGHT0 + id, GL_CONSTANT_ATTENUATION, light.Kc);
2875                   glLightf(GL_LIGHT0 + id, GL_LINEAR_ATTENUATION, light.Kl);
2876                   glLightf(GL_LIGHT0 + id, GL_QUADRATIC_ATTENUATION, light.Kq);
2877                }
2878
2879                if(light.flags.spot)
2880                {
2881                   float exponent = 0;
2882                   #define MAXLIGHT  0.9
2883                   float direction[4] = { (float)light.direction.x, (float)light.direction.y, (float)light.direction.z, 1 };
2884                   // Figure out exponent out of the hot spot
2885                   exponent = (float)(log(MAXLIGHT) / log(cos((light.hotSpot / 2))));
2886
2887                   glLightfv(GL_LIGHT0 + id, GL_SPOT_DIRECTION, direction);
2888                   glLightf(GL_LIGHT0 + id, GL_SPOT_CUTOFF, (float)(light.fallOff / 2));
2889                   glLightf(GL_LIGHT0 + id, GL_SPOT_EXPONENT, exponent);
2890                }
2891             }
2892             else
2893             {
2894                Vector3Df vector { 0,0,-1 };
2895                Vector3Df direction;
2896                Matrix mat;
2897
2898                mat.RotationQuaternion(light.orientation);
2899                direction.MultMatrix(vector, mat);
2900
2901                position[0] = direction.x;
2902                position[1] = direction.y;
2903                position[2] = direction.z;
2904
2905                glLightfv(GL_LIGHT0 + id, GL_POSITION, position);
2906             }
2907          }
2908          else
2909             glDisable(GL_LIGHT0 + id);
2910       }
2911 #endif
2912    }
2913
2914    void SetCamera(Display display, Surface surface, Camera camera)
2915    {
2916       OGLDisplay oglDisplay = display.driverData;
2917
2918       if(surface && camera)
2919       {
2920          int left = surface.box.left + surface.offset.x;
2921          int top = surface.box.top  + surface.offset.y;
2922          int right = surface.box.right + surface.offset.x;
2923          int bottom = surface.box.bottom + surface.offset.y;
2924          float origX = surface.offset.x + camera.origin.x;
2925          float origY = surface.offset.y + camera.origin.y;
2926          int x = left;
2927          int y = display.height - bottom - 1;
2928          int w = right - left + 1;
2929          int h = bottom - top + 1;
2930
2931          // *** ViewPort ***
2932          glViewport(x, y, w, h);
2933
2934          // *** Projection Matrix ***
2935          GLMatrixMode(MatrixMode::projection);
2936          if(!display.display3D.camera)
2937             GLPushMatrix();
2938
2939          if(display.display3D.collectingHits)
2940          {
2941             float pickX = display.display3D.pickX + surface.offset.x;
2942             float pickY = display.height - (display.display3D.pickY + surface.offset.y) - 1;
2943             Matrix pickMatrix
2944             {
2945                {
2946                   w / display.display3D.pickWidth, 0, 0, 0,
2947                   0, h / display.display3D.pickHeight, 0, 0,
2948                   0, 0, 1, 0,
2949                   (w + 2.0f * (x - pickX)) / display.display3D.pickWidth,
2950                   (h + 2.0f * (y - pickY)) / display.display3D.pickHeight, 0, 1
2951                }
2952             };
2953             GLLoadMatrixd(pickMatrix.array);
2954          }
2955          else
2956             GLLoadIdentity();
2957          GLFrustum(
2958             (left   - origX) * camera.zMin / camera.focalX,
2959             (right  - origX) * camera.zMin / camera.focalX,
2960             (bottom - origY) * camera.zMin / camera.focalY,
2961             (top    - origY) * camera.zMin / camera.focalY,
2962             camera.zMin, camera.zMax);
2963
2964          glDisable(GL_BLEND);
2965
2966          // *** Z Inverted Identity Matrix ***
2967          GLMatrixMode(MatrixMode::modelView);
2968          if(!display.display3D.camera)
2969             GLPushMatrix();
2970
2971          GLLoadIdentity();
2972
2973          GLScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane);
2974
2975          // *** View Matrix ***
2976          GLMultMatrixd(camera.viewMatrix.array);
2977
2978          // *** Lights ***
2979          // ...
2980
2981          glEnable(GL_DEPTH_TEST);
2982
2983          GLSetupLighting(true);
2984 #if ENABLE_GL_FFP
2985          if(!glcaps_shaders)
2986             glShadeModel(GL_SMOOTH);
2987 #endif
2988          glDepthMask((byte)bool::true);
2989          oglDisplay.depthWrite = true;
2990
2991 #ifndef __EMSCRIPTEN__
2992          glEnable(GL_MULTISAMPLE);
2993 #endif
2994       }
2995       else if(surface && display.display3D.camera)
2996       {
2997          nearPlane = 1;
2998          oglDisplay.depthWrite = false;
2999          glViewport(0,0,display.width,display.height);
3000
3001          glDisable(GL_CULL_FACE);
3002          glDisable(GL_DEPTH_TEST);
3003
3004          GLSetupTexturing(false);
3005          GLSetupLighting(false);
3006          GLSetupFog(false);
3007
3008          GLDisableClientState(COLORS);
3009
3010 #if ENABLE_GL_SHADERS
3011          if(glcaps_shaders)
3012             shader_setPerVertexColor(false);
3013 #endif
3014
3015 #if ENABLE_GL_FFP
3016          if(!glcaps_shaders)
3017             glShadeModel(GL_FLAT);
3018 #endif
3019          glEnable(GL_BLEND);
3020 #if !defined(__EMSCRIPTEN__)
3021          glDisable(GL_MULTISAMPLE);
3022 #endif
3023
3024          // *** Restore 2D MODELVIEW Matrix ***
3025          GLPopMatrix();
3026
3027          // *** Restore 2D PROJECTION Matrix ***
3028          GLMatrixMode(MatrixMode::projection);
3029          GLPopMatrix();
3030       }
3031
3032    }
3033
3034    void ApplyMaterial(Display display, Material material, Mesh mesh)
3035    {
3036       // Basic Properties
3037       if(material.flags.doubleSided)
3038       {
3039 #if ENABLE_GL_FFP
3040          if(!glcaps_shaders)
3041             GLLightModeli(GL_LIGHT_MODEL_TWO_SIDE, !material.flags.singleSideLight);
3042 #endif
3043          glDisable(GL_CULL_FACE);
3044       }
3045       else
3046       {
3047 #if ENABLE_GL_FFP
3048          if(!glcaps_shaders)
3049             GLLightModeli(GL_LIGHT_MODEL_TWO_SIDE, bool::false);
3050 #endif
3051          glEnable(GL_CULL_FACE);
3052       }
3053
3054       // Fog
3055       GLSetupFog(!material.flags.noFog);
3056
3057       // Maps
3058       if(material.baseMap && (mesh.texCoords || mesh.flags.texCoords1))
3059       {
3060          Bitmap map = material.baseMap;
3061          GLSetupTexturing(true);
3062          glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)map.driverData);
3063
3064          GLMatrixMode(GL_TEXTURE);
3065          GLLoadIdentity();
3066          if(material.uScale && material.vScale)
3067             GLScalef(material.uScale, material.vScale, 1);
3068          GLMatrixMode(MatrixMode::modelView);
3069
3070          if(material.flags.tile)
3071          {
3072             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
3073             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
3074          }
3075          else
3076          {
3077             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3078             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3079          }
3080       }
3081       else
3082          GLSetupTexturing(false);
3083
3084 #if ENABLE_GL_SHADERS
3085       if(glcaps_shaders)
3086          shader_setMaterial(material, mesh.flags.colors);
3087 #endif
3088
3089 #if ENABLE_GL_FFP
3090       if(!glcaps_shaders)
3091       {
3092          if(mesh.flags.colors)
3093          {
3094             GLColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
3095             glEnable(GL_COLOR_MATERIAL);
3096          }
3097          else
3098          {
3099             glDisable(GL_COLOR_MATERIAL);
3100             {
3101                float color[4] = { material.diffuse.r, material.diffuse.g, material.diffuse.b, material.opacity };
3102                glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
3103             }
3104             {
3105                float color[4] = { material.ambient.r, material.ambient.g, material.ambient.b, 0 };
3106                glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
3107             }
3108          }
3109          {
3110             float color[4] = { material.specular.r, material.specular.g, material.specular.b, 0 };
3111             glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
3112          }
3113          {
3114             float color[4] = { material.emissive.r, material.emissive.g, material.emissive.b, 0 };
3115             glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color);
3116          }
3117
3118          glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &material.power);
3119       }
3120 #endif
3121    }
3122
3123    void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
3124    {
3125       OGLMesh oglMesh = mesh.data;
3126       if(oglMesh)
3127       {
3128          OGLSystem oglSystem = displaySystem.driverData;
3129          SETCAPS(oglSystem.capabilities);
3130          if(!mesh.flags.vertices)
3131          {
3132             oglMesh.vertices.free(glcaps_vertexBuffer);
3133             delete mesh.vertices;
3134          }
3135          if(!mesh.flags.normals)
3136          {
3137             oglMesh.normals.free(glcaps_vertexBuffer);
3138             delete mesh.normals;
3139          }
3140          if(!mesh.flags.texCoords1)
3141          {
3142             oglMesh.texCoords.free(glcaps_vertexBuffer);
3143             delete mesh.texCoords;
3144          }
3145          if(!mesh.flags.texCoords2)
3146          {
3147             oglMesh.texCoords2.free(glcaps_vertexBuffer);
3148             // delete mesh.texCoords2;
3149          }
3150          if(!mesh.flags.colors)
3151          {
3152             oglMesh.colors.free(glcaps_vertexBuffer);
3153             delete mesh.colors;
3154          }
3155          if(!mesh.flags)
3156          {
3157             delete oglMesh;
3158             mesh.data = null;
3159          }
3160       }
3161    }
3162
3163    bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags, int nVertices)
3164    {
3165       bool result = false;
3166
3167       if(!mesh.data)
3168          mesh.data = OGLMesh { };
3169       if(mesh.data)
3170       {
3171          if(mesh.nVertices == nVertices)
3172          {
3173             // Same number of vertices, adding features (Leaves the other features pointers alone)
3174             if(mesh.flags != flags)
3175             {
3176                if(!mesh.flags.vertices && flags.vertices)
3177                {
3178                   if(flags.doubleVertices)
3179                   {
3180                      mesh.vertices = (Vector3Df *)new Vector3D[nVertices];
3181                   }
3182                   else
3183                      mesh.vertices = new Vector3Df[nVertices];
3184                }
3185                if(!mesh.flags.normals && flags.normals)
3186                {
3187                   if(flags.doubleNormals)
3188                   {
3189                      mesh.normals = (Vector3Df *)new Vector3D[nVertices];
3190                   }
3191                   else
3192                      mesh.normals = new Vector3Df[nVertices];
3193                }
3194                if(!mesh.flags.texCoords1 && flags.texCoords1)
3195                {
3196                   mesh.texCoords = new Pointf[nVertices];
3197                }
3198                if(!mesh.flags.colors && flags.colors)
3199                {
3200                   mesh.colors = new ColorRGBAf[nVertices];
3201                }
3202             }
3203          }
3204          else
3205          {
3206             // New number of vertices, reallocate all current and new features
3207             flags |= mesh.flags;
3208             if(flags.vertices)
3209             {
3210                if(flags.doubleVertices)
3211                {
3212                   mesh.vertices = (Vector3Df *)renew mesh.vertices Vector3D[nVertices];
3213                }
3214                else
3215                   mesh.vertices = renew mesh.vertices Vector3Df[nVertices];
3216             }
3217             if(flags.normals)
3218             {
3219                if(flags.doubleNormals)
3220                {
3221                   mesh.normals = (Vector3Df *)renew mesh.normals Vector3D[nVertices];
3222                }
3223                else
3224                   mesh.normals = renew mesh.normals Vector3Df[nVertices];
3225             }
3226             if(flags.texCoords1)
3227             {
3228                mesh.texCoords = renew mesh.texCoords Pointf[nVertices];
3229             }
3230             if(flags.colors)
3231             {
3232                mesh.colors = renew mesh.colors ColorRGBAf[nVertices];
3233             }
3234          }
3235          result = true;
3236       }
3237       return result;
3238    }
3239
3240    void UnlockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags)
3241    {
3242       OGLSystem oglSystem = displaySystem.driverData;
3243       SETCAPS(oglSystem.capabilities);
3244       if(glcaps_vertexBuffer)
3245       {
3246          OGLMesh oglMesh = mesh.data;
3247          if(!flags) flags = mesh.flags;
3248          if(flags.vertices)
3249             oglMesh.vertices.upload(
3250                mesh.nVertices * (mesh.flags.doubleVertices ? sizeof(Vector3D) : sizeof(Vector3Df)), mesh.vertices);
3251
3252          if(flags.normals)
3253             oglMesh.normals.upload(
3254                mesh.nVertices * (mesh.flags.doubleNormals ? sizeof(Vector3D) : sizeof(Vector3Df)), mesh.normals);
3255
3256          if(flags.texCoords1)
3257             oglMesh.texCoords.upload(
3258                mesh.nVertices * sizeof(Pointf), mesh.texCoords);
3259
3260          if(flags.colors)
3261             oglMesh.colors.upload(
3262                mesh.nVertices * sizeof(ColorRGBAf), mesh.colors);
3263       }
3264    }
3265
3266    bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags)
3267    {
3268       bool result = true;
3269
3270       return result;
3271    }
3272
3273    void FreeIndices(DisplaySystem displaySystem, OGLIndices oglIndices)
3274    {
3275       OGLSystem oglSystem = displaySystem.driverData;
3276       SETCAPS(oglSystem.capabilities);
3277       if(oglIndices)
3278       {
3279          oglIndices.buffer.free(glcaps_vertexBuffer);
3280          delete oglIndices.indices;
3281          delete oglIndices;
3282       }
3283    }
3284
3285    void * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
3286    {
3287       OGLIndices oglIndices = OGLIndices { };
3288       if(oglIndices)
3289       {
3290          oglIndices.indices = (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
3291          oglIndices.nIndices = nIndices;
3292       }
3293       return oglIndices;
3294    }
3295
3296    void UnlockIndices(DisplaySystem displaySystem, OGLIndices oglIndices, bool indices32bit, int nIndices)
3297    {
3298       OGLSystem oglSystem = displaySystem.driverData;
3299       SETCAPS(oglSystem.capabilities);
3300       if(glcaps_vertexBuffer)
3301       {
3302 #if !ENABLE_GL_INTDBL
3303          if(indices32bit)
3304          {
3305             if(!oglIndices.buffer.buffer)
3306                glGenBuffers(1, &oglIndices.buffer.buffer);
3307             if(glabCurElementBuffer != oglIndices.buffer.buffer)
3308                GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, oglIndices.buffer.buffer);
3309             glimtkBufferDatai(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32) * nIndices, oglIndices.indices, GL_STATIC_DRAW);
3310          }
3311          else
3312 #endif
3313          oglIndices.buffer.upload(
3314             nIndices * (indices32bit ? sizeof(uint32) : sizeof(uint16)),
3315             oglIndices.indices);
3316       }
3317    }
3318
3319    uint16 * LockIndices(DisplaySystem displaySystem, OGLIndices oglIndices)
3320    {
3321
3322       return oglIndices.indices;
3323    }
3324
3325    void SelectMesh(Display display, Mesh mesh)
3326    {
3327 #if !defined( __ANDROID__) && !defined(__APPLE__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
3328 #if defined(__WIN32__)
3329       if(glUnlockArraysEXT)
3330 #endif
3331          if(!glcaps_vertexBuffer && display.display3D.mesh)
3332             glUnlockArraysEXT();
3333 #endif
3334       if(mesh)
3335       {
3336          OGLMesh oglMesh = mesh.data;
3337
3338          // *** Vertex Stream ***
3339          GLEnableClientState(VERTICES);
3340          if(!display.display3D.collectingHits && oglMesh)
3341          {
3342             oglMesh.vertices.use(vertex, 3, (mesh.flags.doubleVertices ? GL_DOUBLE : GL_FLOAT), 0, oglMesh.vertices.buffer ? null : (double *)mesh.vertices);
3343
3344             // *** Normals Stream ***
3345             if(mesh.normals || mesh.flags.normals)
3346             {
3347                GLEnableClientState(NORMALS);
3348                oglMesh.normals.use(normal, 3, GL_FLOAT, 0, oglMesh.normals.buffer ? null : mesh.normals);
3349             }
3350             else
3351                GLDisableClientState(NORMALS);
3352
3353             // *** Texture Coordinates Stream ***
3354             if(mesh.texCoords || mesh.flags.texCoords1)
3355             {
3356                GLEnableClientState(TEXCOORDS);
3357                oglMesh.texCoords.use(texCoord, 2, GL_FLOAT, 0, oglMesh.texCoords.buffer ? null : mesh.texCoords);
3358             }
3359             else
3360                GLDisableClientState(TEXCOORDS);
3361
3362             // *** Color Stream ***
3363             if(mesh.colors || mesh.flags.colors)
3364             {
3365                GLEnableClientState(COLORS);
3366                oglMesh.colors.use(color, 4, GL_FLOAT, 0, oglMesh.colors.buffer ? null : mesh.colors);
3367             }
3368             else
3369                GLDisableClientState(COLORS);
3370          }
3371          else
3372          {
3373             noAB.use(vertex, 3, (mesh.flags.doubleVertices ? GL_DOUBLE : GL_FLOAT), 0, (double *)mesh.vertices);
3374             if((mesh.normals || mesh.flags.normals) && !display.display3D.collectingHits)
3375             {
3376                GLEnableClientState(NORMALS);
3377                noAB.use(normal, 3, GL_FLOAT, 0, mesh.normals);
3378             }
3379             else
3380                GLDisableClientState(NORMALS);
3381             if((mesh.texCoords || mesh.flags.texCoords1) && !display.display3D.collectingHits)
3382             {
3383                GLEnableClientState(TEXCOORDS);
3384                noAB.use(texCoord, 2, GL_FLOAT, 0, mesh.texCoords);
3385             }
3386             else
3387                GLDisableClientState(TEXCOORDS);
3388             if((mesh.colors || mesh.flags.colors) && !display.display3D.collectingHits)
3389             {
3390                GLEnableClientState(COLORS);
3391                noAB.use(color, 4, GL_FLOAT, 0, mesh.colors);
3392             }
3393             else
3394                GLDisableClientState(COLORS);
3395          }
3396
3397 #if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
3398
3399 #if defined(__WIN32__)
3400          if(glLockArraysEXT)
3401 #endif
3402             if(!glcaps_vertexBuffer)
3403                glLockArraysEXT(0, mesh.nVertices);
3404 #endif
3405       }
3406    }
3407
3408    void DrawPrimitives(Display display, PrimitiveSingle * primitive, Mesh mesh)
3409    {
3410       if(primitive->type.vertexRange)
3411       {
3412          GLFlushMatrices();
3413          glDrawArrays(getPrimitiveType(primitive->type.primitiveType), primitive->first, primitive->nVertices);
3414       }
3415       else
3416       {
3417          OGLIndices oglIndices = primitive->data;
3418          GLEAB eab = ((!display.display3D.collectingHits && oglIndices && glcaps_vertexBuffer) ? oglIndices.buffer : noEAB);
3419 #if !ENABLE_GL_INTDBL
3420          if(!glcaps_vertexBuffer && primitive->type.indices32bit)
3421          {
3422             uint16 * temp = new uint16[primitive->nIndices];
3423             uint32 * src = (uint32 *)(oglIndices ? oglIndices.indices : primitive->indices);
3424             int i;
3425             for(i = 0; i < primitive->nIndices; i++)
3426                temp[i] = (uint16)src[i];
3427             eab.draw(getPrimitiveType(primitive->type.primitiveType), primitive->nIndices, GL_UNSIGNED_SHORT, temp);
3428             delete temp;
3429          }
3430          else
3431 #endif
3432             eab.draw(getPrimitiveType(primitive->type.primitiveType), primitive->nIndices,
3433                primitive->type.indices32bit ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT,
3434                eab.buffer ? 0 : (oglIndices ? oglIndices.indices : primitive->indices));
3435          GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
3436       }
3437    }
3438
3439    void PushMatrix(Display display)
3440    {
3441       GLPushMatrix();
3442    }
3443
3444    void PopMatrix(Display display, bool setMatrix)
3445    {
3446       GLPopMatrix();
3447    }
3448
3449    void SetTransform(Display display, Matrix transMatrix, bool viewSpace, bool useCamera)
3450    {
3451       Matrix matrix = transMatrix;
3452       Camera camera = useCamera ? display.display3D.camera : null;
3453
3454       if(viewSpace)
3455       {
3456          GLLoadIdentity();
3457          GLScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane);
3458       }
3459       else if(camera)
3460       {
3461          GLTranslated(
3462             matrix.m[3][0] - camera.cPosition.x,
3463             matrix.m[3][1] - camera.cPosition.y,
3464             matrix.m[3][2] - camera.cPosition.z);
3465       }
3466       else
3467          GLTranslated(
3468             matrix.m[3][0],
3469             matrix.m[3][1],
3470             matrix.m[3][2]);
3471
3472       matrix.m[3][0] = 0;
3473       matrix.m[3][1] = 0;
3474       matrix.m[3][2] = 0;
3475
3476       GLMultMatrixd(matrix.array);
3477    }
3478 #endif
3479 }
3480
3481 public void UseSingleGLContext(bool useSingle)
3482 {
3483    useSingleGLContext = useSingle;
3484 }
3485
3486 default dllexport void *
3487 #if defined(__WIN32__)
3488 __attribute__((stdcall))
3489 #endif
3490 IS_GLGetContext(DisplaySystem displaySystem)
3491 {
3492    if(displaySystem)
3493    {
3494 #if defined(__WIN32__)
3495       OGLSystem system = displaySystem.driverData;
3496       return system.glrc;
3497 #elif defined(__ANDROID__) || defined(__ODROID__)
3498       return eglContext;
3499 #elif defined(__EMSCRIPTEN__)
3500       OGLSystem system = displaySystem.driverData;
3501       return (void *)system.glc;
3502 #else
3503       OGLSystem system = displaySystem.driverData;
3504       return system.glContext;
3505 #endif
3506    }
3507    return null;
3508 }
3509
3510 #endif