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