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