ecere/gfx/OpenGL; FontRendering; Window: Fixed rendering in non-locked Display
[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)
665    {
666       GLCapabilities capabilities;
667 #if !defined(_GLES2)
668       const char * extensions = (const char *)glGetString(GL_EXTENSIONS);
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 = 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);
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)
1037    {
1038       OGLDisplay oglDisplay = display.driverData;
1039       OGLSystem oglSystem = display.displaySystem.driverData;
1040       bool result = true;
1041
1042       oglSystem.capabilities = oglDisplay.capabilities;
1043       SETCAPS(oglDisplay.capabilities);
1044
1045 #if ENABLE_GL_SHADERS
1046       if(glCaps_shaders)
1047       {
1048 #if ENABLE_GL_LEGACY
1049          if(oglDisplay.compat)
1050          {
1051             glDisableClientState(GL_VERTEX_ARRAY);
1052             glDisableClientState(GL_NORMAL_ARRAY);
1053             glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1054             glDisableClientState(GL_COLOR_ARRAY);
1055          }
1056 #endif
1057          loadShaders(display.displaySystem, "<:ecere>shaders/fixed.vertex", "<:ecere>shaders/fixed.frag");
1058       }
1059 #if ENABLE_GL_LEGACY
1060       else
1061       {
1062          glDisableVertexAttribArray(GLBufferContents::color);
1063          glDisableVertexAttribArray(GLBufferContents::normal);
1064          glDisableVertexAttribArray(GLBufferContents::texCoord);
1065          glDisableVertexAttribArray(GLBufferContents::vertex);
1066          glBindVertexArray(0);
1067          glUseProgram(0);
1068       }
1069 #endif
1070
1071 #endif
1072
1073 #if ENABLE_GL_VAO
1074       if(glCaps_vao)
1075          glBindVertexArray(oglDisplay.vao);
1076 #endif
1077
1078       GLEnableClientState(VERTICES);
1079
1080       GLABBindBuffer(GL_ARRAY_BUFFER, 0);
1081       GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1082
1083 #if defined(__WIN32__)
1084       if(glBlendFuncSeparate)
1085          glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1086       else
1087          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1088 #else
1089       glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1090 #endif
1091       glEnable(GL_BLEND);
1092
1093       GLMatrixMode(MatrixMode::texture);
1094       GLLoadIdentity();
1095
1096       GLMatrixMode(MatrixMode::modelView);
1097       GLLoadIdentity(); // For setting up GLES stack
1098       GLScaled(1.0, 1.0, -1.0);
1099       // glTranslatef(0.375f, 0.375f, 0.0f);
1100       // glTranslatef(-0.625f, -0.625f, 0.0f);
1101       GLMatrixMode(MatrixMode::projection);
1102       GLLoadIdentity();
1103       if(display.width && display.height)
1104          GLOrtho(0,display.width,display.height,0,0.0,1.0);
1105
1106 #if ENABLE_GL_FFP
1107       if(!glCaps_shaders)
1108       {
1109          glShadeModel(GL_FLAT);
1110          /*
1111          #define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
1112          GLLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1113          */
1114 #if !defined(_GLES)
1115          GLLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1116 #endif
1117          glFogi(GL_FOG_MODE, GL_EXP);
1118          glFogf(GL_FOG_DENSITY, 0);
1119          glEnable(GL_NORMALIZE);
1120       }
1121 #endif
1122       glDepthFunc(GL_LESS);
1123       glClearDepth(1.0);
1124 #if !defined(__EMSCRIPTEN__)
1125       glDisable(GL_MULTISAMPLE);
1126 #endif
1127
1128 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
1129       display.ambient = Color { 50,50,50 };
1130 #endif
1131       return result;
1132    }
1133
1134    bool CreateDisplay(Display display)
1135    {
1136       bool result = false;
1137       OGLDisplay oglDisplay = display.driverData;
1138       OGLSystem oglSystem = display.displaySystem.driverData;
1139
1140       if(!oglDisplay)
1141          oglDisplay = display.driverData = OGLDisplay { };
1142       oglDisplay.capabilities = oglSystem.capabilities;
1143
1144 #if defined(__WIN32__) || defined(USEPBUFFER)
1145       if(!display.alphaBlend)
1146 #endif
1147       {
1148 #if defined(__WIN32__)
1149          oglDisplay.hdc = GetDC(display.window);
1150          SetPixelFormat(oglDisplay.hdc, oglSystem.format, &oglSystem.pfd);
1151          if((oglDisplay.glrc = winCreateContext(oglDisplay.hdc, &oglDisplay.version, &oglDisplay.compat, (*&display.glCapabilities).compatible)))
1152          {
1153             wglShareLists(oglSystem.glrc, oglDisplay.glrc);
1154             wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
1155             result = true;
1156          }
1157          else
1158             ReleaseDC(display.window, oglDisplay.hdc);
1159 #elif defined(__unix__) || defined(__APPLE__)
1160 #  if defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__ODROID__)
1161          result = true;
1162 #  else
1163          XVisualInfo * visualInfo = ((XWindowData)display.windowDriverData).visual;
1164          /*
1165 #if defined(__APPLE__)
1166          XVisualInfo template = { 0 };
1167          XWindowAttributes winAttr;
1168          int n;
1169          XGetWindowAttributes(xGlobalDisplay, (X11Window)display.window, &winAttr);
1170          template.visualid = XVisualIDFromVisual(winAttr.visual);
1171          visualInfo = XGetVisualInfo(xGlobalDisplay, VisualIDMask, &template, &n);
1172 #ifdef _DEBUG
1173          printf("XGetVisualInfo visual ID = %d\n", template.visualid);
1174          printf("visualInfo visual ID = %d\n", visualInfo->visualid);
1175          printf("oglSystem.visualInfo visual ID = %d\n", oglSystem.visualInfo->visualid);
1176          printf("((XWindowData)display.windowDriverData).visual visual ID = %d\n", ((XWindowData)display.windowDriverData).visual->visualid);
1177 #endif
1178          // visualInfo = oglSystem.visualInfo;
1179 //#endif
1180          */
1181 #if !defined(__APPLE__)
1182          oglDisplay.compat = true;
1183          oglDisplay.version = 4;
1184 #endif
1185
1186          if(visualInfo)
1187          {
1188             //printf("visualInfo is not null\n");
1189             // printf("Creating Display Context, sharing with %x!\n", oglSystem.glContext);
1190             oglDisplay.glContext = glXCreateContext(xGlobalDisplay, visualInfo, oglSystem.glContext, True);
1191             //XFree(visualInfo);
1192          }
1193
1194          // oglDisplay.glContext = glXCreateContext(xGlobalDisplay, oglSystem.visualInfo, oglSystem.glContext, True);
1195          if(oglDisplay.glContext)
1196          {
1197             //printf("CreateDisplay Got a Context\n");
1198             glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext);
1199             result = true;
1200          }
1201 #  endif
1202 #endif
1203       }
1204 #if defined(__WIN32__) || defined(USEPBUFFER)
1205       else
1206       {
1207          result = true;
1208          wglMakeCurrent(oglSystem.hdc, oglSystem.glrc);
1209       }
1210 #endif
1211       if(result)
1212       {
1213 #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
1214
1215 #ifdef DIAGNOSTICS
1216          PrintLn("Calling ogl_LoadFunctions() in CreateDisplay()");
1217 #endif
1218          if(ogl_LoadFunctions() == ogl_LOAD_FAILED)
1219             PrintLn("ogl_LoadFunctions() failed!");
1220
1221 #ifdef DIAGNOSTICS
1222          PrintLn("CheckCapabilities()");
1223 #endif
1224          CheckCapabilities(oglSystem, oglDisplay);
1225
1226 #ifdef DIAGNOSTICS
1227          PrintLn("vboAvailable is: ", vboAvailable);
1228 #endif
1229
1230 #  ifdef GL_DEBUGGING
1231          if(oglDisplay.capabilities.debug)
1232             setupDebugging();
1233 #else
1234          oglDisplay.capabilities.debug = false;
1235 #  endif
1236
1237 #endif
1238
1239 #if defined(__EMSCRIPTEN__)
1240          emscripten_webgl_make_context_current(oglSystem.glc);
1241 #endif
1242
1243          if(result)
1244          {
1245             GLCapabilities capabilities = *&display.glCapabilities;
1246             // PrintLn("Available OpenGL Capabilities: ", oglDisplay.capabilities);
1247             // PrintLn("Desired OpenGL Capabilities: ", capabilities);
1248
1249             oglDisplay.originalCapabilities = oglDisplay.capabilities;
1250
1251             // Re-enable glCaps_shaders if no fixed function support
1252             if(!oglDisplay.capabilities.fixedFunction)
1253                capabilities.shaders = true;
1254             // Re-enable fixed function if no glCaps_shaders support
1255             if(!oglDisplay.capabilities.shaders)
1256             {
1257                capabilities.fixedFunction = true;
1258                capabilities.shaders = false;
1259             }
1260
1261             // Disable things that don't work with glCaps_shaders
1262             if(capabilities.shaders)
1263             {
1264                capabilities.fixedFunction = false;
1265                capabilities.legacy = false;
1266                capabilities.immediate = false;
1267             }
1268
1269             #if !ENABLE_GL_POINTER
1270             // Re-enable vertex buffer if no pointer support
1271             capabilities.vertexBuffer = true;
1272             #endif
1273
1274             oglDisplay.capabilities &= capabilities;
1275
1276             // PrintLn("Selected OpenGL Capabilities: ", oglDisplay.capabilities);
1277             oglSystem.capabilities = oglDisplay.capabilities;
1278          }
1279
1280 #if ENABLE_GL_VAO
1281          if(oglDisplay.capabilities.vao)
1282          {
1283             glGenVertexArrays(1, &oglDisplay.vao);
1284             glBindVertexArray(oglDisplay.vao);
1285          }
1286 #endif
1287
1288          initialDisplaySetup(display);
1289       }
1290
1291       if(!useSingleGLContext)
1292       {
1293    #if defined(__WIN32__)
1294          wglMakeCurrent(null, null);
1295    #elif defined(__unix__) || defined(__APPLE__)
1296       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
1297          result = true;
1298       #else
1299          glXMakeCurrent(xGlobalDisplay, None, null);
1300       #endif
1301    #endif
1302       }
1303       else
1304       {
1305       #if defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__ODROID__)
1306          result = true;
1307       #endif
1308       }
1309       return result;
1310    }
1311
1312    bool DisplaySize(Display display, int width, int height)
1313    {
1314       OGLDisplay oglDisplay = display.driverData;
1315       bool result = false;
1316
1317 #if defined(__WIN32__) || defined(USEPBUFFER)
1318       OGLSystem oglSystem = display.displaySystem.driverData;
1319       if(display.alphaBlend)
1320       {
1321 #if defined(__WIN32__)
1322          const int attributes[]=
1323          {
1324             /*WGL_TEXTURE_FORMAT_ARB, WGL_TEXTURE_RGBA_ARB,
1325             WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_2D_ARB, */0
1326          };
1327          int pixelFormat = 0;
1328          if(wglChoosePixelFormatARB)
1329          {
1330             int valid;
1331             int numFormats;
1332             float fAttributes[] = {0,0};
1333             int iAttributes[] =
1334             {
1335                //WGL_DRAW_TO_BITMAP_ARB, GL_TRUE,
1336                WGL_DRAW_TO_PBUFFER_ARB,GL_TRUE,
1337                WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
1338                WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
1339                WGL_COLOR_BITS_ARB,24,
1340                WGL_ALPHA_BITS_ARB,8,
1341                WGL_DEPTH_BITS_ARB,16,
1342                WGL_STENCIL_BITS_ARB,0,
1343                WGL_DOUBLE_BUFFER_ARB,GL_FALSE,
1344                WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
1345                WGL_SAMPLES_ARB, 4,                  // Check For 4x Multisampling
1346                0,0
1347             };
1348
1349             //Log("Found wglChoosePixelFormatARB\n");
1350
1351             valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
1352             if(!valid || !numFormats)
1353             {
1354                //Log("Can't find 4x multi sampling\n");
1355                iAttributes[19] = 2;
1356                valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
1357                if(!valid || !numFormats)
1358                {
1359                   // Log("Can't find 2x multi sampling\n");
1360                   iAttributes[16] = 0;
1361                   iAttributes[17] = 0;
1362                   valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
1363                   if(!valid || !numFormats)
1364                   {
1365                      int iAttributes[] =
1366                      {
1367                         WGL_DRAW_TO_PBUFFER_ARB,GL_TRUE,
1368                         //WGL_DRAW_TO_BITMAP_ARB,GL_TRUE,
1369                         WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
1370                         WGL_COLOR_BITS_ARB,24,
1371                         WGL_ALPHA_BITS_ARB,8,
1372                         WGL_DEPTH_BITS_ARB,16,
1373                         0,0
1374                      };
1375                      valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
1376                   }
1377                }
1378             }
1379             if(valid && numFormats)
1380             {
1381                wglMakeCurrent(null, null);
1382             }
1383          }
1384
1385          wglMakeCurrent( null, null );
1386          wglMakeCurrent( oglDisplay.hdc, oglDisplay.glrc );
1387          if(oglDisplay.hdc && oglDisplay.pBuffer)
1388             wglReleasePbufferDCARB(oglDisplay.pBuffer, oglDisplay.hdc);
1389
1390          wglDestroyPbufferARB(oglDisplay.pBuffer);
1391
1392          if(!useSingleGLContext)
1393             wglMakeCurrent( null, null );
1394
1395          if(oglDisplay.glrc)
1396             wglDeleteContext(oglDisplay.glrc);
1397
1398          oglDisplay.pBuffer = wglCreatePbufferARB(oglSystem.hdc, pixelFormat, width, height, attributes);
1399          oglDisplay.hdc = wglGetPbufferDCARB(oglDisplay.pBuffer);
1400          if((oglDisplay.glrc = winCreateContext(oglDisplay.hdc, null, null, oglDisplay.capabilities.compatible)))
1401          {
1402             BITMAPINFO * info;
1403             HDC hdc = GetDC(display.window);
1404
1405             wglShareLists(oglSystem.glrc, oglDisplay.glrc);
1406             wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
1407
1408             //wglQueryPbufferARB(pBuffer, WGL_PBUFFER_WIDTH_ARB, &width);
1409             //wglQueryPbufferARB(pBuffer, WGL_PBUFFER_HEIGHT_ARB, &height);
1410
1411             // glDeleteBuffersARB(2, oglDisplay.imageBuffers);
1412
1413             if((info = (BITMAPINFO *)new0 byte[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256]))
1414             {
1415                HBITMAP newBitmap;
1416
1417                if(oglDisplay.memDC) DeleteDC(oglDisplay.memDC);
1418                oglDisplay.memDC = CreateCompatibleDC(hdc);
1419                SetMapMode(oglDisplay.memDC, MM_TEXT);
1420                info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1421                info->bmiHeader.biPlanes = 1;
1422                info->bmiHeader.biCompression = BI_RGB;
1423                info->bmiHeader.biBitCount = 32; //(uint16)GetDeviceCaps(hdc, BITSPIXEL);
1424                info->bmiHeader.biWidth = width;
1425                info->bmiHeader.biHeight = height;
1426                newBitmap = CreateDIBSection(hdc, info, DIB_RGB_COLORS, &oglDisplay.picture, null, 0);
1427                if(newBitmap)
1428                {
1429                   SelectObject(oglDisplay.memDC, newBitmap);
1430                   if(oglDisplay.memBitmap) DeleteObject(oglDisplay.memBitmap);
1431                   /*
1432                   {
1433                      PIXELFORMATDESCRIPTOR pfd = { 0 };
1434                      pfd.nSize = (short)sizeof(pfd);
1435                      pfd.nVersion = 1;
1436                      pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL;
1437                      pfd.iPixelType = PFD_TYPE_RGBA;
1438                      pfd.cColorBits = 32;
1439                      //pfd.cAlphaBits = 8;
1440                      pfd.cDepthBits = 24;
1441                      pfd.iLayerType = PFD_MAIN_PLANE;
1442
1443                      oglDisplay.hdc = oglDisplay.memDC;
1444
1445                      pixelFormat = ChoosePixelFormat(oglSystem.hdc, &pfd);
1446                      DescribePixelFormat(oglDisplay.hdc, pixelFormat, sizeof(pfd), &pfd);
1447                      SetPixelFormat(oglDisplay.hdc, pixelFormat, &pfd);
1448
1449                      oglDisplay.glrc = wglCreateContext(oglDisplay.hdc);
1450                      wglShareLists(oglSystem.glrc, oglDisplay.glrc);
1451                      wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
1452                   }
1453                   */
1454                   /*
1455                   {
1456                      const int imageSize = width * height * 4;
1457
1458                      glGenBuffersARB(2, oglDisplay.imageBuffers);
1459
1460                      glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[0]);
1461                      glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, imageSize, null, GL_STREAM_READ);
1462                      // glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[1]);
1463                      // glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, imageSize / 2, null, GL_STREAM_READ);
1464                   }
1465                   */
1466                   oglDisplay.memBitmap = newBitmap;
1467                   oglDisplay.stride = width;
1468
1469                   result = true;
1470                }
1471                delete info;
1472             }
1473             ReleaseDC(display.window, hdc);
1474          }
1475 #elif defined(__unix__) || defined(__APPLE__)
1476       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
1477          result = true;
1478       #else
1479          int attrib[] =
1480          {
1481             GLX_DOUBLEBUFFER,  True,
1482             GLX_DEPTH_SIZE,    1,
1483             GLX_RED_SIZE,      8,
1484             GLX_GREEN_SIZE,    8,
1485             GLX_BLUE_SIZE,     8,
1486             GLX_ALPHA_SIZE,    8,
1487             GLX_STENCIL_SIZE,  1,
1488             //GLX_DEPTH_SIZE,    24,
1489             GLX_RENDER_TYPE,   GLX_RGBA_BIT,
1490             GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT,
1491             None
1492          };
1493
1494          int PBattrib[] =
1495          {
1496             GLX_PBUFFER_WIDTH,   width,
1497             GLX_PBUFFER_HEIGHT,  height,
1498             GLX_LARGEST_PBUFFER, False,
1499             None
1500          };
1501
1502          // choose a pixel format that meets our minimum requirements
1503          int count = 0;
1504
1505          GLXFBConfig *config = glXChooseFBConfig(xGlobalDisplay, DefaultScreen(xGlobalDisplay), attrib, &count);
1506          if(config)
1507          {
1508             if(oglDisplay.pixmap)
1509             {
1510                XFreePixmap(xGlobalDisplay, oglDisplay.pixmap);
1511                oglDisplay.pixmap = None;
1512             }
1513             if(oglDisplay.shapePixmap)
1514             {
1515                XFreePixmap(xGlobalDisplay, oglDisplay.shapePixmap);
1516                oglDisplay.shapePixmap = None;
1517             }
1518
1519             // Free Shared Memory Pixmap
1520             if(oglDisplay.image)
1521             {
1522                if(oglDisplay.shminfoShape.shmid != -1)
1523                {
1524                   XShmDetach(xGlobalDisplay, &oglDisplay.shminfo);
1525                   if(oglDisplay.shminfo.shmaddr != (void *)-1)
1526                      shmdt(oglDisplay.shminfo.shmaddr);
1527                   shmctl(oglDisplay.shminfo.shmid, IPC_RMID, 0);
1528                }
1529                XDestroyImage(oglDisplay.image);
1530                oglDisplay.image = None;
1531             }
1532             if(oglDisplay.shapeImage)
1533             {
1534                if(oglDisplay.shminfoShape.shmid != -1)
1535                {
1536                   XShmDetach(xGlobalDisplay, &oglDisplay.shminfoShape);
1537                   if(oglDisplay.shminfoShape.shmaddr != (void *)-1)
1538                      shmdt(oglDisplay.shminfoShape.shmaddr);
1539                   shmctl(oglDisplay.shminfoShape.shmid, IPC_RMID, 0);
1540                }
1541                XDestroyImage(oglDisplay.shapeImage);
1542                oglDisplay.shapeImage = None;
1543             }
1544
1545             if(oglDisplay.windowPicture)
1546                XRenderFreePicture(xGlobalDisplay, oglDisplay.windowPicture);
1547             if(oglDisplay.pixmapPicture)
1548                XRenderFreePicture(xGlobalDisplay, oglDisplay.pixmapPicture);
1549
1550             if(oglDisplay.pixmap)
1551                XFreePixmap(xGlobalDisplay, oglDisplay.pixmap);
1552
1553             if(oglDisplay.glContext)
1554               glXDestroyContext(xGlobalDisplay, oglDisplay.glContext);
1555             if(oglDisplay.pBuffer)
1556                glXDestroyPbuffer(xGlobalDisplay, oglDisplay.pBuffer);
1557
1558             oglDisplay.pBuffer = glXCreatePbuffer(xGlobalDisplay, config[0], PBattrib);
1559             if(oglDisplay.pBuffer)
1560             {
1561                oglDisplay.glContext = glXCreateNewContext(xGlobalDisplay, config[0], GLX_RGBA_TYPE, oglSystem.glContext, True);
1562                if(oglDisplay.glContext)
1563                {
1564                   glXMakeCurrent(xGlobalDisplay, None, null);
1565                   glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext);
1566
1567                   // Initialize Shared Memory Pixmap
1568                   oglDisplay.image = XShmCreateImage(xGlobalDisplay, DefaultVisual(xGlobalDisplay, DefaultScreen(xGlobalDisplay)), 32,
1569                      ZPixmap, null, &oglDisplay.shminfo, width, height);
1570                   if(oglDisplay.image)
1571                   {
1572                      oglDisplay.shminfo.shmid = shmget(IPC_PRIVATE,
1573                         oglDisplay.image->bytes_per_line * oglDisplay.image->height, IPC_CREAT|0777);
1574                      if(oglDisplay.shminfo.shmid != -1)
1575                      {
1576                         oglDisplay.shminfo.shmaddr = shmat(oglDisplay.shminfo.shmid, 0, 0);
1577                         if(oglDisplay.shminfo.shmaddr != (void *)-1)
1578                         {
1579                            oglDisplay.shminfo.readOnly = False;
1580                            if(XShmAttach(xGlobalDisplay, &oglDisplay.shminfo))
1581                            {
1582                               oglDisplay.pixmap = XShmCreatePixmap(xGlobalDisplay, (X11Window)display.window, oglDisplay.shminfo.shmaddr,
1583                                  &oglDisplay.shminfo, width, height, 32);
1584
1585                               // Initialize Shared Memory Shape Pixmap
1586                               oglDisplay.shapeImage = XShmCreateImage(xGlobalDisplay, DefaultVisual(xGlobalDisplay, DefaultScreen(xGlobalDisplay)), 1,
1587                                  ZPixmap, null, &oglDisplay.shminfoShape, width, height);
1588                               if(oglDisplay.shapeImage)
1589                               {
1590                                  oglDisplay.shminfoShape.shmid = shmget(IPC_PRIVATE,
1591                                     oglDisplay.shapeImage->bytes_per_line * oglDisplay.shapeImage->height, IPC_CREAT|0777);
1592                                  if(oglDisplay.shminfoShape.shmid != -1)
1593                                  {
1594                                     oglDisplay.shminfoShape.shmaddr = shmat(oglDisplay.shminfoShape.shmid, 0, 0);
1595                                     if(oglDisplay.shminfoShape.shmaddr != (void *)-1)
1596                                     {
1597                                        oglDisplay.shminfoShape.readOnly = False;
1598                                        if(XShmAttach(xGlobalDisplay, &oglDisplay.shminfoShape))
1599                                        {
1600                                           oglDisplay.shapePixmap = XShmCreatePixmap(xGlobalDisplay, (X11Window)display.window, oglDisplay.shminfoShape.shmaddr,
1601                                              &oglDisplay.shminfoShape, width, height, 1);
1602                                           //oglDisplay.shapePixmap = XCreatePixmap(xGlobalDisplay, (X11Window)display.window, width, height, 1);
1603
1604                                           {
1605                                              XRenderPictureAttributes attributes = { 0 };
1606                                              XRenderPictFormat * format = XRenderFindStandardFormat(xGlobalDisplay, /*PictStandardRGB24*/ PictStandardARGB32);
1607                                              #if !defined(__APPLE__)
1608                                              attributes.repeat = RepeatNormal;
1609                                              #else
1610                                              attributes.repeat = 1;
1611                                              #endif
1612                                              oglDisplay.pixmapPicture = XRenderCreatePicture(xGlobalDisplay, oglDisplay.pixmap, format, CPRepeat, &attributes);
1613                                              oglDisplay.windowPicture = XRenderCreatePicture(xGlobalDisplay, (X11Window)display.window, format, 0, &attributes);
1614                                              oglDisplay.shapePicture = XRenderCreatePicture(xGlobalDisplay, oglDisplay.shapePixmap,
1615                                                 XRenderFindStandardFormat(xGlobalDisplay, PictStandardA1), 0, &attributes);
1616                                           }
1617
1618                                           oglDisplay.picture = oglDisplay.shminfo.shmaddr;
1619                                           oglDisplay.stride = oglDisplay.image->bytes_per_line / 4;
1620
1621                                           result = true;
1622                                        }
1623                                     }
1624                                  }
1625                               }
1626                            }
1627                         }
1628                      }
1629                   }
1630                }
1631             }
1632             XFree(config);
1633          }
1634      #endif
1635 #endif
1636          CreateDisplay(display);
1637 #if defined(__WIN32__)
1638          wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
1639 #elif defined(__unix__) || defined(__APPLE__)
1640       #if defined(__ANDROID__) || defined(__ODROID__)
1641          width = eglWidth;
1642          height = eglHeight;
1643       #elif defined(__EMSCRIPTEN__)
1644          emscripten_webgl_make_context_current(oglSystem.glc);
1645       #else
1646          glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext);
1647       #endif
1648 #endif
1649       }
1650       else
1651 #endif
1652          result = true;
1653
1654       SETCAPS(oglDisplay.capabilities);
1655
1656       if(display.alphaBlend && result)
1657          initialDisplaySetup(display);
1658
1659       if(!result && display.alphaBlend)
1660       {
1661          printf("Alpha blending windows not supported on this display\n");
1662       }
1663       if(!result)
1664          return false;
1665
1666       result = false;
1667
1668       glViewport(0,0,width,height);
1669       GLMatrixMode(MatrixMode::projection);
1670       GLLoadIdentity();
1671       GLOrtho(0,width,height,0,0.0,1.0);
1672       displayWidth = display.width = width;
1673       displayHeight = display.height = height;
1674
1675       if(!oglDisplay.flippingBuffer || oglDisplay.flipBufW < width || oglDisplay.flipBufH < height)
1676       {
1677          oglDisplay.flipBufW = width;
1678          oglDisplay.flipBufH = height;
1679 #if defined(_GLES) || defined(_GLES2)
1680          result = true;
1681 #else
1682          oglDisplay.flippingBuffer = renew oglDisplay.flippingBuffer ColorAlpha [width * height];
1683 #endif
1684       }
1685       if(oglDisplay.flippingBuffer || !width || !height)
1686          result = true;
1687
1688       return result;
1689    }
1690
1691    void DisplayPosition(Display display, int x, int y)
1692    {
1693       OGLDisplay oglDisplay = display.driverData;
1694
1695       oglDisplay.x = x;
1696       oglDisplay.y = y;
1697    }
1698
1699    void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
1700    {
1701    }
1702
1703    void RestorePalette(Display display)
1704    {
1705    }
1706
1707    void StartUpdate(Display display)
1708    {
1709 #if ENABLE_GL_VAO
1710       if(glCaps_vao)
1711       {
1712          OGLDisplay oglDisplay = display.driverData;
1713          glBindVertexArray(oglDisplay.vao);
1714       }
1715 #endif
1716       GLABBindBuffer(GL_ARRAY_BUFFER, 0);
1717       GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1718    }
1719
1720    void EndUpdate(Display display)
1721    {
1722    }
1723
1724    void Scroll(Display display, Box scroll, int x, int y, Extent dirty)
1725    {
1726    }
1727
1728    void Update(Display display, Box updateBox)
1729    {
1730 #if defined(__WIN32__) || defined(USEPBUFFER)
1731       OGLDisplay oglDisplay = display.driverData;
1732 #endif
1733
1734 #if !defined(__ANDROID__)
1735       /*glFlush();
1736       glFinish();*/
1737 #endif
1738
1739 #if defined(__WIN32__) || defined(USEPBUFFER)
1740       if(display.alphaBlend)
1741       {
1742          glPixelStorei(GL_PACK_ALIGNMENT, 4);
1743          glPixelStorei(GL_PACK_ROW_LENGTH, oglDisplay.stride);
1744          glPixelStorei(GL_PACK_SKIP_ROWS, 0);
1745          glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
1746          glReadPixels(0,0,display.width,display.height,GL_BGRA_EXT,GL_UNSIGNED_BYTE, oglDisplay.picture);
1747
1748          {
1749 #if defined(__WIN32__)
1750             HDC hdc = GetDC(0);
1751             POINT point = { oglDisplay.x, oglDisplay.y};
1752             POINT srcPoint = { 0, 0 };
1753             BLENDFUNCTION blend = { 0 };
1754             SIZE size;
1755             size.cx = display.width;
1756             size.cy = display.height;
1757             blend.BlendOp = AC_SRC_OVER;
1758             blend.BlendFlags = 0;
1759             blend.SourceConstantAlpha = 255;
1760             blend.AlphaFormat = AC_SRC_ALPHA;
1761
1762             /*
1763             // Process partial images.  Mapping the buffer waits for
1764             // outstanding DMA transfers into the buffer to finish.
1765             glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[0]);
1766             oglDisplay.pboMemory1 = (byte *)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
1767
1768             // glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[1]);
1769             // oglDisplay.pboMemory2 = (byte *)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB,GL_READ_ONLY);
1770
1771
1772             memcpy(oglDisplay.picture, oglDisplay.pboMemory1, display.width * display.height * 4);
1773             //memcpy(oglDisplay.picture + display.width * display.height * 4 / 2, oglDisplay.pboMemory2, display.width * display.height * 4/ 2);
1774             */
1775
1776             UpdateLayeredWindow(display.window, hdc, &point, &size, oglDisplay.memDC, &srcPoint, 0, &blend, ULW_ALPHA);
1777             /*
1778
1779             // Unmap the image buffers
1780             glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[0]);
1781             glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
1782
1783             // glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[1]);
1784             // glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
1785
1786             // Bind two different buffer objects and start the glReadPixels
1787             // asynchronously. Each call will return directly after
1788             // starting the DMA transfer.
1789             glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[0]);
1790             glReadPixels(0, 0, display.width, display.height, GL_BGRA, GL_UNSIGNED_BYTE, 0);
1791
1792             // glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[1]);
1793             // glReadPixels(0, display.height/2, display.width, display.height/2, GL_BGRA, GL_UNSIGNED_BYTE, 0);
1794             */
1795
1796             ReleaseDC(0, hdc);
1797 #elif defined(__unix__) || defined(__APPLE__)
1798       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
1799       #else
1800             XTransform transform =
1801             {
1802                {
1803                   { (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)),  (int)(0 * (1 << 16)) },
1804                   { (int)(0.0f),           (int)(-1.0f * (1<<16)), (int)(0 * (1<<16)) },
1805                   { (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)),  (int)(1.0f * (1<<16)) }
1806                }
1807             };
1808             XRenderSetPictureTransform(xGlobalDisplay, oglDisplay.pixmapPicture, &transform);
1809             XRenderComposite(xGlobalDisplay, PictOpSrc, oglDisplay.pixmapPicture, None, oglDisplay.shapePicture, 0, 0, 0, 0, 0, 0, display.width, display.height);
1810             XRenderComposite(xGlobalDisplay, PictOpSrc, oglDisplay.pixmapPicture, None, oglDisplay.windowPicture, 0, 0, 0, 0, 0, 0, display.width, display.height);
1811             #if !defined(__APPLE__)
1812             XShapeCombineMask(xGlobalDisplay, (X11Window)display.window, ShapeInput, 0, 0, oglDisplay.shapePixmap, ShapeSet);
1813             #else
1814             XShapeCombineMask(xGlobalDisplay, display.window, 2, 0, 0, oglDisplay.shapePixmap, ShapeSet);
1815             #endif
1816             XFlush(xGlobalDisplay);
1817      #endif
1818 #endif
1819          }
1820       }
1821       else
1822 #endif
1823       {
1824 #if defined(__WIN32__)
1825          //wglSwapLayerBuffers(oglDisplay.hdc,WGL_SWAP_MAIN_PLANE);
1826          SwapBuffers(oglDisplay.hdc);
1827          //ecere::sys::Sleep(0.1);
1828 #elif defined(__unix__) || defined(__APPLE__)
1829       #if defined(__ANDROID__) || defined(__ODROID__)
1830          egl_swap_buffers();
1831       #elif defined(__EMSCRIPTEN__)
1832       #else
1833          glXSwapBuffers(xGlobalDisplay, (GLXDrawable)display.window);
1834       #endif
1835 #endif
1836       }
1837    }
1838
1839    void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
1840    {
1841       if(bitmap.driverData)
1842       {
1843          GLuint tex = (GLuint)(uintptr)bitmap.driverData;
1844          glDeleteTextures(1, &tex);
1845          bitmap.driverData = 0;
1846       }
1847       bitmap.driver = ((subclass(DisplayDriver))class(LFBDisplayDriver));
1848    }
1849
1850    bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
1851    {
1852       OGLSystem oglSystem = displaySystem.driverData;
1853       GLCapabilities capabilities = oglSystem.capabilities;
1854       bool result = false;
1855       Bitmap mipMap { };
1856       GLuint glBitmap = 0;
1857
1858       uint w = width, h = height;
1859       if(!capabilities.nonPow2Textures)
1860       {
1861          w = pow2i(w);
1862          h = pow2i(h);
1863       }
1864       w = Min(w, oglSystem.maxTextureSize);
1865       h = Min(h, oglSystem.maxTextureSize);
1866
1867       glGenTextures(1, &glBitmap);
1868       glBindTexture(GL_TEXTURE_2D, glBitmap);
1869
1870       glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
1871
1872       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1873       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1874
1875       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1876       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1877
1878 #if ENABLE_GL_FFP
1879       if(!capabilities.shaders)
1880          glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1881 #endif
1882
1883       mipMap.Allocate(null, w, h, w, pixelFormatRGBA, false);
1884
1885       // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture);
1886       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture);
1887
1888       delete mipMap;
1889
1890       bitmap.driverData = (void *)(uintptr)glBitmap;
1891       bitmap.driver = displaySystem.driver;
1892       bitmap.width = w;
1893       bitmap.height = h;
1894
1895       result = true;
1896       return result;
1897    }
1898
1899    bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
1900    {
1901       bool result = false;
1902       OGLSystem oglSystem = displaySystem.driverData;
1903       GLCapabilities capabilities = oglSystem.capabilities;
1904       Bitmap convBitmap = bitmap;
1905       if(bitmap.keepData)
1906       {
1907          convBitmap = { };
1908          convBitmap.Copy(bitmap);
1909       }
1910
1911       // Pre process the bitmap... First make it 32 bit
1912       if(/*bitmap.pixelFormat == pixelFormatRGBA || */convBitmap.Convert(null, pixelFormat888, null))
1913       {
1914          int c, level;
1915          uint w = bitmap.width, h = bitmap.height;
1916          GLuint glBitmap = 0;
1917          if(!capabilities.nonPow2Textures)
1918          {
1919             w = pow2i(w);
1920             h = pow2i(h);
1921          }
1922          w = Min(w, oglSystem.maxTextureSize);
1923          h = Min(h, oglSystem.maxTextureSize);
1924
1925          if(mipMaps)
1926          {
1927             while(w * 2 < h) w *= 2;
1928             while(h * 2 < w) h *= 2;
1929          }
1930
1931          // Switch ARGB to RGBA
1932          //if(bitmap.format != pixelFormatRGBA)
1933          {
1934             for(c=0; c<bitmap.size; c++)
1935             {
1936                // ((ColorRGBA *)bitmap.picture)[c] = ((ColorAlpha *)bitmap.picture)[c];
1937                // TODO:
1938                ColorAlpha color = ((ColorAlpha *)convBitmap.picture)[c];
1939                ((ColorRGBA *)convBitmap.picture)[c] = ColorRGBA { color.color.r, color.color.g, color.color.b, color.a };
1940             }
1941          }
1942          // convBitmap.pixelFormat = pixelFormat888;
1943
1944          glGetError();
1945          glGenTextures(1, &glBitmap);
1946          if(glBitmap == 0)
1947          {
1948             //int error = glGetError();
1949             return false;
1950          }
1951
1952          glBindTexture(GL_TEXTURE_2D, glBitmap);
1953          glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
1954
1955          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mipMaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
1956          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1957
1958          //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1959
1960          //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1961          //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1962
1963          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1964          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1965 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
1966          glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0 );
1967 #endif
1968
1969 #if ENABLE_GL_FFP
1970       if(!capabilities.shaders)
1971          glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1972 #endif
1973
1974          result = true;
1975
1976          for(level = 0; result && (w >= 1 || h >= 1); level++, w >>= 1, h >>= 1)
1977          {
1978             Bitmap mipMap;
1979             if(!w) w = 1;
1980             if(!h) h = 1;
1981             if(bitmap.width != w || bitmap.height != h)
1982             {
1983                mipMap = Bitmap { };
1984                if(mipMap.Allocate(null, w, h, w, convBitmap.pixelFormat, false))
1985                {
1986                   Surface mipSurface = mipMap.GetSurface(0,0,null);
1987                   mipSurface.Filter(convBitmap, 0,0,0,0, w, h, convBitmap.width, convBitmap.height);
1988                   delete mipSurface;
1989                }
1990                else
1991                {
1992                   result = false;
1993                   delete mipMap;
1994                }
1995             }
1996             else
1997                mipMap = convBitmap;
1998
1999             if(result)
2000             {
2001                int error;
2002                //int width = 0;
2003                glGetError();
2004                // glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture);
2005                glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture);
2006                //printf("Calling glTexImage2D\n");
2007                //glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, &width);
2008                //printf("width = %d (Should be %d, %d)\n", width, w, h);
2009                if((error = glGetError()))
2010                {
2011                   //Logf("OpenGL Bitmap MakeDD error: %d...\n", error);
2012                   //printf("OpenGL Bitmap MakeDD error: %d...\n", error);
2013                   result = false;
2014                }
2015             }
2016             if(mipMap != convBitmap)
2017                delete mipMap;
2018             if(!mipMaps) break;
2019          }
2020
2021          convBitmap.driver.FreeBitmap(convBitmap.displaySystem, convBitmap);
2022          bitmap.driverData = (void *)(uintptr)glBitmap;
2023          bitmap.driver = displaySystem.driver;
2024          if(bitmap.keepData)
2025             delete convBitmap;
2026
2027          if(!result)
2028             FreeBitmap(displaySystem, bitmap);
2029          else if(oglSystem.loadingFont)
2030          {
2031             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2032             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2033             oglSystem.loadingFont = false;
2034          }
2035       }
2036       return result;
2037    }
2038
2039    void ReleaseSurface(Display display, Surface surface)
2040    {
2041       glDisable(GL_SCISSOR_TEST);
2042       delete surface.driverData;
2043       surface.driverData = null;
2044    }
2045
2046    bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x, int y, Box clip)
2047    {
2048       return false;
2049    }
2050
2051    bool GetSurface(Display display, Surface surface, int x,int y, Box clip)
2052    {
2053       bool result = false;
2054       OGLDisplay oglDisplay = display.driverData;
2055       OGLSurface oglSurface = surface.driverData = OGLSurface { };
2056       if(oglSurface)
2057       {
2058          SETCAPS(oglDisplay.capabilities);
2059          if(displayWidth != display.width || displayHeight != display.height)
2060          {
2061             displayWidth = display.width;
2062             displayHeight = display.height;
2063
2064             glViewport(0,0,display.width,display.height);
2065             GLLoadIdentity();
2066             GLOrtho(0,display.width,display.height,0,0.0,1.0);
2067          }
2068
2069          surface.offset.x = x;
2070          surface.offset.y = y;
2071          surface.unclippedBox = surface.box = clip;
2072          oglSurface.bitmapMult[0] = 1;
2073          oglSurface.bitmapMult[1] = 1;
2074          oglSurface.bitmapMult[2] = 1;
2075          oglSurface.bitmapMult[3] = 1;
2076
2077          glEnable(GL_SCISSOR_TEST);
2078          glScissor(
2079             x+clip.left,
2080             (display.height) -(y+clip.bottom)-1,
2081             clip.right-clip.left+1,
2082             clip.bottom-clip.top+1);
2083          result = true;
2084       }
2085       return result;
2086    }
2087
2088    void Clip(Display display, Surface surface, Box clip)
2089    {
2090       Box box;
2091
2092       if(clip != null)
2093       {
2094          box = clip;
2095          box.Clip(surface.unclippedBox);
2096          surface.box = box;
2097       }
2098       else
2099          box = surface.box = surface.unclippedBox;
2100       box.left += surface.offset.x;
2101       box.top  += surface.offset.y;
2102       box.right+= surface.offset.x;
2103       box.bottom += surface.offset.y;
2104
2105       glScissor(
2106          box.left,display.height - box.bottom - 1,
2107          box.right-box.left+1, box.bottom-box.top+1);
2108    }
2109
2110    bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
2111    {
2112       bool result = false;
2113       OGLDisplay oglDisplay = display.driverData;
2114       ColorAlpha * flippingBuffer = oglDisplay.flippingBuffer;
2115
2116       if(oglDisplay.flippingBuffer)
2117       {
2118          if(bitmap.pixelFormat != pixelFormat888 || bitmap.width < w || bitmap.height < h)
2119          {
2120             bitmap.Free();
2121             bitmap.Allocate(null, w,h,w, pixelFormat888, false);
2122          }
2123          if(bitmap)
2124          {
2125             uint row;
2126
2127             glPixelStorei(GL_PACK_ALIGNMENT, 4);
2128 #if ENABLE_GL_LEGACY
2129             glPixelStorei(GL_PACK_ROW_LENGTH, bitmap.stride);
2130             glPixelStorei(GL_PACK_SKIP_ROWS, 0);
2131             glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
2132 #endif
2133             glReadPixels(x,display.height-h-y,w,h,GL_BGRA_EXT,GL_UNSIGNED_BYTE, flippingBuffer);
2134
2135             // Need a flip...
2136             for(row = 0; row<h; row++)
2137                CopyBytesBy4(((ColorAlpha *)bitmap.picture) + row * w, ((ColorAlpha *)flippingBuffer) + (h-row-1) * w, w);
2138             result = true;
2139          }
2140       }
2141       return result;
2142    }
2143
2144    void SetForeground(Display display, Surface surface, ColorAlpha color)
2145    {
2146       OGLSurface oglSurface = surface.driverData;
2147
2148       oglSurface.foreground[0] = color.color.r/255.0f;
2149       oglSurface.foreground[1] = color.color.g/255.0f;
2150       oglSurface.foreground[2] = color.color.b/255.0f;
2151       //oglSurface.foreground[3] = 1.0f;
2152       oglSurface.foreground[3] = color.a/255.0f;
2153
2154       //if(!oglSurface.foreground[3])printf("bug");
2155    }
2156
2157    void SetBackground(Display display, Surface surface, ColorAlpha color)
2158    {
2159       OGLSurface oglSurface = surface.driverData;
2160
2161       oglSurface.background[0] = color.color.r/255.0f;
2162       oglSurface.background[1] = color.color.g/255.0f;
2163       oglSurface.background[2] = color.color.b/255.0f;
2164       //oglSurface.background[3] = 1.0;
2165       oglSurface.background[3] = color.a/255.0f;
2166    }
2167
2168    void SetBlitTint(Display display, Surface surface, ColorAlpha color)
2169    {
2170       OGLSurface oglSurface = surface.driverData;
2171
2172       oglSurface.bitmapMult[0] = color.color.r/255.0f;
2173       oglSurface.bitmapMult[1] = color.color.g/255.0f;
2174       oglSurface.bitmapMult[2] = color.color.b/255.0f;
2175       oglSurface.bitmapMult[3] = color.a/255.0f;
2176    }
2177
2178    ColorAlpha GetPixel(Display display, Surface surface,int x,int y)
2179    {
2180       return 0;
2181    }
2182
2183    void PutPixel(Display display, Surface surface,int x,int y)
2184    {
2185       OGLSurface oglSurface = surface.driverData;
2186       GLColor4fv(oglSurface.foreground);
2187       GLBegin(GL_POINTS);
2188       // glVertex2i(x+surface.offset.x, y+surface.offset.y);
2189       GLVertex2f(x+surface.offset.x + 0.5f, y+surface.offset.y + 0.5f);
2190       GLEnd();
2191    }
2192
2193    void DrawLine(Display display, Surface surface, int _x1, int _y1, int _x2, int _y2)
2194    {
2195       OGLSurface oglSurface = surface.driverData;
2196       float x1 = _x1, x2 = _x2, y1 = _y1, y2 = _y2;
2197       if(_x1 == _x2)
2198       {
2199          if(_y2 >= _y1)
2200             y2 += 1;
2201          else
2202             y1 += 1;
2203       }
2204       else if(_y1 == _y2)
2205       {
2206          if(_x2 >= _x1)
2207             x2 += 1;
2208          else
2209             x1 += 1;
2210       }
2211       x1 += surface.offset.x;
2212       y1 += surface.offset.y;
2213       x2 += surface.offset.x;
2214       y2 += surface.offset.y;
2215
2216       GLColor4fv(oglSurface.foreground);
2217       GLBegin(GL_LINES);
2218       if(stippleEnabled)
2219       {
2220          GLTexCoord2f(0.5f, 0);
2221          GLVertex2f(x1 + 0.5f, y1 + 0.5f);
2222          GLTexCoord2f(Max(x2-x1, y2-y1) + 0.5f, 0);
2223          GLVertex2f(x2 + 0.5f, y2 + 0.5f);
2224       }
2225       else
2226       {
2227          /*
2228          GLVertex2i(x1, y1);
2229          GLVertex2i(x2, y2);
2230          */
2231          GLVertex2f(x1 + 0.5f, y1 + 0.5f);
2232          GLVertex2f(x2 + 0.5f, y2 + 0.5f);
2233       }
2234
2235       GLEnd();
2236    }
2237
2238    void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
2239    {
2240       OGLSurface oglSurface = surface.driverData;
2241       x1 += surface.offset.x;
2242       y1 += surface.offset.y;
2243       x2 += surface.offset.x;
2244       y2 += surface.offset.y;
2245
2246       GLColor4fv(oglSurface.foreground);
2247       if(stippleEnabled)
2248       {
2249          GLBegin(GL_LINES);
2250
2251          GLTexCoord2f(0.5f, 0);
2252          GLVertex2f(x1 + 0.5f, y1 + 0.5f);
2253          GLTexCoord2f(y2-y1 + 0.5f, 0);
2254          GLVertex2f(x1 + 0.5f, y2 + 0.5f);
2255
2256          GLTexCoord2f(0.5f, 0);
2257          GLVertex2f(x1 + 0.5f, y2 + 0.5f);
2258          GLTexCoord2f(x2 - x1 + 0.5f, 0);
2259          GLVertex2f(x2 + 0.5f, y2 + 0.5f);
2260
2261          GLTexCoord2f(0.5f, 0);
2262          GLVertex2f(x2 + 0.5f, y2 + 0.5f);
2263          GLTexCoord2f(y1 - y2 + 0.5f, 0);
2264          GLVertex2f(x2 + 0.5f, y1 + 0.5f);
2265
2266          GLTexCoord2f(0.5f, 0);
2267          GLVertex2f(x2 + 0.5f, y1 + 0.5f);
2268          GLTexCoord2f(x1 - x2 + 0.5f, 0);
2269          GLVertex2f(x1 + 0.5f, y1 + 0.5f);
2270       }
2271       else
2272       {
2273          GLBegin(GL_LINE_LOOP);
2274          /*
2275          glVertex2i(x1, y1);
2276          glVertex2i(x1, y2);
2277          glVertex2i(x2, y2);
2278          glVertex2i(x2, y1);
2279          */
2280          GLVertex2f(x1 + 0.5f, y1 + 0.5f);
2281          GLVertex2f(x1 + 0.5f, y2 + 0.5f);
2282          GLVertex2f(x2 + 0.5f, y2 + 0.5f);
2283          GLVertex2f(x2 + 0.5f, y1 + 0.5f);
2284       }
2285       GLEnd();
2286    }
2287
2288    void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
2289    {
2290       OGLSurface oglSurface = surface.driverData;
2291
2292       GLColor4fv(oglSurface.background);
2293
2294       GLRecti(x1+surface.offset.x, y1+surface.offset.y,
2295               x2+surface.offset.x + 1, y2+surface.offset.y + 1);
2296       /*
2297       GLRectf(x1+surface.offset.x, y1+surface.offset.y,
2298               x2+surface.offset.x + 1, y2+surface.offset.y + 1);
2299       */
2300    }
2301
2302    void Clear(Display display, Surface surface, ClearType type)
2303    {
2304       OGLDisplay oglDisplay = display.driverData;
2305       OGLSurface oglSurface = surface.driverData;
2306
2307       //Logf("Clear\n");
2308       if(type != depthBuffer)
2309          glClearColor(oglSurface.background[0], oglSurface.background[1], oglSurface.background[2], oglSurface.background[3]);
2310       if(type != colorBuffer && !oglDisplay.depthWrite)
2311       {
2312          glDepthMask((byte)bool::true);
2313       }
2314       glClear(((type != depthBuffer) ? GL_COLOR_BUFFER_BIT : 0) |
2315               ((type != colorBuffer) ? GL_DEPTH_BUFFER_BIT : 0));
2316       if(type != colorBuffer && !oglDisplay.depthWrite)
2317       {
2318          glDepthMask((byte)bool::false);
2319       }
2320    }
2321
2322    bool ConvertBitmap(DisplaySystem displaySystem, Bitmap bitmap, PixelFormat format, ColorAlpha * palette)
2323    {
2324       return true;
2325    }
2326
2327    void Blit(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h)
2328    {
2329       OGLSurface oglSurface = surface.driverData;
2330       GLuint tex = (GLuint)(uintptr)bitmap.driverData;
2331       if(!tex) return;
2332
2333       if(!oglSurface.writingText)
2334       {
2335          // glTranslatef(-0.375f, -0.375f, 0.0f);
2336          GLSetupTexturing(true);
2337          GLColor4fv(oglSurface.bitmapMult);
2338          glBindTexture(GL_TEXTURE_2D, tex);
2339          GLBegin(GLIMTKMode::quads);
2340       }
2341       else if(lastBlitTex != tex)
2342       {
2343          if(lastBlitTex)
2344             GLEnd();
2345          glBindTexture(GL_TEXTURE_2D, tex);
2346          GLBegin(GLIMTKMode::quads);
2347          lastBlitTex = tex;
2348       }
2349
2350       if(h < 0)
2351       {
2352          GLTexCoord2f((float)sx/ bitmap.width, (float)(sy-h)/ bitmap.height);
2353          GLVertex2i(dx+surface.offset.x, dy+surface.offset.y);
2354          GLTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy-h)/ bitmap.height);
2355          GLVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
2356          GLTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height);
2357          GLVertex2i(dx+w+surface.offset.x, dy-h+surface.offset.y);
2358          GLTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height);
2359          GLVertex2i(dx+surface.offset.x, dy-h+surface.offset.y);
2360       }
2361       else
2362       {
2363          /*
2364          GLTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height);
2365          GLVertex2i(dx+surface.offset.x, dy+surface.offset.y);
2366          GLTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height);
2367          GLVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
2368          GLTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy+h)/ bitmap.height);
2369          GLVertex2i(dx+w+surface.offset.x, dy+h+surface.offset.y);
2370          GLTexCoord2f((float)sx/ bitmap.width, (float)(sy+h)/ bitmap.height);
2371          GLVertex2i(dx+surface.offset.x, dy+h+surface.offset.y);
2372          */
2373
2374          GLTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height);
2375          GLVertex2f((float)dx+surface.offset.x, (float)dy+surface.offset.y);
2376          GLTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height);
2377          GLVertex2f((float)dx+w+surface.offset.x, (float)dy+surface.offset.y);
2378          GLTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy+h)/ bitmap.height);
2379          GLVertex2f((float)dx+w+surface.offset.x, (float)dy+h+surface.offset.y);
2380          GLTexCoord2f((float)sx/ bitmap.width, (float)(sy+h)/ bitmap.height);
2381          GLVertex2f((float)dx+surface.offset.x, (float)dy+h+surface.offset.y);
2382       }
2383       if(!oglSurface.writingText)
2384       {
2385          GLEnd();
2386          GLSetupTexturing(false);
2387          //glTranslate(0.375, 0.375, 0.0);
2388       }
2389    }
2390
2391    void Stretch(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2392    {
2393       OGLSurface oglSurface = surface.driverData;
2394
2395       //glTranslate(-0.375, -0.375, 0.0);
2396
2397       GLSetupTexturing(true);
2398       glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)bitmap.driverData);
2399
2400       GLColor4fv(oglSurface.bitmapMult);
2401
2402       GLBegin(GLIMTKMode::quads);
2403
2404       if(h < 0)
2405       {
2406          GLTexCoord2f((float)(sx)/ bitmap.width, (float)(sy+sh)/ bitmap.height);
2407          GLVertex2i(dx+surface.offset.x, dy+surface.offset.y);
2408
2409          GLTexCoord2f((float)(sx+sw) / bitmap.width, (float)(sy+sh)/ bitmap.height);
2410          GLVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
2411
2412          GLTexCoord2f((float)(sx+sw)/ bitmap.width, (float)(sy)/ bitmap.height);
2413          GLVertex2i(dx+w+surface.offset.x, dy-h+surface.offset.y);
2414
2415          GLTexCoord2f((float)(sx) / bitmap.width, (float)(sy)/ bitmap.height);
2416          GLVertex2i(dx+surface.offset.x, dy-h+surface.offset.y);
2417       }
2418       else
2419       {
2420          GLTexCoord2f((float)(sx) / bitmap.width, (float)(sy)/ bitmap.height);
2421          GLVertex2i(dx+surface.offset.x, dy+surface.offset.y);
2422
2423          GLTexCoord2f((float)(sx+sw)/ bitmap.width, (float)(sy)/ bitmap.height);
2424          GLVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
2425
2426          GLTexCoord2f((float)(sx+sw) / bitmap.width, (float)(sy+sh)/ bitmap.height);
2427          GLVertex2i(dx+w+surface.offset.x, dy+h+surface.offset.y);
2428
2429          GLTexCoord2f((float)(sx)/ bitmap.width, (float)(sy+sh)/ bitmap.height);
2430          GLVertex2i(dx+surface.offset.x, dy+h+surface.offset.y);
2431       }
2432
2433       GLEnd();
2434
2435       GLSetupTexturing(false);
2436
2437       //glTranslate(0.375, 0.375, 0.0);
2438    }
2439
2440    void Filter(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2441    {
2442       Stretch(display, surface, bitmap, dx, dy, sx, sy, w, h, sw, sh);
2443    }
2444
2445    void StretchDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2446    {
2447       float s2dw,s2dh,d2sw,d2sh;
2448       //bool flipX = false, flipY = false;
2449
2450       if(Sgn(w) != Sgn(sw))
2451       {
2452          w = Abs(w);
2453          sw = Abs(sw);
2454          //flipX = true;
2455       }
2456       if(Sgn(h) != Sgn(sh))
2457       {
2458          h = Abs(h);
2459          sh = Abs(sh);
2460          //flipY = true;
2461       }
2462
2463       s2dw=(float)w / sw;
2464       s2dh=(float)h / sh;
2465       d2sw=(float)sw / w;
2466       d2sh=(float)sh / h;
2467
2468       //Clip against the edges of the source
2469       if(sx<0)
2470       {
2471          dx+=(int)((0-sx) * s2dw);
2472          w-=(int)((0-sx) * s2dw);
2473          sw-=0-sx;
2474          sx=0;
2475       }
2476       if(sy<0)
2477       {
2478          dy+=(int)((0-sy) * s2dh);
2479          h-=(int)((0-sy) * s2dh);
2480
2481          sh-=0-sy;
2482          sy=0;
2483       }
2484       if(sx+sw>bitmap.width-1)
2485       {
2486          w-=(int)((sx+sw-(bitmap.width-1)-1)*s2dw);
2487          sw-=sx+sw-(bitmap.width-1)-1;
2488       }
2489       if(sy+sh>(bitmap.height-1))
2490       {
2491          h-=(int)((sy+sh-(bitmap.height-1)-1)*s2dh);
2492          sh-=sy+sh-(bitmap.height-1)-1;
2493       }
2494       //Clip against the edges of the surfaceination
2495       if(dx<surface.box.left)
2496       {
2497          //if(!flip)
2498          sx+=(int)((surface.box.left-dx)*d2sw);
2499          sw-=(int)((surface.box.left-dx)*d2sw);
2500          w-=surface.box.left-dx;
2501          dx=surface.box.left;
2502       }
2503       if(dy<surface.box.top)
2504       {
2505          sy+=(int)((surface.box.top-dy)*d2sh);
2506          sh-=(int)((surface.box.top-dy)*d2sh);
2507          h-=surface.box.top-dy;
2508          dy=surface.box.top;
2509       }
2510       if(dx+w>surface.box.right)
2511       {
2512          //if(flip) sx+=(int)((dx+w-surface.box.right-1)*d2sw);
2513          sw-=(int)((dx+w-surface.box.right-1)*d2sw);
2514          w-=dx+w-surface.box.right-1;
2515       }
2516       if(dy+h>surface.box.bottom)
2517       {
2518          sh-=(int)((dy+h-surface.box.bottom-1)*d2sh);
2519          h-=dy+h-surface.box.bottom-1;
2520       }
2521       if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2522
2523       dx += surface.offset.x;
2524       dy += surface.offset.y;
2525
2526       if(bitmap.pixelFormat == pixelFormat888 && !bitmap.paletteShades)
2527       {
2528          glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
2529 #if ENABLE_GL_LEGACY
2530          if(glCaps_legacy)
2531          {
2532             glPixelStorei(GL_UNPACK_ROW_LENGTH, bitmap.stride);
2533             glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx);
2534             glPixelStorei(GL_UNPACK_SKIP_ROWS, sy);
2535             glRasterPos2d(dx,dy);
2536             //glPixelZoom(flipX ? -s2dw : s2dw, flipY ? s2dh : -s2dh);
2537             glPixelZoom(s2dw, -s2dh);
2538             glDrawPixels(sw,sh,GL_BGRA_EXT,GL_UNSIGNED_BYTE, bitmap.picture);
2539             glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
2540             glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
2541             glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
2542          }
2543 #endif
2544          glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2545       }
2546    }
2547
2548    void BlitDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h)
2549    {
2550       //Clip against the edges of the source
2551       if(sx<0)
2552       {
2553          dx+=-sx;
2554          w-=-sx;
2555          sx=0;
2556       }
2557       if(sy<0)
2558       {
2559          dy+=0-sy;
2560          h-=0-sy;
2561          sy=0;
2562       }
2563       if(sx+w>bitmap.width-1)
2564          w-=sx+w-(bitmap.width-1)-1;
2565       if(sy+h>bitmap.height-1)
2566          h-=sy+h-(bitmap.height-1)-1;
2567       //Clip against the edges of the surfaceination
2568       if(dx<surface.box.left)
2569       {
2570          //if(!flip)
2571          sx+=surface.box.left-dx;
2572          w-=surface.box.left-dx;
2573          dx=surface.box.left;
2574       }
2575       if(dy<surface.box.top)
2576       {
2577          sy+=surface.box.top-dy;
2578          h-=surface.box.top-dy;
2579          dy=surface.box.top;
2580       }
2581       if(dx+w>surface.box.right)
2582       {
2583          //if(flip) sx+=dx+w-surface.box.right-1;
2584          w-=dx+w-surface.box.right-1;
2585       }
2586       if(dy+h>surface.box.bottom)
2587          h-=dy+h-surface.box.bottom-1;
2588       if((w<=0)||(h<=0))
2589          return;
2590
2591       dx += surface.offset.x;
2592       dy += surface.offset.y;
2593
2594       if(bitmap.pixelFormat == pixelFormat888 && !bitmap.paletteShades)
2595       {
2596          glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
2597 #if ENABLE_GL_LEGACY
2598          if(glCaps_legacy)
2599          {
2600             glPixelStorei(GL_UNPACK_ROW_LENGTH, bitmap.stride);
2601             glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx);
2602             glPixelStorei(GL_UNPACK_SKIP_ROWS, sy);
2603             glRasterPos2d(dx,dy);
2604             glPixelZoom(1,-1);
2605             glDrawPixels(w,h,GL_BGRA_EXT,GL_UNSIGNED_BYTE, bitmap.picture);
2606             glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
2607             glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
2608             glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
2609          }
2610 #endif
2611          glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2612       }
2613    }
2614
2615    void FilterDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2616    {
2617       StretchDI(display, surface, bitmap, dx, dy, sx, sy, w, h, sw, sh);
2618    }
2619
2620    void UnloadFont(DisplaySystem displaySystem, Font font)
2621    {
2622       ((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, font);
2623    }
2624
2625    Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
2626    {
2627       Font font;
2628       OGLSystem oglSystem = displaySystem.driverData;
2629       oglSystem.loadingFont = true;
2630       font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags, outlineSize, outlineFade);
2631       return font;
2632    }
2633
2634    void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * adv)
2635    {
2636       ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(displaySystem, font, text, len, width, height, prevGlyph, rPrevGlyph, adv);
2637    }
2638
2639    void WriteText(Display display, Surface surface, int x, int y, const char * text, int len, int prevGlyph, int * rPrevGlyph)
2640    {
2641       if(len && text[0])
2642       {
2643          OGLSurface oglSurface = surface.driverData;
2644          OGLSystem oglSystem = display.displaySystem.driverData;
2645          oglSystem.loadingFont = true;
2646
2647          //glTranslated(-0.375, -0.375, 0.0);
2648
2649          if(surface.textOpacity)
2650          {
2651             int w = 0, h, adv = 0;
2652             FontExtent(display.displaySystem, surface.font, text, len, &w, &h, 0, null, &adv);
2653             w += adv;
2654             display.displaySystem.driver.Area(display, surface,x,y,x+w-1,y+h-1);
2655          }
2656
2657          oglSurface.writingText = true;
2658
2659          GLSetupTexturing(true);
2660
2661          if(surface.font.outlineSize)
2662          {
2663             ColorAlpha outlineColor = surface.outlineColor;
2664             GLColor4ub(outlineColor.color.r, outlineColor.color.g, outlineColor.color.b, outlineColor.a);
2665             oglSurface.writingOutline = true;
2666             lastBlitTex = 0;
2667             ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len, prevGlyph, rPrevGlyph);
2668             if(lastBlitTex) GLEnd();
2669             oglSurface.writingOutline = false;
2670          }
2671          GLColor4fv(oglSurface.foreground);
2672
2673          lastBlitTex = 0;
2674          ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len, prevGlyph, rPrevGlyph);
2675          if(lastBlitTex) GLEnd();
2676          lastBlitTex = 0;
2677
2678          oglSurface.writingText = false;
2679          oglSystem.loadingFont = false;
2680
2681          GLSetupTexturing(false);
2682
2683          //glTranslated(0.375, 0.375, 0.0);
2684       }
2685    }
2686
2687    void TextFont(Display display, Surface surface, Font font)
2688    {
2689       ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextFont(display, surface, font);
2690    }
2691
2692    void TextOpacity(Display display, Surface surface, bool opaque)
2693    {
2694       OGLSurface oglSurface = surface.driverData;
2695       oglSurface.opaqueText = opaque;
2696    }
2697
2698    void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * adv)
2699    {
2700       OGLSurface oglSurface = surface.driverData;
2701       OGLSystem oglSystem = display.displaySystem.driverData;
2702       oglSystem.loadingFont = true;
2703       FontExtent(display.displaySystem, oglSurface.font, text, len, width, height, prevGlyph, rPrevGlyph, adv);
2704       oglSystem.loadingFont = false;
2705    }
2706
2707    void DrawingChar(Display display, Surface surface, char character)
2708    {
2709
2710    }
2711
2712    void LineStipple(Display display, Surface surface, uint32 stipple)
2713    {
2714       if(stipple)
2715       {
2716 #if ENABLE_GL_LEGACY
2717          if(glCaps_legacy)
2718          {
2719             glLineStipple(1, (uint16)stipple);
2720             glEnable(GL_LINE_STIPPLE);
2721          }
2722          else
2723 #endif
2724          {
2725             stippleEnabled = true;
2726             glsupLineStipple(1, (uint16)stipple);
2727          }
2728       }
2729       else
2730       {
2731 #if ENABLE_GL_LEGACY
2732          if(glCaps_legacy)
2733             glDisable(GL_LINE_STIPPLE);
2734          else
2735 #endif
2736          {
2737             stippleEnabled = false;
2738             GLMatrixMode(GL_TEXTURE);
2739             GLLoadIdentity();
2740             GLMatrixMode(MatrixMode::projection);
2741             GLSetupTexturing(false);   // TODO: Special shading code for stipple?
2742          }
2743       }
2744    }
2745
2746 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
2747    void SetRenderState(Display display, RenderState state, uint value)
2748    {
2749       OGLDisplay oglDisplay = display.driverData;
2750       switch(state)
2751       {
2752          case antiAlias:
2753 #ifndef __EMSCRIPTEN__
2754             if(value)
2755                glEnable(GL_MULTISAMPLE);
2756             else
2757                glDisable(GL_MULTISAMPLE);
2758 #endif
2759             break;
2760          case fillMode:
2761 #if ENABLE_GL_LEGACY
2762             if(glCaps_legacy)
2763                glPolygonMode(GL_FRONT_AND_BACK, ((FillModeValue)value == solid) ? GL_FILL : GL_LINE);
2764 #endif
2765             break;
2766          case depthTest:
2767             if(value) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
2768             break;
2769          case depthWrite:
2770             if(value) glDepthMask((byte)bool::true); else glDepthMask((byte)bool::false);
2771             oglDisplay.depthWrite = (bool)value;
2772             break;
2773          case fogColor:
2774          {
2775             float color[4] = { ((Color)value).r/255.0f, ((Color)value).g/255.0f, ((Color)value).b/255.0f, 1.0f };
2776 #if ENABLE_GL_SHADERS
2777             if(glCaps_shaders)
2778                shader_fogColor(color[0], color[1], color[2]);
2779 #endif
2780
2781 #if ENABLE_GL_FFP
2782             if(!glCaps_shaders)
2783                glFogfv(GL_FOG_COLOR, (float *)&color);
2784 #endif
2785             break;
2786          }
2787          case fogDensity:
2788 #if ENABLE_GL_SHADERS
2789             if(glCaps_shaders)
2790                shader_fogDensity((float)(RenderStateFloat { ui = value }.f * nearPlane));
2791 #endif
2792
2793 #if ENABLE_GL_FFP
2794             if(!glCaps_shaders)
2795                glFogf(GL_FOG_DENSITY, (float)(RenderStateFloat { ui = value }.f * nearPlane));
2796 #endif
2797             break;
2798          case blend:
2799 //#if !defined(__EMSCRIPTEN__)
2800             if(value) glEnable(GL_BLEND); else glDisable(GL_BLEND);
2801 //#endif
2802             break;
2803          case ambient:
2804          {
2805 #if ENABLE_GL_SHADERS
2806             if(glCaps_shaders)
2807                shader_setGlobalAmbient(((Color)value).r / 255.0f, ((Color)value).g / 255.0f, ((Color)value).b / 255.0f, 1.0f);
2808 #endif
2809
2810 #if ENABLE_GL_FFP
2811             if(!glCaps_shaders)
2812             {
2813                float ambient[4] = { ((Color)value).r/255.0f, ((Color)value).g/255.0f, ((Color)value).b/255.0f, 1.0f };
2814                glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
2815             }
2816 #endif
2817             break;
2818          }
2819          case alphaWrite:
2820          {
2821             if(value) glColorMask(1,1,1,1); else glColorMask(1,1,1,0);
2822             break;
2823          }
2824          case vSync:
2825          {
2826 #if defined(__WIN32__)
2827             if(wglSwapIntervalEXT)
2828                wglSwapIntervalEXT(value ? 1 : 0);
2829 #endif
2830             break;
2831          }
2832       }
2833    }
2834
2835    void SetLight(Display display, int id, Light light)
2836    {
2837 #if ENABLE_GL_SHADERS
2838       if(glCaps_shaders)
2839          shader_setLight(display, id, light);
2840 #endif
2841
2842 #if ENABLE_GL_FFP
2843       if(!glCaps_shaders)
2844       {
2845          if(light != null)
2846          {
2847             Object lightObject = light.lightObject;
2848             float position[4] = { 0, 0, 0, 0 };
2849             float color[4] = { 0, 0, 0, 1 };
2850
2851             glEnable(GL_LIGHT0 + id);
2852
2853             if(!light.multiplier) light.multiplier = 1.0f;
2854
2855             color[0] = light.diffuse.r * light.multiplier;
2856             color[1] = light.diffuse.g * light.multiplier;
2857             color[2] = light.diffuse.b * light.multiplier;
2858             glLightfv(GL_LIGHT0 + id, GL_DIFFUSE, color);
2859
2860             color[0] = light.ambient.r * light.multiplier;
2861             color[1] = light.ambient.g * light.multiplier;
2862             color[2] = light.ambient.b * light.multiplier;
2863             glLightfv(GL_LIGHT0 + id, GL_AMBIENT, color);
2864             color[0] = light.specular.r * light.multiplier;
2865             color[1] = light.specular.g * light.multiplier;
2866             color[2] = light.specular.b * light.multiplier;
2867             glLightfv(GL_LIGHT0 + id, GL_SPECULAR,color);
2868
2869             if(lightObject)
2870             {
2871                Vector3D positionVector;
2872                if(light.flags.spot)
2873                {
2874                   if(lightObject.flags.root || !lightObject.parent)
2875                   {
2876                      positionVector = lightObject.transform.position;
2877                      positionVector.Subtract(positionVector, display.display3D.camera.cPosition);
2878                   }
2879                   else
2880                   {
2881                      positionVector.MultMatrix(lightObject.transform.position, lightObject.parent.matrix);
2882                      if(display.display3D.camera)
2883                         positionVector.Subtract(positionVector, display.display3D.camera.cPosition);
2884                   }
2885                   position[3] = 1;
2886                }
2887                else
2888                {
2889                   if(!light.direction.x && !light.direction.y && !light.direction.z)
2890                   {
2891                      Vector3Df vector { 0,0,-1 };
2892                      Matrix mat;
2893                      mat.RotationQuaternion(light.orientation);
2894                      positionVector.MultMatrixf(vector, mat);
2895                   }
2896                   else
2897                   {
2898                      positionVector = light.direction;
2899                      position[3] = 1;
2900                   }
2901                }
2902
2903                position[0] = (float)positionVector.x;
2904                position[1] = (float)positionVector.y;
2905                position[2] = (float)positionVector.z;
2906
2907                glLightfv(GL_LIGHT0 + id, GL_POSITION, position);
2908
2909                /*
2910                // Display Light Position
2911                glDisable(GL_LIGHTING);
2912                glDisable(GL_DEPTH_TEST);
2913                glColor3f(1,1,1);
2914                glPointSize(10);
2915                glBegin(GL_POINTS);
2916                glVertex3fv(position);
2917                glEnd();
2918                glEnable(GL_DEPTH_TEST);
2919                glEnable(GL_LIGHTING);
2920
2921
2922                // Display Target
2923                if(lightObject.flags.root || !lightObject.parent)
2924                {
2925                   positionVector = light.target.transform.position;
2926                   positionVector.Subtract(positionVector, display.camera.cPosition);
2927                }
2928                else
2929                {
2930                   positionVector.MultMatrix(light.target.transform.position,
2931                      lightObject.light.target.parent.matrix);
2932                   positionVector.Subtract(positionVector, display.camera.cPosition);
2933                }
2934
2935                position[0] = positionVector.x;
2936                position[1] = positionVector.y;
2937                position[2] = positionVector.z;
2938
2939                glDisable(GL_LIGHTING);
2940                glDisable(GL_DEPTH_TEST);
2941                glColor3f(1,1,0);
2942                glPointSize(10);
2943                glBegin(GL_POINTS);
2944                glVertex3fv(position);
2945                glEnd();
2946                glEnable(GL_DEPTH_TEST);
2947                glEnable(GL_LIGHTING);
2948                */
2949
2950                if(light.flags.attenuation)
2951                {
2952                   glLightf(GL_LIGHT0 + id, GL_CONSTANT_ATTENUATION, light.Kc);
2953                   glLightf(GL_LIGHT0 + id, GL_LINEAR_ATTENUATION, light.Kl);
2954                   glLightf(GL_LIGHT0 + id, GL_QUADRATIC_ATTENUATION, light.Kq);
2955                }
2956
2957                if(light.flags.spot)
2958                {
2959                   float exponent = 0;
2960                   #define MAXLIGHT  0.9
2961                   float direction[4] = { (float)light.direction.x, (float)light.direction.y, (float)light.direction.z, 1 };
2962                   // Figure out exponent out of the hot spot
2963                   exponent = (float)(log(MAXLIGHT) / log(cos((light.hotSpot / 2))));
2964
2965                   glLightfv(GL_LIGHT0 + id, GL_SPOT_DIRECTION, direction);
2966                   glLightf(GL_LIGHT0 + id, GL_SPOT_CUTOFF, (float)(light.fallOff / 2));
2967                   glLightf(GL_LIGHT0 + id, GL_SPOT_EXPONENT, exponent);
2968                }
2969             }
2970             else
2971             {
2972                Vector3Df vector { 0,0,-1 };
2973                Vector3Df direction;
2974                Matrix mat;
2975
2976                mat.RotationQuaternion(light.orientation);
2977                direction.MultMatrix(vector, mat);
2978
2979                position[0] = direction.x;
2980                position[1] = direction.y;
2981                position[2] = direction.z;
2982
2983                glLightfv(GL_LIGHT0 + id, GL_POSITION, position);
2984             }
2985          }
2986          else
2987             glDisable(GL_LIGHT0 + id);
2988       }
2989 #endif
2990    }
2991
2992    void SetCamera(Display display, Surface surface, Camera camera)
2993    {
2994       OGLDisplay oglDisplay = display.driverData;
2995
2996       if(surface && camera)
2997       {
2998          int left = surface.box.left + surface.offset.x;
2999          int top = surface.box.top  + surface.offset.y;
3000          int right = surface.box.right + surface.offset.x;
3001          int bottom = surface.box.bottom + surface.offset.y;
3002          float origX = surface.offset.x + camera.origin.x;
3003          float origY = surface.offset.y + camera.origin.y;
3004          int x = left;
3005          int y = display.height - bottom - 1;
3006          int w = right - left + 1;
3007          int h = bottom - top + 1;
3008
3009          // *** ViewPort ***
3010          glViewport(x, y, w, h);
3011
3012          // *** Projection Matrix ***
3013          GLMatrixMode(MatrixMode::projection);
3014          if(!display.display3D.camera)
3015             GLPushMatrix();
3016
3017          if(display.display3D.collectingHits)
3018          {
3019             float pickX = display.display3D.pickX + surface.offset.x;
3020             float pickY = display.height - (display.display3D.pickY + surface.offset.y) - 1;
3021             Matrix pickMatrix
3022             {
3023                {
3024                   w / display.display3D.pickWidth, 0, 0, 0,
3025                   0, h / display.display3D.pickHeight, 0, 0,
3026                   0, 0, 1, 0,
3027                   (w + 2.0f * (x - pickX)) / display.display3D.pickWidth,
3028                   (h + 2.0f * (y - pickY)) / display.display3D.pickHeight, 0, 1
3029                }
3030             };
3031             GLLoadMatrixd(pickMatrix.array);
3032          }
3033          else
3034             GLLoadIdentity();
3035          GLFrustum(
3036             (left   - origX) * camera.zMin / camera.focalX,
3037             (right  - origX) * camera.zMin / camera.focalX,
3038             (bottom - origY) * camera.zMin / camera.focalY,
3039             (top    - origY) * camera.zMin / camera.focalY,
3040             camera.zMin, camera.zMax);
3041
3042          glDisable(GL_BLEND);
3043
3044          // *** Z Inverted Identity Matrix ***
3045          GLMatrixMode(MatrixMode::modelView);
3046          if(!display.display3D.camera)
3047             GLPushMatrix();
3048
3049          GLLoadIdentity();
3050
3051          GLScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane);
3052
3053          // *** View Matrix ***
3054          GLMultMatrixd(camera.viewMatrix.array);
3055
3056          // *** Lights ***
3057          // ...
3058
3059          glEnable(GL_DEPTH_TEST);
3060
3061          GLSetupLighting(true);
3062 #if ENABLE_GL_FFP
3063          if(!glCaps_shaders)
3064             glShadeModel(GL_SMOOTH);
3065 #endif
3066          glDepthMask((byte)bool::true);
3067          oglDisplay.depthWrite = true;
3068
3069 #ifndef __EMSCRIPTEN__
3070          glEnable(GL_MULTISAMPLE);
3071 #endif
3072       }
3073       else if(surface && display.display3D.camera)
3074       {
3075          nearPlane = 1;
3076          oglDisplay.depthWrite = false;
3077          glViewport(0,0,display.width,display.height);
3078
3079          glDisable(GL_CULL_FACE);
3080          glDisable(GL_DEPTH_TEST);
3081
3082          GLSetupTexturing(false);
3083          GLSetupLighting(false);
3084          GLSetupFog(false);
3085
3086          GLDisableClientState(COLORS);
3087
3088 #if ENABLE_GL_SHADERS
3089          if(glCaps_shaders)
3090             shader_setPerVertexColor(false);
3091 #endif
3092
3093 #if ENABLE_GL_FFP
3094          if(!glCaps_shaders)
3095             glShadeModel(GL_FLAT);
3096 #endif
3097          glEnable(GL_BLEND);
3098 #if !defined(__EMSCRIPTEN__)
3099          glDisable(GL_MULTISAMPLE);
3100 #endif
3101
3102          // *** Restore 2D MODELVIEW Matrix ***
3103          GLPopMatrix();
3104
3105          // *** Restore 2D PROJECTION Matrix ***
3106          GLMatrixMode(MatrixMode::projection);
3107          GLPopMatrix();
3108       }
3109
3110    }
3111
3112    void ApplyMaterial(Display display, Material material, Mesh mesh)
3113    {
3114       // Basic Properties
3115       if(material.flags.doubleSided)
3116       {
3117 #if ENABLE_GL_FFP
3118          if(!glCaps_shaders)
3119             GLLightModeli(GL_LIGHT_MODEL_TWO_SIDE, !material.flags.singleSideLight);
3120 #endif
3121          glDisable(GL_CULL_FACE);
3122       }
3123       else
3124       {
3125 #if ENABLE_GL_FFP
3126          if(!glCaps_shaders)
3127             GLLightModeli(GL_LIGHT_MODEL_TWO_SIDE, bool::false);
3128 #endif
3129          glEnable(GL_CULL_FACE);
3130       }
3131
3132       // Fog
3133       GLSetupFog(!material.flags.noFog);
3134
3135       // Maps
3136       if(material.baseMap && (mesh.texCoords || mesh.flags.texCoords1))
3137       {
3138          Bitmap map = material.baseMap;
3139          GLSetupTexturing(true);
3140          glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)map.driverData);
3141
3142          GLMatrixMode(GL_TEXTURE);
3143          GLLoadIdentity();
3144          if(material.uScale && material.vScale)
3145             GLScalef(material.uScale, material.vScale, 1);
3146          GLMatrixMode(MatrixMode::modelView);
3147
3148          if(material.flags.tile)
3149          {
3150             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
3151             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
3152          }
3153          else
3154          {
3155             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3156             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3157          }
3158       }
3159       else
3160          GLSetupTexturing(false);
3161
3162 #if ENABLE_GL_SHADERS
3163       if(glCaps_shaders)
3164          shader_setMaterial(material, mesh.flags.colors);
3165 #endif
3166
3167 #if ENABLE_GL_FFP
3168       if(!glCaps_shaders)
3169       {
3170          if(mesh.flags.colors)
3171          {
3172             GLColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
3173             glEnable(GL_COLOR_MATERIAL);
3174          }
3175          else
3176          {
3177             glDisable(GL_COLOR_MATERIAL);
3178             {
3179                float color[4] = { material.diffuse.r, material.diffuse.g, material.diffuse.b, material.opacity };
3180                glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
3181             }
3182             {
3183                float color[4] = { material.ambient.r, material.ambient.g, material.ambient.b, 0 };
3184                glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
3185             }
3186          }
3187          {
3188             float color[4] = { material.specular.r, material.specular.g, material.specular.b, 0 };
3189             glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
3190          }
3191          {
3192             float color[4] = { material.emissive.r, material.emissive.g, material.emissive.b, 0 };
3193             glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color);
3194          }
3195
3196          glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &material.power);
3197       }
3198 #endif
3199    }
3200
3201    void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
3202    {
3203       OGLMesh oglMesh = mesh.data;
3204       if(oglMesh)
3205       {
3206          OGLSystem oglSystem = displaySystem.driverData;
3207          SETCAPS(oglSystem.capabilities);
3208          if(!mesh.flags.vertices)
3209          {
3210             oglMesh.vertices.free(glCaps_vertexBuffer);
3211             delete mesh.vertices;
3212          }
3213          if(!mesh.flags.normals)
3214          {
3215             oglMesh.normals.free(glCaps_vertexBuffer);
3216             delete mesh.normals;
3217          }
3218          if(!mesh.flags.texCoords1)
3219          {
3220             oglMesh.texCoords.free(glCaps_vertexBuffer);
3221             delete mesh.texCoords;
3222          }
3223          if(!mesh.flags.texCoords2)
3224          {
3225             oglMesh.texCoords2.free(glCaps_vertexBuffer);
3226             // delete mesh.texCoords2;
3227          }
3228          if(!mesh.flags.colors)
3229          {
3230             oglMesh.colors.free(glCaps_vertexBuffer);
3231             delete mesh.colors;
3232          }
3233          if(!mesh.flags)
3234          {
3235             delete oglMesh;
3236             mesh.data = null;
3237          }
3238       }
3239    }
3240
3241    bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags, int nVertices)
3242    {
3243       bool result = false;
3244
3245       if(!mesh.data)
3246          mesh.data = OGLMesh { };
3247       if(mesh.data)
3248       {
3249          if(mesh.nVertices == nVertices)
3250          {
3251             // Same number of vertices, adding features (Leaves the other features pointers alone)
3252             if(mesh.flags != flags)
3253             {
3254                if(!mesh.flags.vertices && flags.vertices)
3255                {
3256                   if(flags.doubleVertices)
3257                   {
3258                      mesh.vertices = (Vector3Df *)new Vector3D[nVertices];
3259                   }
3260                   else
3261                      mesh.vertices = new Vector3Df[nVertices];
3262                }
3263                if(!mesh.flags.normals && flags.normals)
3264                {
3265                   if(flags.doubleNormals)
3266                   {
3267                      mesh.normals = (Vector3Df *)new Vector3D[nVertices];
3268                   }
3269                   else
3270                      mesh.normals = new Vector3Df[nVertices];
3271                }
3272                if(!mesh.flags.texCoords1 && flags.texCoords1)
3273                {
3274                   mesh.texCoords = new Pointf[nVertices];
3275                }
3276                if(!mesh.flags.colors && flags.colors)
3277                {
3278                   mesh.colors = new ColorRGBAf[nVertices];
3279                }
3280             }
3281          }
3282          else
3283          {
3284             // New number of vertices, reallocate all current and new features
3285             flags |= mesh.flags;
3286             if(flags.vertices)
3287             {
3288                if(flags.doubleVertices)
3289                {
3290                   mesh.vertices = (Vector3Df *)renew mesh.vertices Vector3D[nVertices];
3291                }
3292                else
3293                   mesh.vertices = renew mesh.vertices Vector3Df[nVertices];
3294             }
3295             if(flags.normals)
3296             {
3297                if(flags.doubleNormals)
3298                {
3299                   mesh.normals = (Vector3Df *)renew mesh.normals Vector3D[nVertices];
3300                }
3301                else
3302                   mesh.normals = renew mesh.normals Vector3Df[nVertices];
3303             }
3304             if(flags.texCoords1)
3305             {
3306                mesh.texCoords = renew mesh.texCoords Pointf[nVertices];
3307             }
3308             if(flags.colors)
3309             {
3310                mesh.colors = renew mesh.colors ColorRGBAf[nVertices];
3311             }
3312          }
3313          result = true;
3314       }
3315       return result;
3316    }
3317
3318    void UnlockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags)
3319    {
3320       OGLSystem oglSystem = displaySystem.driverData;
3321       SETCAPS(oglSystem.capabilities);
3322       if(glCaps_vertexBuffer)
3323       {
3324          OGLMesh oglMesh = mesh.data;
3325          if(!flags) flags = mesh.flags;
3326          if(flags.vertices)
3327             oglMesh.vertices.allocate(
3328                mesh.nVertices * (mesh.flags.doubleVertices ? sizeof(Vector3D) : sizeof(Vector3Df)), mesh.vertices, staticDraw);
3329
3330          if(flags.normals)
3331             oglMesh.normals.allocate(
3332                mesh.nVertices * (mesh.flags.doubleNormals ? sizeof(Vector3D) : sizeof(Vector3Df)), mesh.normals, staticDraw);
3333
3334          if(flags.texCoords1)
3335             oglMesh.texCoords.allocate(
3336                mesh.nVertices * sizeof(Pointf), mesh.texCoords, staticDraw);
3337
3338          if(flags.colors)
3339             oglMesh.colors.allocate(
3340                mesh.nVertices * sizeof(ColorRGBAf), mesh.colors, staticDraw);
3341       }
3342    }
3343
3344    bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags)
3345    {
3346       bool result = true;
3347
3348       return result;
3349    }
3350
3351    void FreeIndices(DisplaySystem displaySystem, OGLIndices oglIndices)
3352    {
3353       OGLSystem oglSystem = displaySystem.driverData;
3354       SETCAPS(oglSystem.capabilities);
3355       if(oglIndices)
3356       {
3357          oglIndices.buffer.free(glCaps_vertexBuffer);
3358          delete oglIndices.indices;
3359          delete oglIndices;
3360       }
3361    }
3362
3363    void * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
3364    {
3365       OGLIndices oglIndices = OGLIndices { };
3366       if(oglIndices)
3367       {
3368          oglIndices.indices = (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
3369          oglIndices.nIndices = nIndices;
3370       }
3371       return oglIndices;
3372    }
3373
3374    void UnlockIndices(DisplaySystem displaySystem, OGLIndices oglIndices, bool indices32bit, int nIndices)
3375    {
3376       OGLSystem oglSystem = displaySystem.driverData;
3377       SETCAPS(oglSystem.capabilities);
3378       if(glCaps_vertexBuffer)
3379       {
3380          if(!glCaps_intAndDouble && indices32bit)
3381          {
3382             if(!oglIndices.buffer.buffer)
3383                glGenBuffers(1, &oglIndices.buffer.buffer);
3384             if(glabCurElementBuffer != oglIndices.buffer.buffer)
3385                GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, oglIndices.buffer.buffer);
3386
3387             {
3388                uint * pointer = (uint *)oglIndices.indices;
3389                int i;
3390                uint16 * b;
3391                if(nIndices > oglSystem.shortBDSize)
3392                {
3393                   oglSystem.shortBDSize = nIndices;
3394                   oglSystem.shortBDBuffer = renew oglSystem.shortBDBuffer uint16[oglSystem.shortBDSize];
3395                }
3396                b = oglSystem.shortBDBuffer;
3397                for(i = 0; i < nIndices; i++)
3398                   b[i] = (uint16)pointer[i];
3399
3400                glBufferData(GL_ELEMENT_ARRAY_BUFFER, nIndices * sizeof(uint16), b, GL_STATIC_DRAW);
3401             }
3402          }
3403          else
3404             oglIndices.buffer.allocate(
3405                nIndices * (indices32bit ? sizeof(uint32) : sizeof(uint16)),
3406                oglIndices.indices, staticDraw);
3407       }
3408    }
3409
3410    uint16 * LockIndices(DisplaySystem displaySystem, OGLIndices oglIndices)
3411    {
3412
3413       return oglIndices.indices;
3414    }
3415
3416    void SelectMesh(Display display, Mesh mesh)
3417    {
3418 #if !defined( __ANDROID__) && !defined(__APPLE__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
3419 #if defined(__WIN32__)
3420       if(glUnlockArraysEXT)
3421 #endif
3422          if(!glCaps_vertexBuffer && display.display3D.mesh)
3423             glUnlockArraysEXT();
3424 #endif
3425       if(mesh)
3426       {
3427          OGLMesh oglMesh = mesh.data;
3428
3429          // *** Vertex Stream ***
3430          GLEnableClientState(VERTICES);
3431          if(!display.display3D.collectingHits && oglMesh)
3432          {
3433             oglMesh.vertices.use(vertex, 3, (mesh.flags.doubleVertices ? GL_DOUBLE : GL_FLOAT), 0, oglMesh.vertices.buffer ? null : (double *)mesh.vertices);
3434
3435             // *** Normals Stream ***
3436             if(mesh.normals || mesh.flags.normals)
3437             {
3438                GLEnableClientState(NORMALS);
3439                oglMesh.normals.use(normal, 3, GL_FLOAT, 0, oglMesh.normals.buffer ? null : mesh.normals);
3440             }
3441             else
3442                GLDisableClientState(NORMALS);
3443
3444             // *** Texture Coordinates Stream ***
3445             if(mesh.texCoords || mesh.flags.texCoords1)
3446             {
3447                GLEnableClientState(TEXCOORDS);
3448                oglMesh.texCoords.use(texCoord, 2, GL_FLOAT, 0, oglMesh.texCoords.buffer ? null : mesh.texCoords);
3449             }
3450             else
3451                GLDisableClientState(TEXCOORDS);
3452
3453             // *** Color Stream ***
3454             if(mesh.colors || mesh.flags.colors)
3455             {
3456                GLEnableClientState(COLORS);
3457                oglMesh.colors.use(color, 4, GL_FLOAT, 0, oglMesh.colors.buffer ? null : mesh.colors);
3458             }
3459             else
3460                GLDisableClientState(COLORS);
3461          }
3462          else
3463          {
3464             noAB.use(vertex, 3, (mesh.flags.doubleVertices ? GL_DOUBLE : GL_FLOAT), 0, (double *)mesh.vertices);
3465             if((mesh.normals || mesh.flags.normals) && !display.display3D.collectingHits)
3466             {
3467                GLEnableClientState(NORMALS);
3468                noAB.use(normal, 3, GL_FLOAT, 0, mesh.normals);
3469             }
3470             else
3471                GLDisableClientState(NORMALS);
3472             if((mesh.texCoords || mesh.flags.texCoords1) && !display.display3D.collectingHits)
3473             {
3474                GLEnableClientState(TEXCOORDS);
3475                noAB.use(texCoord, 2, GL_FLOAT, 0, mesh.texCoords);
3476             }
3477             else
3478                GLDisableClientState(TEXCOORDS);
3479             if((mesh.colors || mesh.flags.colors) && !display.display3D.collectingHits)
3480             {
3481                GLEnableClientState(COLORS);
3482                noAB.use(color, 4, GL_FLOAT, 0, mesh.colors);
3483             }
3484             else
3485                GLDisableClientState(COLORS);
3486          }
3487
3488 #if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
3489
3490 #if defined(__WIN32__)
3491          if(glLockArraysEXT)
3492 #endif
3493             if(!glCaps_vertexBuffer)
3494                glLockArraysEXT(0, mesh.nVertices);
3495 #endif
3496       }
3497    }
3498
3499    void DrawPrimitives(Display display, PrimitiveSingle * primitive, Mesh mesh)
3500    {
3501       if(primitive->type.vertexRange)
3502       {
3503          GLFlushMatrices();
3504          glDrawArrays(getPrimitiveType(primitive->type.primitiveType), primitive->first, primitive->nVertices);
3505       }
3506       else
3507       {
3508          OGLIndices oglIndices = primitive->data;
3509          GLEAB eab = ((!display.display3D.collectingHits && oglIndices && glCaps_vertexBuffer) ? oglIndices.buffer : noEAB);
3510          if(!glCaps_intAndDouble && !glCaps_vertexBuffer && primitive->type.indices32bit)
3511          {
3512             uint16 * temp = new uint16[primitive->nIndices];
3513             uint32 * src = (uint32 *)(oglIndices ? oglIndices.indices : primitive->indices);
3514             int i;
3515             for(i = 0; i < primitive->nIndices; i++)
3516                temp[i] = (uint16)src[i];
3517             eab.draw(getPrimitiveType(primitive->type.primitiveType), primitive->nIndices, GL_UNSIGNED_SHORT, temp);
3518             delete temp;
3519          }
3520          else
3521             eab.draw(getPrimitiveType(primitive->type.primitiveType), primitive->nIndices,
3522                primitive->type.indices32bit ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT,
3523                eab.buffer ? 0 : (oglIndices ? oglIndices.indices : primitive->indices));
3524          GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
3525       }
3526    }
3527
3528    void PushMatrix(Display display)
3529    {
3530       GLPushMatrix();
3531    }
3532
3533    void PopMatrix(Display display, bool setMatrix)
3534    {
3535       GLPopMatrix();
3536    }
3537
3538    void SetTransform(Display display, Matrix transMatrix, bool viewSpace, bool useCamera)
3539    {
3540       Matrix matrix = transMatrix;
3541       Camera camera = useCamera ? display.display3D.camera : null;
3542
3543       if(viewSpace)
3544       {
3545          GLLoadIdentity();
3546          GLScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane);
3547       }
3548       else if(camera)
3549       {
3550          GLTranslated(
3551             matrix.m[3][0] - camera.cPosition.x,
3552             matrix.m[3][1] - camera.cPosition.y,
3553             matrix.m[3][2] - camera.cPosition.z);
3554       }
3555       else
3556          GLTranslated(
3557             matrix.m[3][0],
3558             matrix.m[3][1],
3559             matrix.m[3][2]);
3560
3561       matrix.m[3][0] = 0;
3562       matrix.m[3][1] = 0;
3563       matrix.m[3][2] = 0;
3564
3565       GLMultMatrixd(matrix.array);
3566    }
3567 #endif
3568 }
3569
3570 public void UseSingleGLContext(bool useSingle)
3571 {
3572    useSingleGLContext = useSingle;
3573 }
3574
3575 default dllexport void *
3576 #if defined(__WIN32__)
3577 __attribute__((stdcall))
3578 #endif
3579 IS_GLGetContext(DisplaySystem displaySystem)
3580 {
3581    if(displaySystem)
3582    {
3583 #if defined(__WIN32__)
3584       OGLSystem system = displaySystem.driverData;
3585       return system.glrc;
3586 #elif defined(__ANDROID__) || defined(__ODROID__)
3587       return eglContext;
3588 #elif defined(__EMSCRIPTEN__)
3589       OGLSystem system = displaySystem.driverData;
3590       return (void *)system.glc;
3591 #else
3592       OGLSystem system = displaySystem.driverData;
3593       return system.glContext;
3594 #endif
3595    }
3596    return null;
3597 }
3598
3599 #endif