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