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