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