ecere/gfx/drivers/OpenGL: Fixed FFP font modulation
[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 "defaultShader"
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       defaultShader.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       defaultShader.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       defaultShader.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 Shader activeShader;
365
366 static int displayWidth, displayHeight;
367
368 #define GL_CLAMP_TO_EDGE 0x812F
369
370 static bool useSingleGLContext = false;
371 class OGLDisplay : struct
372 {
373    GLCapabilities capabilities, originalCapabilities;
374    bool compat;
375    int version;
376
377    ColorAlpha * flippingBuffer;
378    int flipBufH, flipBufW;
379    bool depthWrite;
380    int x, y;
381    uint vao;
382
383 #if defined(__WIN32__)
384    HDC hdc;
385    HGLRC glrc;
386
387    HBITMAP memBitmap;
388    HDC memDC;
389    byte * picture;
390    uint stride;
391    void * pBuffer;
392    /*
393    int imageBuffers[2];
394    byte * pboMemory1, * pboMemory2;
395    */
396 #elif !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
397    GLXContext glContext;
398
399    Pixmap pixmap;
400    XShmSegmentInfo shminfo;
401    XImage * image;
402    XShmSegmentInfo shminfoShape;
403    XImage * shapeImage;
404    byte * picture;
405    uint stride;
406    GLXPbuffer pBuffer;
407    X11Picture windowPicture;
408    X11Picture pixmapPicture;
409    Pixmap shapePixmap;
410    X11Picture shapePicture;
411 #endif
412 };
413
414 class OGLSystem : struct
415 {
416    int maxTextureSize;
417    bool loadingFont;
418 #if defined(__WIN32__)
419    PIXELFORMATDESCRIPTOR pfd;
420    int format;
421    HDC hdc;
422    HGLRC glrc;
423    HWND hwnd;
424 #elif defined(__EMSCRIPTEN__)
425    EMSCRIPTEN_WEBGL_CONTEXT_HANDLE glc;
426 #elif !defined(__ANDROID__) && !defined(__ODROID__)
427    XVisualInfo * visualInfo;
428    GLXContext glContext;
429    GLXDrawable glxDrawable;
430 #endif
431    GLCapabilities capabilities;
432    bool compat;
433    int version;
434
435    // Buffer Data
436    uint16 *shortBDBuffer;
437    uint shortBDSize;
438 };
439
440 class OGLSurface : struct
441 {
442    Font font;
443    bool opaqueText;
444    int xOffset;
445    bool writingText;
446    bool writingOutline;
447
448    float foreground[4], background[4], bitmapMult[4];
449 } OGLSurface;
450
451 class OGLMesh : struct
452 {
453    GLAB vertices;
454    GLAB normals;
455    GLAB tangents;
456    GLAB lightVectors;
457    GLAB texCoords;
458    GLAB texCoords2;
459    GLAB colors;
460 };
461
462 class OGLIndices : struct
463 {
464    uint16 * indices;
465    GLEAB buffer;
466    uint nIndices;
467 };
468
469 int current;
470 void * previous;
471
472 #if defined(__WIN32__)
473 static HGLRC winCreateContext(HDC hdc, int * contextVersion, bool * isCompatible, bool compatible)
474 {
475    HGLRC result = 0;
476    if(wglCreateContextAttribsARB)
477    {
478       int versions[12][2] =
479       {
480          { 4, 5 }, { 4, 4 }, { 4, 3 }, { 4, 2 }, { 4, 1 }, { 4, 0 },
481                              { 3, 3 }, { 3, 2 }, { 3, 1 }, { 3, 0 },
482                                                  { 2, 1 }, { 2, 0 }
483       };
484
485       bool tryingCompat = compatible;
486       int v = 0;
487       while(!result)
488       {
489          for(v = 0; !result && v < sizeof(versions) / sizeof(versions[0]); v++)
490          {
491             int v0 = versions[v][0], v1 = versions[v][1];
492             if(!tryingCompat || v0 >= 3)
493             {
494                bool coreNotion = v0 > 3 || (v0 == 3 && v1 >= 3);
495                int attribs[] =
496                {
497                   WGL_CONTEXT_MAJOR_VERSION_ARB, v0, WGL_CONTEXT_MINOR_VERSION_ARB, v1,
498          #ifdef _DEBUG
499                   WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB,
500          #endif
501                   coreNotion ? WGL_CONTEXT_PROFILE_MASK_ARB : 0, coreNotion ? (tryingCompat ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : WGL_CONTEXT_CORE_PROFILE_BIT_ARB) : 0,
502                   0,0
503                };
504                result = wglCreateContextAttribsARB(hdc, null, attribs);
505                if(result)
506                {
507                   if(contextVersion) *contextVersion = v0;
508                   if(isCompatible)   *isCompatible = tryingCompat || !coreNotion;
509                }
510             }
511          }
512          if(tryingCompat)
513             tryingCompat = false;
514          else
515             break;
516       }
517    }
518    if(!result)
519    {
520       if(contextVersion) *contextVersion = 1;
521       if(isCompatible)   *isCompatible = true;
522       result = wglCreateContext(hdc);
523    }
524    return result;
525 }
526 #endif
527
528 #if ENABLE_GL_FFP
529 static int maxTMU = 0;
530
531 static void disableRemainingTMUs(int lastTMU)
532 {
533    int t;
534    for(t = lastTMU; t < maxTMU; t++)
535    {
536       glActiveTexture(GL_TEXTURE0 + t);
537       glClientActiveTexture(GL_TEXTURE0 + t);
538       glDisable(GL_TEXTURE_2D);
539       glDisable(GL_TEXTURE_CUBE_MAP);
540       GLDisableClientState(TEXCOORDS);
541    }
542    glActiveTexture(GL_TEXTURE0);
543    glClientActiveTexture(GL_TEXTURE0);
544    maxTMU = lastTMU;
545 }
546 #endif
547
548 class OpenGLDisplayDriver : DisplayDriver
549 {
550    class_property(name) = "OpenGL";
551
552    bool LockSystem(DisplaySystem displaySystem)
553    {
554 #if defined(__EMSCRIPTEN__)
555       OGLSystem oglSystem = displaySystem.driverData;
556       emscripten_webgl_make_context_current(oglSystem.glc);
557 #elif !defined(__ANDROID__) && !defined(__ODROID__)
558       OGLSystem oglSystem = displaySystem.driverData;
559       if(useSingleGLContext) return true;
560    #if defined(__WIN32__)
561       wglMakeCurrent(oglSystem.hdc, oglSystem.glrc);
562    #elif defined(__unix__) || defined(__APPLE__)
563       //if(previous) return true;
564       // printf("Making SYSTEM current\n");
565       glXMakeCurrent(xGlobalDisplay, (GLXDrawable)oglSystem.glxDrawable, oglSystem.glContext);
566       //previous = oglSystem.glContext;
567    #endif
568 #endif
569       GLABBindBuffer(GL_ARRAY_BUFFER, 0);
570       GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
571       return true;
572    }
573
574    void UnlockSystem(DisplaySystem displaySystem)
575    {
576       if(useSingleGLContext) return;
577    #if defined(__WIN32__)
578       wglMakeCurrent(null, null);
579    #elif defined(__unix__) || defined(__APPLE__)
580       // printf("Making NULL current\n");
581       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
582       #else
583       glXMakeCurrent(xGlobalDisplay, None, null);
584       #endif
585       // previous = null;
586    #endif
587    }
588
589    bool Lock(Display display)
590    {
591 #if !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
592       OGLDisplay oglDisplay = display.driverData;
593       if(useSingleGLContext) return true;
594    #if defined(__WIN32__)
595       wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
596    #elif defined(__unix__) || defined(__APPLE__)
597       // if(previous) glXMakeCurrent(xGlobalDisplay, None, null);
598       // printf("   Making DISPLAY current\n");
599       glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext);
600    #endif
601 #endif
602       GLABBindBuffer(GL_ARRAY_BUFFER, 0);
603       GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
604       return true;
605    }
606
607    void Unlock(Display display)
608    {
609       if(useSingleGLContext) return;
610       //printf("   Making NULL current\n");
611       //glXMakeCurrent(xGlobalDisplay, None, null);
612       // if(previous)
613          LockSystem(display.displaySystem);
614    }
615
616    void DestroyDisplay(Display display)
617    {
618       OGLDisplay oglDisplay = display.driverData;
619
620       if(oglDisplay)
621       {
622    #if defined(__WIN32__)
623          wglMakeCurrent( null, null );
624
625          if(oglDisplay.glrc)
626             wglDeleteContext(oglDisplay.glrc);
627
628          if(oglDisplay.hdc && oglDisplay.pBuffer)
629             wglReleasePbufferDCARB(oglDisplay.pBuffer, oglDisplay.hdc);
630
631          if(oglDisplay.pBuffer)
632             wglDestroyPbufferARB(oglDisplay.pBuffer);
633
634          if(oglDisplay.hdc)
635             ReleaseDC(display.window, oglDisplay.hdc);
636
637          if(oglDisplay.memDC) DeleteDC(oglDisplay.memDC);
638          if(oglDisplay.memBitmap) DeleteObject(oglDisplay.memBitmap);
639
640    #elif defined(__unix__) || defined(__APPLE__)
641       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
642       #else
643          if(oglDisplay.shapePixmap)
644             XFreePixmap(xGlobalDisplay, oglDisplay.shapePixmap);
645          if(oglDisplay.pixmap)
646             XFreePixmap(xGlobalDisplay, oglDisplay.pixmap);
647          if(oglDisplay.image)
648          {
649             if(oglDisplay.shminfoShape.shmid != -1)
650             {
651                XShmDetach(xGlobalDisplay, &oglDisplay.shminfo);
652                if(oglDisplay.shminfo.shmaddr != (void *)-1)
653                   shmdt(oglDisplay.shminfo.shmaddr);
654                shmctl(oglDisplay.shminfo.shmid, IPC_RMID, 0);
655             }
656          }
657          if(oglDisplay.shapeImage)
658          {
659             if(oglDisplay.shminfoShape.shmid != -1)
660             {
661                XShmDetach(xGlobalDisplay, &oglDisplay.shminfoShape);
662                if(oglDisplay.shminfoShape.shmaddr != (void *)-1)
663                   shmdt(oglDisplay.shminfoShape.shmaddr);
664                shmctl(oglDisplay.shminfoShape.shmid, IPC_RMID, 0);
665             }
666             XDestroyImage(oglDisplay.shapeImage);
667             oglDisplay.shapeImage = None;
668          }
669
670          glXMakeCurrent(xGlobalDisplay, None, null);
671
672          if(oglDisplay.glContext)
673             glXDestroyContext(xGlobalDisplay, oglDisplay.glContext);
674       #endif
675    #endif
676          delete oglDisplay.flippingBuffer;
677          delete oglDisplay;
678          display.driverData = null;
679       }
680    }
681
682 #if !defined(__EMSCRIPTEN__)
683    void ::CheckCapabilities(OGLSystem oglSystem, OGLDisplay oglDisplay, bool canCheckExtensions)
684    {
685       GLCapabilities capabilities;
686 #if !defined(_GLES2)
687       const char * extensions = (canCheckExtensions && (!oglDisplay || oglDisplay.compat)) ? (const char *)glGetString(GL_EXTENSIONS) : null;
688 #endif
689 #ifdef DIAGNOSTICS
690       printf("extensions: %s\n", extensions);
691 #endif
692
693       glGetIntegerv(GL_MAX_TEXTURE_SIZE, &oglSystem.maxTextureSize);
694
695 #if defined(_GLES)
696       capabilities = { fixedFunction = true, vertexPointer = true, vertexBuffer = true, pointSize = true, legacyFormats = true, frameBuffer = extensions && strstr(extensions, "GL_OES_framebuffer_object") };
697 #elif defined(_GLES2)
698       capabilities = { glCaps_shaders = true, vertexBuffer = true, pointSize = true, frameBuffer = true, legacyFormats = true };
699 #else
700       capabilities =
701       {
702          nonPow2Textures = glGetStringi || (extensions && (strstr(extensions, "GL_ARB_texture_non_power_of_two")));
703          intAndDouble = true;
704 #ifdef GL_DEBUGGING
705          debug = true;
706 #endif
707          compatible = oglDisplay.compat;
708          pointSize = oglDisplay.compat;
709 #if ENABLE_GL_LEGACY
710          legacy         = glBegin != null && oglDisplay.compat;
711          legacyFormats  = glBegin != null && oglDisplay.compat;
712          immediate      = glBegin != null && oglDisplay.compat;
713          fixedFunction  = glBegin != null && oglDisplay.compat;
714          quads          = glBegin != null && oglDisplay.compat;
715          select         = glSelectBuffer != null && oglDisplay.compat;
716 #endif
717 #if ENABLE_GL_SHADERS
718          shaders = glCreateProgram != null;
719 #endif
720 #if ENABLE_GL_POINTER
721          vertexPointer = oglDisplay.compat;
722 #endif
723 #if ENABLE_GL_VAO
724          vao = glBindVertexArray != null && !oglDisplay.compat;
725 #endif
726 #if ENABLE_GL_FBO
727          shaders = glBindFramebuffer != null;
728 #endif
729          vertexBuffer = glBindBuffer != null;
730          // mapBuffer = glMapBuffer != null;
731       };
732 #endif
733
734 #ifdef DIAGNOSTICS
735       PrintLn("max texture size: ", oglSystem.maxTextureSize);
736 #endif
737       if(oglDisplay) oglDisplay.capabilities = capabilities;
738       if(oglSystem)  oglSystem.capabilities = capabilities;
739    }
740 #endif
741
742    bool CreateDisplaySystem(DisplaySystem displaySystem)
743    {
744       bool result = false;
745       OGLSystem oglSystem = displaySystem.driverData = OGLSystem { };
746
747 #ifdef _GLES
748       oglSystem.capabilities = { fixedFunction = true, vertexBuffer = true, frameBuffer = true, pointSize = true };
749 #elif defined(_GLES2)
750       oglSystem.capabilities = { shaders = true, vertexBuffer = true, frameBuffer = true, pointSize = true };
751 #else
752       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 };
753 #endif
754
755 #ifdef DIAGNOSTICS
756       PrintLn("OpenGL driver's CreateDisplaySystem()");
757 #endif
758
759    #ifdef __WIN32__
760       oglSystem.hwnd = CreateWindow("static", null, 0,0,0,0,0,null,null,null,null);
761
762       oglSystem.hdc = GetDC(oglSystem.hwnd);
763       if(oglSystem.hdc)
764       {
765
766          oglSystem.pfd.nSize = (short)sizeof(oglSystem.pfd);
767          oglSystem.pfd.nVersion = 1;
768          oglSystem.pfd.dwFlags = PFD_DRAW_TO_WINDOW /*PFD_DRAW_TO_BITMAP*/ | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
769          oglSystem.pfd.iPixelType = PFD_TYPE_RGBA;
770          oglSystem.pfd.cColorBits = 24;
771          oglSystem.pfd.cAlphaBits = 8;
772          oglSystem.pfd.cDepthBits = 24;
773          oglSystem.pfd.iLayerType = PFD_MAIN_PLANE;
774
775          oglSystem.format = ChoosePixelFormat(oglSystem.hdc, &oglSystem.pfd);
776          DescribePixelFormat(oglSystem.hdc, oglSystem.format, sizeof(oglSystem.pfd), &oglSystem.pfd);
777
778          if(oglSystem.pfd.cColorBits > 8)
779          {
780             SetPixelFormat(oglSystem.hdc, oglSystem.format, &oglSystem.pfd);
781             oglSystem.glrc = wglCreateContext(oglSystem.hdc);
782             if(oglSystem.glrc)
783             {
784                wglMakeCurrent(oglSystem.hdc, oglSystem.glrc);
785
786                wglChoosePixelFormatARB = (void *) wglGetProcAddress("wglChoosePixelFormatARB");
787                wglGetExtensionsStringARB = (void *)wglGetProcAddress("wglGetExtensionsStringARB");
788                wglCreatePbufferARB = (void *)wglGetProcAddress("wglCreatePbufferARB");
789                wglGetPbufferDCARB = (void *)wglGetProcAddress("wglGetPbufferDCARB");
790                wglQueryPbufferARB = (void *)wglGetProcAddress("wglQueryPbufferARB");
791                wglDestroyPbufferARB = (void *)wglGetProcAddress("wglDestroyPbufferARB");
792                wglReleasePbufferDCARB = (void *)wglGetProcAddress("wglReleasePbufferDCARB");
793                wglBindTexImageARB = (void *)wglGetProcAddress("wglBindTexImageARB");
794                wglReleaseTexImageARB = (void *)wglGetProcAddress("wglReleaseTexImageARB");
795                wglSwapIntervalEXT = (void *)wglGetProcAddress("wglSwapIntervalEXT");
796                wglCreateContextAttribsARB = (void *)wglGetProcAddress("wglCreateContextAttribsARB");
797
798                glLockArraysEXT = (void *) wglGetProcAddress("glLockArraysEXT" );
799                glUnlockArraysEXT = (void *) wglGetProcAddress("glUnlockArraysEXT");
800
801                // eSystem_LoggingMode(LOG_MSGBOX, null);
802
803                if(wglChoosePixelFormatARB)
804                {
805                   int pixelFormat;
806                   int valid;
807                   int numFormats;
808                   float fAttributes[] = {0,0};
809                   int iAttributes[] =
810                   {
811                      WGL_DRAW_TO_WINDOW_ARB,GL_TRUE,
812                      WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
813                      WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
814                      WGL_COLOR_BITS_ARB,24,
815                      WGL_ALPHA_BITS_ARB,8,
816                      WGL_DEPTH_BITS_ARB,16,
817                      WGL_STENCIL_BITS_ARB,0,
818                      WGL_DOUBLE_BUFFER_ARB,GL_TRUE,
819                      WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
820                      WGL_SAMPLES_ARB, 4,                  // Check For 4x Multisampling
821                      0,0
822                   };
823
824                   //Log("Found wglChoosePixelFormatARB\n");
825
826                   valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
827                   if(!valid || !numFormats)
828                   {
829                      //Log("Can't find 4x multi sampling\n");
830                      iAttributes[19] = 2;
831                      valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
832                      if(!valid || !numFormats)
833                      {
834                         // Log("Can't find 2x multi sampling\n");
835                         iAttributes[16] = 0;
836                         iAttributes[17] = 0;
837                         valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
838                      }
839                   }
840                   if(valid && numFormats)
841                   {
842                      oglSystem.format = pixelFormat;
843                      wglMakeCurrent(null, null);
844                      wglDeleteContext(oglSystem.glrc);
845
846                      // *** DescribePixelFormat does not support WGL pixel formats! ***
847                      //DescribePixelFormat(oglSystem.hdc, oglSystem.format, sizeof(oglSystem.pfd), &oglSystem.pfd);
848                      SetPixelFormat(oglSystem.hdc, oglSystem.format, &oglSystem.pfd);
849                      //Log("Successfully set pixel format\n");
850
851 #ifdef DIAGNOSTICS
852                      PrintLn("winCreateContext()");
853 #endif
854                      oglSystem.glrc = winCreateContext(oglSystem.hdc, &oglSystem.version, &oglSystem.compat, displaySystem.glCapabilities.compatible);
855 #ifdef DIAGNOSTICS
856                      PrintLn("wglMakeCurrent()");
857 #endif
858                      if(oglSystem.glrc)
859                         wglMakeCurrent(oglSystem.hdc, oglSystem.glrc);
860                   }
861                }
862                /*else
863                   eSystem_Logf("Can't find wglChoosePixelFormatARB\n");*/
864
865                result = true;
866
867                wglMakeCurrent(null, null);
868
869                //eSystem_DumpErrors(true);
870             }
871          }
872       }
873    #elif defined(__unix__) || defined(__APPLE__)
874       #if defined(__ANDROID__) || defined(__ODROID__)
875          #if defined(__ANDROID__)
876          egl_init_display(guiApp.desktop.windowHandle);
877          #elif defined(__ODROID__)
878          egl_init_display((uint)displaySystem.window);
879          #endif
880          CheckCapabilities(oglSystem, null, true);
881
882          // TODO: Clean this up? Needed here?
883          GLEnableClientState(VERTICES);
884          /*
885          // Initialize GL state.
886          glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
887          glEnable(GL_CULL_FACE);
888          glShadeModel(GL_SMOOTH);
889          glDisable(GL_DEPTH_TEST);
890          */
891          glDisable(GL_CULL_FACE);
892          glDisable(GL_DEPTH_TEST);
893
894          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
895          glEnable(GL_BLEND);
896
897          matrixStack[0][0].Identity();
898          matrixStack[1][0].Identity();
899          matrixStack[2][0].Identity();
900
901          GLMatrixMode(GL_MODELVIEW);
902          GLScaled(1.0, 1.0, -1.0);
903          GLMatrixMode(GL_PROJECTION);
904          glShadeModel(GL_FLAT);
905
906 #if !defined(_GLES)
907          if(!glCaps_shaders)
908             ;//GLLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
909 #endif
910          glFogi(GL_FOG_MODE, GL_EXP);
911          glFogf(GL_FOG_DENSITY, 0);
912          glEnable(GL_NORMALIZE);
913          glDepthFunc(GL_LESS);
914          glClearDepth(1.0);
915          glDisable(GL_MULTISAMPLE);
916
917          glViewport(0,0,eglWidth,eglHeight);
918          GLLoadIdentity();
919          GLOrtho(0,eglWidth,eglHeight,0,0.0,1.0);
920
921          glabCurArrayBuffer = 0;
922          glabCurElementBuffer = 0;
923
924          result = true;
925       #elif defined(__EMSCRIPTEN__)
926          {
927             EmscriptenWebGLContextAttributes attribs = { 0 };
928             attribs.depth = 1;
929             attribs.antialias = 1;
930
931             /*
932               EM_BOOL alpha;
933               EM_BOOL depth;
934               EM_BOOL stencil;
935               EM_BOOL antialias;
936               EM_BOOL premultipliedAlpha;
937               EM_BOOL preserveDrawingBuffer;
938               EM_BOOL preferLowPowerToHighPerformance;
939               EM_BOOL failIfMajorPerformanceCaveat;
940               int majorVersion;
941               int minorVersion;
942               EM_BOOL enableExtensionsByDefault;
943               */
944
945             emscripten_webgl_init_context_attributes(&attribs);
946             oglSystem.maxTextureSize = 16384;
947             oglSystem.glc = emscripten_webgl_create_context("canvas", &attribs);
948             if(emscripten_webgl_make_context_current(oglSystem.glc) == EMSCRIPTEN_RESULT_SUCCESS)
949                result = true;
950
951             /*glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
952             glEnable(GL_BLEND);*/
953          }
954       #else
955       {
956          X11Window root = RootWindow( xGlobalDisplay, DefaultScreen( xGlobalDisplay ) );
957          XSetWindowAttributes attr;
958          unsigned long mask;
959
960          int attrList[] =
961          {
962       #ifndef ECERE_MINIGLX
963             GLX_USE_GL, GLX_DEPTH_SIZE, 1,
964       #endif
965             GLX_RGBA,
966             GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
967             GLX_DOUBLEBUFFER,
968             None
969          };
970          oglSystem.visualInfo = glXChooseVisual( xGlobalDisplay,  DefaultScreen( xGlobalDisplay ), attrList );
971          attr.background_pixel = 0;
972          attr.border_pixel = 0;
973          attr.colormap = XCreateColormap( xGlobalDisplay, root, oglSystem.visualInfo->visual, AllocNone);
974          attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
975          mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
976
977          oglSystem.glxDrawable = XCreateWindow( xGlobalDisplay, root, 0, 0, 1, 1, 0, oglSystem.visualInfo->depth, InputOutput,
978             oglSystem.visualInfo->visual, mask, &attr );
979       }
980       if(oglSystem.visualInfo)
981       {
982          oglSystem.glContext = glXCreateContext(xGlobalDisplay, oglSystem.visualInfo, null, True);
983          if(oglSystem.glContext)
984          {
985             glXMakeCurrent(xGlobalDisplay, oglSystem.glxDrawable, oglSystem.glContext);
986             glXMakeCurrent(xGlobalDisplay, None, null);
987             result = true;
988          }
989       }
990       #endif
991    #endif
992
993       displaySystem.flags.alpha = true;
994       displaySystem.flags.flipping = true;
995       displaySystem.pixelFormat = pixelFormat888;
996       return result;
997    }
998
999    void DestroyDisplaySystem(DisplaySystem displaySystem)
1000    {
1001       OGLSystem oglSystem = displaySystem.driverData;
1002       if(stippleTexture)
1003       {
1004          glDeleteTextures(1, &stippleTexture);
1005          stippleTexture = 0;
1006       }
1007
1008 #if ENABLE_GL_SHADERS
1009       defaultShader.free();
1010       activeShader = null;
1011 #endif
1012
1013       delete oglSystem.shortBDBuffer;
1014       glimtkTerminate();
1015
1016    #if defined(__WIN32__)
1017       wglMakeCurrent( null, null );
1018
1019       if(oglSystem.glrc)
1020          wglDeleteContext(oglSystem.glrc);
1021
1022       if(oglSystem.hdc)
1023          ReleaseDC(oglSystem.hwnd, oglSystem.hdc);
1024       DestroyWindow(oglSystem.hwnd);
1025
1026    #elif defined(__unix__) || defined(__APPLE__)
1027       #if defined(__ANDROID__) || defined(__ODROID__)
1028          egl_term_display();
1029       #elif defined(__EMSCRIPTEN__)
1030          emscripten_webgl_destroy_context(oglSystem.glc);
1031       #else
1032       if(oglSystem.visualInfo)
1033       {
1034    #ifdef   ECERE_MINIGLX
1035          __miniglx_XFree(oglSystem.visualInfo);
1036    #else
1037          XFree(oglSystem.visualInfo);
1038    #endif
1039       }
1040       if(oglSystem.glContext)
1041         glXDestroyContext(xGlobalDisplay, oglSystem.glContext);
1042
1043       if(oglSystem.glxDrawable)
1044       {
1045          XDestroyWindow(xGlobalDisplay, oglSystem.glxDrawable);
1046          oglSystem.glxDrawable = 0;
1047       }
1048       #endif
1049    #endif
1050       delete oglSystem;
1051    }
1052
1053    /*static */bool ::initialDisplaySetup(Display display, bool canCheckExtensions, bool loadExtensions)
1054    {
1055       OGLDisplay oglDisplay = display.driverData;
1056       OGLSystem oglSystem = display.displaySystem.driverData;
1057       bool result = true;
1058
1059 #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
1060       if(loadExtensions && ogl_LoadFunctions() == ogl_LOAD_FAILED)
1061          PrintLn("ogl_LoadFunctions() failed!");
1062       CheckCapabilities(oglSystem, oglDisplay, canCheckExtensions);
1063 #endif
1064
1065       {
1066          GLCapabilities capabilities = *&display.glCapabilities;
1067          // PrintLn("Available OpenGL Capabilities: ", oglDisplay.capabilities);
1068          // PrintLn("Desired OpenGL Capabilities: ", capabilities);
1069
1070          oglDisplay.originalCapabilities = oglDisplay.capabilities;
1071
1072          // Re-enable glCaps_shaders if no fixed function support
1073          if(!oglDisplay.capabilities.fixedFunction)
1074             capabilities.shaders = true;
1075          // Re-enable fixed function if no glCaps_shaders support
1076          if(!oglDisplay.capabilities.shaders)
1077          {
1078             capabilities.fixedFunction = true;
1079             capabilities.shaders = false;
1080          }
1081
1082          if(!capabilities.shaders && !capabilities.fixedFunction)
1083          {
1084             capabilities.fixedFunction = oglDisplay.capabilities.fixedFunction;
1085             capabilities.shaders = oglDisplay.capabilities.shaders;
1086          }
1087
1088          // Disable things that don't work with glCaps_shaders
1089          if(capabilities.shaders)
1090          {
1091             capabilities.fixedFunction = false;
1092             capabilities.legacy = false;
1093             capabilities.immediate = false;
1094          }
1095
1096          #if !ENABLE_GL_POINTER
1097          // Re-enable vertex buffer if no pointer support
1098          capabilities.vertexBuffer = true;
1099          #endif
1100
1101          oglDisplay.capabilities &= capabilities;
1102
1103          // PrintLn("Selected OpenGL Capabilities: ", oglDisplay.capabilities);
1104          oglSystem.capabilities = oglDisplay.capabilities;
1105       }
1106
1107    #ifdef GL_DEBUGGING
1108       if(oglDisplay.capabilities.debug)
1109          setupDebugging();
1110    #else
1111       oglDisplay.capabilities.debug = false;
1112    #endif
1113
1114 #if ENABLE_GL_VAO
1115       if(oglDisplay.capabilities.vao)
1116       {
1117          glGenVertexArrays(1, &oglDisplay.vao);
1118          glBindVertexArray(oglDisplay.vao);
1119       }
1120 #endif
1121
1122       oglSystem.capabilities = oglDisplay.capabilities;
1123       SETCAPS(oglDisplay.capabilities);
1124
1125 #if ENABLE_GL_SHADERS
1126       if(glCaps_shaders)
1127       {
1128 #if ENABLE_GL_LEGACY
1129          if(oglDisplay.compat)
1130          {
1131             glDisableClientState(GL_VERTEX_ARRAY);
1132             glDisableClientState(GL_NORMAL_ARRAY);
1133             glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1134             glDisableClientState(GL_COLOR_ARRAY);
1135          }
1136 #endif
1137          defaultShader.select();
1138       }
1139 #if ENABLE_GL_LEGACY
1140       else
1141       {
1142          glDisableVertexAttribArray(GLBufferContents::color);
1143          glDisableVertexAttribArray(GLBufferContents::normal);
1144          glDisableVertexAttribArray(GLBufferContents::texCoord);
1145          glDisableVertexAttribArray(GLBufferContents::vertex);
1146          glDisableVertexAttribArray(GLBufferContents::tangent1);
1147          glDisableVertexAttribArray(GLBufferContents::tangent2);
1148          glBindVertexArray(0);
1149          glUseProgram(0);
1150       }
1151 #endif
1152
1153 #endif
1154
1155 #if ENABLE_GL_VAO
1156       if(glCaps_vao)
1157          glBindVertexArray(oglDisplay.vao);
1158 #endif
1159
1160       GLEnableClientState(VERTICES);
1161
1162       GLABBindBuffer(GL_ARRAY_BUFFER, 0);
1163       GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1164
1165 #if defined(__WIN32__)
1166       if(glBlendFuncSeparate)
1167          glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1168       else
1169          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1170 #else
1171       glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1172 #endif
1173       glEnable(GL_BLEND);
1174
1175       GLMatrixMode(MatrixMode::texture);
1176       GLLoadIdentity();
1177
1178       GLMatrixMode(MatrixMode::modelView);
1179       GLLoadIdentity(); // For setting up GLES stack
1180       GLScaled(1.0, 1.0, -1.0);
1181       // glTranslatef(0.375f, 0.375f, 0.0f);
1182       // glTranslatef(-0.625f, -0.625f, 0.0f);
1183       GLMatrixMode(MatrixMode::projection);
1184       GLLoadIdentity();
1185       if(display.width && display.height)
1186          GLOrtho(0,display.width,display.height,0,0.0,1.0);
1187
1188 #if ENABLE_GL_FFP
1189       if(!glCaps_shaders)
1190       {
1191          glShadeModel(GL_FLAT);
1192
1193          #define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
1194          GLLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1195
1196 #if !defined(_GLES)
1197          ;//GLLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1198 #endif
1199          glFogi(GL_FOG_MODE, GL_EXP);
1200          glFogf(GL_FOG_DENSITY, 0);
1201          glEnable(GL_NORMALIZE);
1202       }
1203 #endif
1204       glDepthFunc(GL_LESS);
1205       glClearDepth(1.0);
1206 #if !defined(__EMSCRIPTEN__)
1207       glDisable(GL_MULTISAMPLE);
1208 #endif
1209
1210 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
1211       display.ambient = Color { 50,50,50 };
1212 #endif
1213       return result;
1214    }
1215
1216    bool CreateDisplay(Display display)
1217    {
1218       bool result = false;
1219       OGLDisplay oglDisplay = display.driverData;
1220       OGLSystem oglSystem = display.displaySystem.driverData;
1221
1222       if(!oglDisplay)
1223          oglDisplay = display.driverData = OGLDisplay { };
1224       oglDisplay.capabilities = oglSystem.capabilities;
1225
1226 #if defined(__WIN32__) || defined(USEPBUFFER)
1227       if(!display.alphaBlend)
1228 #endif
1229       {
1230 #if defined(__WIN32__)
1231          oglDisplay.hdc = GetDC(display.window);
1232          SetPixelFormat(oglDisplay.hdc, oglSystem.format, &oglSystem.pfd);
1233          if((oglDisplay.glrc = winCreateContext(oglDisplay.hdc, &oglDisplay.version, &oglDisplay.compat, (*&display.glCapabilities).compatible)))
1234          {
1235             wglShareLists(oglSystem.glrc, oglDisplay.glrc);
1236             wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
1237             result = true;
1238          }
1239          else
1240             ReleaseDC(display.window, oglDisplay.hdc);
1241 #elif defined(__unix__) || defined(__APPLE__)
1242 #  if defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__ODROID__)
1243          result = true;
1244 #  else
1245          XVisualInfo * visualInfo = ((XWindowData)display.windowDriverData).visual;
1246          /*
1247 #if defined(__APPLE__)
1248          XVisualInfo template = { 0 };
1249          XWindowAttributes winAttr;
1250          int n;
1251          XGetWindowAttributes(xGlobalDisplay, (X11Window)display.window, &winAttr);
1252          template.visualid = XVisualIDFromVisual(winAttr.visual);
1253          visualInfo = XGetVisualInfo(xGlobalDisplay, VisualIDMask, &template, &n);
1254 #ifdef _DEBUG
1255          printf("XGetVisualInfo visual ID = %d\n", template.visualid);
1256          printf("visualInfo visual ID = %d\n", visualInfo->visualid);
1257          printf("oglSystem.visualInfo visual ID = %d\n", oglSystem.visualInfo->visualid);
1258          printf("((XWindowData)display.windowDriverData).visual visual ID = %d\n", ((XWindowData)display.windowDriverData).visual->visualid);
1259 #endif
1260          // visualInfo = oglSystem.visualInfo;
1261 //#endif
1262          */
1263 #if !defined(__APPLE__)
1264          oglDisplay.compat = true;
1265          oglDisplay.version = 4;
1266 #endif
1267
1268          if(visualInfo)
1269          {
1270             //printf("visualInfo is not null\n");
1271             // printf("Creating Display Context, sharing with %x!\n", oglSystem.glContext);
1272             oglDisplay.glContext = glXCreateContext(xGlobalDisplay, visualInfo, oglSystem.glContext, True);
1273             //XFree(visualInfo);
1274          }
1275
1276          // oglDisplay.glContext = glXCreateContext(xGlobalDisplay, oglSystem.visualInfo, oglSystem.glContext, True);
1277          if(oglDisplay.glContext)
1278          {
1279             //printf("CreateDisplay Got a Context\n");
1280             glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext);
1281             result = true;
1282          }
1283 #  endif
1284 #endif
1285       }
1286 #if defined(__WIN32__) || defined(USEPBUFFER)
1287       else
1288       {
1289          oglDisplay.compat = (*&display.glCapabilities).compatible;
1290          result = true;
1291          wglMakeCurrent(oglSystem.hdc, oglSystem.glrc);
1292       }
1293 #endif
1294       if(result)
1295       {
1296 #if defined(__EMSCRIPTEN__)
1297          emscripten_webgl_make_context_current(oglSystem.glc);
1298 #endif
1299
1300 #if defined(__WIN32__) || defined(USEPBUFFER)
1301          initialDisplaySetup(display, !display.alphaBlend, true);
1302 #else
1303          initialDisplaySetup(display, true, true);
1304 #endif
1305       }
1306
1307       if(!useSingleGLContext)
1308       {
1309    #if defined(__WIN32__)
1310          wglMakeCurrent(null, null);
1311    #elif defined(__unix__) || defined(__APPLE__)
1312       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
1313          result = true;
1314       #else
1315          glXMakeCurrent(xGlobalDisplay, None, null);
1316       #endif
1317    #endif
1318       }
1319       else
1320       {
1321       #if defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__ODROID__)
1322          result = true;
1323       #endif
1324       }
1325       return result;
1326    }
1327
1328    bool DisplaySize(Display display, int width, int height)
1329    {
1330       OGLDisplay oglDisplay = display.driverData;
1331       bool result = false;
1332
1333 #if defined(__WIN32__) || defined(USEPBUFFER)
1334       OGLSystem oglSystem = display.displaySystem.driverData;
1335       if(display.alphaBlend)
1336       {
1337 #if defined(__WIN32__)
1338          const int attributes[]=
1339          {
1340             /*WGL_TEXTURE_FORMAT_ARB, WGL_TEXTURE_RGBA_ARB,
1341             WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_2D_ARB, */0
1342          };
1343          int pixelFormat = 0;
1344          if(wglChoosePixelFormatARB)
1345          {
1346             int valid;
1347             int numFormats;
1348             float fAttributes[] = {0,0};
1349             int iAttributes[] =
1350             {
1351                //WGL_DRAW_TO_BITMAP_ARB, GL_TRUE,
1352                WGL_DRAW_TO_PBUFFER_ARB,GL_TRUE,
1353                WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
1354                WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
1355                WGL_COLOR_BITS_ARB,24,
1356                WGL_ALPHA_BITS_ARB,8,
1357                WGL_DEPTH_BITS_ARB,16,
1358                WGL_STENCIL_BITS_ARB,0,
1359                WGL_DOUBLE_BUFFER_ARB,GL_FALSE,
1360                WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
1361                WGL_SAMPLES_ARB, 4,                  // Check For 4x Multisampling
1362                0,0
1363             };
1364
1365             //Log("Found wglChoosePixelFormatARB\n");
1366
1367             valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
1368             if(!valid || !numFormats)
1369             {
1370                //Log("Can't find 4x multi sampling\n");
1371                iAttributes[19] = 2;
1372                valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
1373                if(!valid || !numFormats)
1374                {
1375                   // Log("Can't find 2x multi sampling\n");
1376                   iAttributes[16] = 0;
1377                   iAttributes[17] = 0;
1378                   valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
1379                   if(!valid || !numFormats)
1380                   {
1381                      int iAttributes[] =
1382                      {
1383                         WGL_DRAW_TO_PBUFFER_ARB,GL_TRUE,
1384                         //WGL_DRAW_TO_BITMAP_ARB,GL_TRUE,
1385                         WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
1386                         WGL_COLOR_BITS_ARB,24,
1387                         WGL_ALPHA_BITS_ARB,8,
1388                         WGL_DEPTH_BITS_ARB,16,
1389                         0,0
1390                      };
1391                      valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
1392                   }
1393                }
1394             }
1395             if(valid && numFormats)
1396             {
1397                wglMakeCurrent(null, null);
1398             }
1399          }
1400
1401          wglMakeCurrent( null, null );
1402          wglMakeCurrent( oglDisplay.hdc, oglDisplay.glrc );
1403          if(oglDisplay.hdc && oglDisplay.pBuffer)
1404             wglReleasePbufferDCARB(oglDisplay.pBuffer, oglDisplay.hdc);
1405
1406          wglDestroyPbufferARB(oglDisplay.pBuffer);
1407
1408          if(!useSingleGLContext)
1409             wglMakeCurrent( null, null );
1410
1411          if(oglDisplay.glrc)
1412             wglDeleteContext(oglDisplay.glrc);
1413
1414          oglDisplay.pBuffer = wglCreatePbufferARB(oglSystem.hdc, pixelFormat, width, height, attributes);
1415          oglDisplay.hdc = wglGetPbufferDCARB(oglDisplay.pBuffer);
1416          if((oglDisplay.glrc = winCreateContext(oglDisplay.hdc, null, null, oglDisplay.capabilities.compatible)))
1417          {
1418             BITMAPINFO * info;
1419             HDC hdc = GetDC(display.window);
1420
1421             wglShareLists(oglSystem.glrc, oglDisplay.glrc);
1422             wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
1423
1424             //wglQueryPbufferARB(pBuffer, WGL_PBUFFER_WIDTH_ARB, &width);
1425             //wglQueryPbufferARB(pBuffer, WGL_PBUFFER_HEIGHT_ARB, &height);
1426
1427             // glDeleteBuffersARB(2, oglDisplay.imageBuffers);
1428
1429             if((info = (BITMAPINFO *)new0 byte[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256]))
1430             {
1431                HBITMAP newBitmap;
1432
1433                if(oglDisplay.memDC) DeleteDC(oglDisplay.memDC);
1434                oglDisplay.memDC = CreateCompatibleDC(hdc);
1435                SetMapMode(oglDisplay.memDC, MM_TEXT);
1436                info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1437                info->bmiHeader.biPlanes = 1;
1438                info->bmiHeader.biCompression = BI_RGB;
1439                info->bmiHeader.biBitCount = 32; //(uint16)GetDeviceCaps(hdc, BITSPIXEL);
1440                info->bmiHeader.biWidth = width;
1441                info->bmiHeader.biHeight = height;
1442                newBitmap = CreateDIBSection(hdc, info, DIB_RGB_COLORS, &oglDisplay.picture, null, 0);
1443                if(newBitmap)
1444                {
1445                   SelectObject(oglDisplay.memDC, newBitmap);
1446                   if(oglDisplay.memBitmap) DeleteObject(oglDisplay.memBitmap);
1447                   /*
1448                   {
1449                      PIXELFORMATDESCRIPTOR pfd = { 0 };
1450                      pfd.nSize = (short)sizeof(pfd);
1451                      pfd.nVersion = 1;
1452                      pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL;
1453                      pfd.iPixelType = PFD_TYPE_RGBA;
1454                      pfd.cColorBits = 32;
1455                      //pfd.cAlphaBits = 8;
1456                      pfd.cDepthBits = 24;
1457                      pfd.iLayerType = PFD_MAIN_PLANE;
1458
1459                      oglDisplay.hdc = oglDisplay.memDC;
1460
1461                      pixelFormat = ChoosePixelFormat(oglSystem.hdc, &pfd);
1462                      DescribePixelFormat(oglDisplay.hdc, pixelFormat, sizeof(pfd), &pfd);
1463                      SetPixelFormat(oglDisplay.hdc, pixelFormat, &pfd);
1464
1465                      oglDisplay.glrc = wglCreateContext(oglDisplay.hdc);
1466                      wglShareLists(oglSystem.glrc, oglDisplay.glrc);
1467                      wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
1468                   }
1469                   */
1470                   /*
1471                   {
1472                      const int imageSize = width * height * 4;
1473
1474                      glGenBuffersARB(2, oglDisplay.imageBuffers);
1475
1476                      glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[0]);
1477                      glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, imageSize, null, GL_STREAM_READ);
1478                      // glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[1]);
1479                      // glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, imageSize / 2, null, GL_STREAM_READ);
1480                   }
1481                   */
1482                   oglDisplay.memBitmap = newBitmap;
1483                   oglDisplay.stride = width;
1484
1485                   result = true;
1486                }
1487                delete info;
1488             }
1489             ReleaseDC(display.window, hdc);
1490          }
1491 #elif defined(__unix__) || defined(__APPLE__)
1492       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
1493          result = true;
1494       #else
1495          int attrib[] =
1496          {
1497             GLX_DOUBLEBUFFER,  True,
1498             GLX_DEPTH_SIZE,    1,
1499             GLX_RED_SIZE,      8,
1500             GLX_GREEN_SIZE,    8,
1501             GLX_BLUE_SIZE,     8,
1502             GLX_ALPHA_SIZE,    8,
1503             GLX_STENCIL_SIZE,  1,
1504             //GLX_DEPTH_SIZE,    24,
1505             GLX_RENDER_TYPE,   GLX_RGBA_BIT,
1506             GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT,
1507             None
1508          };
1509
1510          int PBattrib[] =
1511          {
1512             GLX_PBUFFER_WIDTH,   width,
1513             GLX_PBUFFER_HEIGHT,  height,
1514             GLX_LARGEST_PBUFFER, False,
1515             None
1516          };
1517
1518          // choose a pixel format that meets our minimum requirements
1519          int count = 0;
1520
1521          GLXFBConfig *config = glXChooseFBConfig(xGlobalDisplay, DefaultScreen(xGlobalDisplay), attrib, &count);
1522          if(config)
1523          {
1524             if(oglDisplay.pixmap)
1525             {
1526                XFreePixmap(xGlobalDisplay, oglDisplay.pixmap);
1527                oglDisplay.pixmap = None;
1528             }
1529             if(oglDisplay.shapePixmap)
1530             {
1531                XFreePixmap(xGlobalDisplay, oglDisplay.shapePixmap);
1532                oglDisplay.shapePixmap = None;
1533             }
1534
1535             // Free Shared Memory Pixmap
1536             if(oglDisplay.image)
1537             {
1538                if(oglDisplay.shminfoShape.shmid != -1)
1539                {
1540                   XShmDetach(xGlobalDisplay, &oglDisplay.shminfo);
1541                   if(oglDisplay.shminfo.shmaddr != (void *)-1)
1542                      shmdt(oglDisplay.shminfo.shmaddr);
1543                   shmctl(oglDisplay.shminfo.shmid, IPC_RMID, 0);
1544                }
1545                XDestroyImage(oglDisplay.image);
1546                oglDisplay.image = None;
1547             }
1548             if(oglDisplay.shapeImage)
1549             {
1550                if(oglDisplay.shminfoShape.shmid != -1)
1551                {
1552                   XShmDetach(xGlobalDisplay, &oglDisplay.shminfoShape);
1553                   if(oglDisplay.shminfoShape.shmaddr != (void *)-1)
1554                      shmdt(oglDisplay.shminfoShape.shmaddr);
1555                   shmctl(oglDisplay.shminfoShape.shmid, IPC_RMID, 0);
1556                }
1557                XDestroyImage(oglDisplay.shapeImage);
1558                oglDisplay.shapeImage = None;
1559             }
1560
1561             if(oglDisplay.windowPicture)
1562                XRenderFreePicture(xGlobalDisplay, oglDisplay.windowPicture);
1563             if(oglDisplay.pixmapPicture)
1564                XRenderFreePicture(xGlobalDisplay, oglDisplay.pixmapPicture);
1565
1566             if(oglDisplay.pixmap)
1567                XFreePixmap(xGlobalDisplay, oglDisplay.pixmap);
1568
1569             if(oglDisplay.glContext)
1570               glXDestroyContext(xGlobalDisplay, oglDisplay.glContext);
1571             if(oglDisplay.pBuffer)
1572                glXDestroyPbuffer(xGlobalDisplay, oglDisplay.pBuffer);
1573
1574             oglDisplay.pBuffer = glXCreatePbuffer(xGlobalDisplay, config[0], PBattrib);
1575             if(oglDisplay.pBuffer)
1576             {
1577                oglDisplay.glContext = glXCreateNewContext(xGlobalDisplay, config[0], GLX_RGBA_TYPE, oglSystem.glContext, True);
1578                if(oglDisplay.glContext)
1579                {
1580                   glXMakeCurrent(xGlobalDisplay, None, null);
1581                   glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext);
1582
1583                   // Initialize Shared Memory Pixmap
1584                   oglDisplay.image = XShmCreateImage(xGlobalDisplay, DefaultVisual(xGlobalDisplay, DefaultScreen(xGlobalDisplay)), 32,
1585                      ZPixmap, null, &oglDisplay.shminfo, width, height);
1586                   if(oglDisplay.image)
1587                   {
1588                      oglDisplay.shminfo.shmid = shmget(IPC_PRIVATE,
1589                         oglDisplay.image->bytes_per_line * oglDisplay.image->height, IPC_CREAT|0777);
1590                      if(oglDisplay.shminfo.shmid != -1)
1591                      {
1592                         oglDisplay.shminfo.shmaddr = shmat(oglDisplay.shminfo.shmid, 0, 0);
1593                         if(oglDisplay.shminfo.shmaddr != (void *)-1)
1594                         {
1595                            oglDisplay.shminfo.readOnly = False;
1596                            if(XShmAttach(xGlobalDisplay, &oglDisplay.shminfo))
1597                            {
1598                               oglDisplay.pixmap = XShmCreatePixmap(xGlobalDisplay, (X11Window)display.window, oglDisplay.shminfo.shmaddr,
1599                                  &oglDisplay.shminfo, width, height, 32);
1600
1601                               // Initialize Shared Memory Shape Pixmap
1602                               oglDisplay.shapeImage = XShmCreateImage(xGlobalDisplay, DefaultVisual(xGlobalDisplay, DefaultScreen(xGlobalDisplay)), 1,
1603                                  ZPixmap, null, &oglDisplay.shminfoShape, width, height);
1604                               if(oglDisplay.shapeImage)
1605                               {
1606                                  oglDisplay.shminfoShape.shmid = shmget(IPC_PRIVATE,
1607                                     oglDisplay.shapeImage->bytes_per_line * oglDisplay.shapeImage->height, IPC_CREAT|0777);
1608                                  if(oglDisplay.shminfoShape.shmid != -1)
1609                                  {
1610                                     oglDisplay.shminfoShape.shmaddr = shmat(oglDisplay.shminfoShape.shmid, 0, 0);
1611                                     if(oglDisplay.shminfoShape.shmaddr != (void *)-1)
1612                                     {
1613                                        oglDisplay.shminfoShape.readOnly = False;
1614                                        if(XShmAttach(xGlobalDisplay, &oglDisplay.shminfoShape))
1615                                        {
1616                                           oglDisplay.shapePixmap = XShmCreatePixmap(xGlobalDisplay, (X11Window)display.window, oglDisplay.shminfoShape.shmaddr,
1617                                              &oglDisplay.shminfoShape, width, height, 1);
1618                                           //oglDisplay.shapePixmap = XCreatePixmap(xGlobalDisplay, (X11Window)display.window, width, height, 1);
1619
1620                                           {
1621                                              XRenderPictureAttributes attributes = { 0 };
1622                                              XRenderPictFormat * format = XRenderFindStandardFormat(xGlobalDisplay, /*PictStandardRGB24*/ PictStandardARGB32);
1623                                              #if !defined(__APPLE__)
1624                                              attributes.repeat = RepeatNormal;
1625                                              #else
1626                                              attributes.repeat = 1;
1627                                              #endif
1628                                              oglDisplay.pixmapPicture = XRenderCreatePicture(xGlobalDisplay, oglDisplay.pixmap, format, CPRepeat, &attributes);
1629                                              oglDisplay.windowPicture = XRenderCreatePicture(xGlobalDisplay, (X11Window)display.window, format, 0, &attributes);
1630                                              oglDisplay.shapePicture = XRenderCreatePicture(xGlobalDisplay, oglDisplay.shapePixmap,
1631                                                 XRenderFindStandardFormat(xGlobalDisplay, PictStandardA1), 0, &attributes);
1632                                           }
1633
1634                                           oglDisplay.picture = oglDisplay.shminfo.shmaddr;
1635                                           oglDisplay.stride = oglDisplay.image->bytes_per_line / 4;
1636
1637                                           result = true;
1638                                        }
1639                                     }
1640                                  }
1641                               }
1642                            }
1643                         }
1644                      }
1645                   }
1646                }
1647             }
1648             XFree(config);
1649          }
1650      #endif
1651 #endif
1652          CreateDisplay(display);
1653 #if defined(__WIN32__)
1654          wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
1655 #elif defined(__unix__) || defined(__APPLE__)
1656       #if defined(__ANDROID__) || defined(__ODROID__)
1657          width = eglWidth;
1658          height = eglHeight;
1659       #elif defined(__EMSCRIPTEN__)
1660          emscripten_webgl_make_context_current(oglSystem.glc);
1661       #else
1662          glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext);
1663       #endif
1664 #endif
1665       }
1666       else
1667 #endif
1668          result = true;
1669
1670       SETCAPS(oglDisplay.capabilities);
1671
1672       if(display.alphaBlend && result)
1673          initialDisplaySetup(display, true, false);
1674
1675       if(!result && display.alphaBlend)
1676       {
1677          printf("Alpha blending windows not supported on this display\n");
1678       }
1679       if(!result)
1680          return false;
1681
1682       result = false;
1683
1684       glViewport(0,0,width,height);
1685       GLMatrixMode(MatrixMode::projection);
1686       GLLoadIdentity();
1687       GLOrtho(0,width,height,0,0.0,1.0);
1688       displayWidth = display.width = width;
1689       displayHeight = display.height = height;
1690
1691       if(!oglDisplay.flippingBuffer || oglDisplay.flipBufW < width || oglDisplay.flipBufH < height)
1692       {
1693          oglDisplay.flipBufW = width;
1694          oglDisplay.flipBufH = height;
1695 #if defined(_GLES) || defined(_GLES2)
1696          result = true;
1697 #else
1698          oglDisplay.flippingBuffer = renew oglDisplay.flippingBuffer ColorAlpha [width * height];
1699 #endif
1700       }
1701       if(oglDisplay.flippingBuffer || !width || !height)
1702          result = true;
1703
1704       return result;
1705    }
1706
1707    void DisplayPosition(Display display, int x, int y)
1708    {
1709       OGLDisplay oglDisplay = display.driverData;
1710
1711       oglDisplay.x = x;
1712       oglDisplay.y = y;
1713    }
1714
1715    void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
1716    {
1717    }
1718
1719    void RestorePalette(Display display)
1720    {
1721    }
1722
1723    void StartUpdate(Display display)
1724    {
1725 #if ENABLE_GL_VAO
1726       if(glCaps_vao)
1727       {
1728          OGLDisplay oglDisplay = display.driverData;
1729          glBindVertexArray(oglDisplay.vao);
1730       }
1731 #endif
1732       GLABBindBuffer(GL_ARRAY_BUFFER, 0);
1733       GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1734 #if ENABLE_GL_SHADERS
1735       activeProgram = 0;
1736 #endif
1737    }
1738
1739    void EndUpdate(Display display)
1740    {
1741    }
1742
1743    void Scroll(Display display, Box scroll, int x, int y, Extent dirty)
1744    {
1745    }
1746
1747    void Update(Display display, Box updateBox)
1748    {
1749 #if defined(__WIN32__) || defined(USEPBUFFER)
1750       OGLDisplay oglDisplay = display.driverData;
1751 #endif
1752
1753 #if !defined(__ANDROID__)
1754       /*glFlush();
1755       glFinish();*/
1756 #endif
1757
1758 #if defined(__WIN32__) || defined(USEPBUFFER)
1759       if(display.alphaBlend)
1760       {
1761          glPixelStorei(GL_PACK_ALIGNMENT, 4);
1762          glPixelStorei(GL_PACK_ROW_LENGTH, oglDisplay.stride);
1763          glPixelStorei(GL_PACK_SKIP_ROWS, 0);
1764          glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
1765          glReadPixels(0,0,display.width,display.height,GL_BGRA_EXT,GL_UNSIGNED_BYTE, oglDisplay.picture);
1766
1767          {
1768 #if defined(__WIN32__)
1769             HDC hdc = GetDC(0);
1770             POINT point = { oglDisplay.x, oglDisplay.y};
1771             POINT srcPoint = { 0, 0 };
1772             BLENDFUNCTION blend = { 0 };
1773             SIZE size;
1774             size.cx = display.width;
1775             size.cy = display.height;
1776             blend.BlendOp = AC_SRC_OVER;
1777             blend.BlendFlags = 0;
1778             blend.SourceConstantAlpha = 255;
1779             blend.AlphaFormat = AC_SRC_ALPHA;
1780
1781             /*
1782             // Process partial images.  Mapping the buffer waits for
1783             // outstanding DMA transfers into the buffer to finish.
1784             glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[0]);
1785             oglDisplay.pboMemory1 = (byte *)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
1786
1787             // glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[1]);
1788             // oglDisplay.pboMemory2 = (byte *)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB,GL_READ_ONLY);
1789
1790
1791             memcpy(oglDisplay.picture, oglDisplay.pboMemory1, display.width * display.height * 4);
1792             //memcpy(oglDisplay.picture + display.width * display.height * 4 / 2, oglDisplay.pboMemory2, display.width * display.height * 4/ 2);
1793             */
1794
1795             UpdateLayeredWindow(display.window, hdc, &point, &size, oglDisplay.memDC, &srcPoint, 0, &blend, ULW_ALPHA);
1796             /*
1797
1798             // Unmap the image buffers
1799             glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[0]);
1800             glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
1801
1802             // glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[1]);
1803             // glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
1804
1805             // Bind two different buffer objects and start the glReadPixels
1806             // asynchronously. Each call will return directly after
1807             // starting the DMA transfer.
1808             glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[0]);
1809             glReadPixels(0, 0, display.width, display.height, GL_BGRA, GL_UNSIGNED_BYTE, 0);
1810
1811             // glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[1]);
1812             // glReadPixels(0, display.height/2, display.width, display.height/2, GL_BGRA, GL_UNSIGNED_BYTE, 0);
1813             */
1814
1815             ReleaseDC(0, hdc);
1816 #elif defined(__unix__) || defined(__APPLE__)
1817       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
1818       #else
1819             XTransform transform =
1820             {
1821                {
1822                   { (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)),  (int)(0 * (1 << 16)) },
1823                   { (int)(0.0f),           (int)(-1.0f * (1<<16)), (int)(0 * (1<<16)) },
1824                   { (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)),  (int)(1.0f * (1<<16)) }
1825                }
1826             };
1827             XRenderSetPictureTransform(xGlobalDisplay, oglDisplay.pixmapPicture, &transform);
1828             XRenderComposite(xGlobalDisplay, PictOpSrc, oglDisplay.pixmapPicture, None, oglDisplay.shapePicture, 0, 0, 0, 0, 0, 0, display.width, display.height);
1829             XRenderComposite(xGlobalDisplay, PictOpSrc, oglDisplay.pixmapPicture, None, oglDisplay.windowPicture, 0, 0, 0, 0, 0, 0, display.width, display.height);
1830             #if !defined(__APPLE__)
1831             XShapeCombineMask(xGlobalDisplay, (X11Window)display.window, ShapeInput, 0, 0, oglDisplay.shapePixmap, ShapeSet);
1832             #else
1833             XShapeCombineMask(xGlobalDisplay, display.window, 2, 0, 0, oglDisplay.shapePixmap, ShapeSet);
1834             #endif
1835             XFlush(xGlobalDisplay);
1836      #endif
1837 #endif
1838          }
1839       }
1840       else
1841 #endif
1842       {
1843 #if defined(__WIN32__)
1844          //wglSwapLayerBuffers(oglDisplay.hdc,WGL_SWAP_MAIN_PLANE);
1845          SwapBuffers(oglDisplay.hdc);
1846          //ecere::sys::Sleep(0.1);
1847 #elif defined(__unix__) || defined(__APPLE__)
1848       #if defined(__ANDROID__) || defined(__ODROID__)
1849          egl_swap_buffers();
1850       #elif defined(__EMSCRIPTEN__)
1851       #else
1852          glXSwapBuffers(xGlobalDisplay, (GLXDrawable)display.window);
1853       #endif
1854 #endif
1855       }
1856    }
1857
1858    void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
1859    {
1860       if(bitmap.driverData)
1861       {
1862          GLuint tex = (GLuint)(uintptr)bitmap.driverData;
1863          glDeleteTextures(1, &tex);
1864          bitmap.driverData = 0;
1865       }
1866       bitmap.driver = ((subclass(DisplayDriver))class(LFBDisplayDriver));
1867    }
1868
1869    bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
1870    {
1871       OGLSystem oglSystem = displaySystem.driverData;
1872       GLCapabilities capabilities = oglSystem.capabilities;
1873       bool result = false;
1874       Bitmap mipMap { };
1875       GLuint glBitmap = 0;
1876
1877       uint w = width, h = height;
1878       if(!capabilities.nonPow2Textures)
1879       {
1880          w = pow2i(w);
1881          h = pow2i(h);
1882       }
1883       w = Min(w, oglSystem.maxTextureSize);
1884       h = Min(h, oglSystem.maxTextureSize);
1885
1886       glGenTextures(1, &glBitmap);
1887       glBindTexture(GL_TEXTURE_2D, glBitmap);
1888
1889       glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
1890
1891       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1892       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1893
1894       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1895       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1896
1897 #if ENABLE_GL_FFP
1898       if(!capabilities.shaders)
1899          glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1900 #endif
1901
1902       mipMap.Allocate(null, w, h, w, pixelFormatRGBA, false);
1903
1904       // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture);
1905       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture);
1906
1907       delete mipMap;
1908
1909       bitmap.driverData = (void *)(uintptr)glBitmap;
1910       bitmap.driver = displaySystem.driver;
1911       bitmap.width = w;
1912       bitmap.height = h;
1913
1914       result = true;
1915       return result;
1916    }
1917
1918    bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps, uint cubeMapFace)
1919    {
1920       bool result = false;
1921       OGLSystem oglSystem = displaySystem.driverData;
1922       GLCapabilities capabilities = oglSystem.capabilities;
1923       Bitmap convBitmap = bitmap;
1924       bool oldStyleCubeMap = (cubeMapFace >> 3) != 0;
1925       int face = (cubeMapFace & 7) - 1;
1926       if(bitmap.keepData)
1927       {
1928          convBitmap = { };
1929          convBitmap.Copy(bitmap);
1930       }
1931
1932       // Pre process the bitmap... First make it 32 bit
1933       if(/*bitmap.pixelFormat == pixelFormatRGBA || */convBitmap.Convert(null, pixelFormat888, null))
1934       {
1935          int c, level;
1936          uint w = bitmap.width, h = bitmap.height;
1937          GLuint glBitmap = cubeMapFace && face > 0 ? (GLuint)(uintptr)bitmap.driverData : 0;
1938          int target = cubeMapFace ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
1939          if(!capabilities.nonPow2Textures)
1940          {
1941             w = pow2i(w);
1942             h = pow2i(h);
1943          }
1944          w = Min(w, oglSystem.maxTextureSize);
1945          h = Min(h, oglSystem.maxTextureSize);
1946
1947          if(mipMaps)
1948          {
1949             while(w * 2 < h) w *= 2;
1950             while(h * 2 < w) h *= 2;
1951          }
1952
1953          // Switch ARGB to RGBA
1954          //if(bitmap.format != pixelFormatRGBA)
1955          {
1956             int size = convBitmap.stride * convBitmap.height;
1957             for(c = 0; c < size; c++)
1958             {
1959                // ((ColorRGBA *)bitmap.picture)[c] = ((ColorAlpha *)bitmap.picture)[c];
1960                // TODO:
1961                ColorAlpha color = ((ColorAlpha *)convBitmap.picture)[c];
1962                ((ColorRGBA *)convBitmap.picture)[c] = ColorRGBA { color.color.r, color.color.g, color.color.b, color.a };
1963             }
1964          }
1965          // convBitmap.pixelFormat = pixelFormat888;
1966
1967          if(cubeMapFace && oldStyleCubeMap)
1968          {
1969             if(face == 0 || face == 1 || face == 4 || face == 5)
1970             {
1971                uint w = convBitmap.width;
1972                uint32 * tmp = new uint [convBitmap.width];
1973                int x, y;
1974                for(y = 0; y < convBitmap.height; y++)
1975                {
1976                   uint32 * pic = (uint32 *)((byte *)convBitmap.picture + y * w * 4);
1977                   for(x = 0; x < w; x++)
1978                      tmp[x] = pic[w-1-x];
1979                   memcpy(pic, tmp, w*4);
1980                }
1981                delete tmp;
1982             }
1983             else if(face == 2 || face == 3)
1984             {
1985                int y;
1986                Bitmap tmp { };
1987                tmp.Allocate(null, convBitmap.width, convBitmap.height, 0, convBitmap.pixelFormat, false);
1988                for(y = 0; y < convBitmap.height; y++)
1989                {
1990                   memcpy(tmp.picture + convBitmap.width * 4 * y,
1991                      convBitmap.picture + (convBitmap.height-1-y) * convBitmap.width * 4,
1992                      convBitmap.width * 4);
1993                }
1994                memcpy(convBitmap.picture, tmp.picture, convBitmap.sizeBytes);
1995                delete tmp;
1996             }
1997          }
1998
1999          glGetError();
2000          if(!glBitmap)
2001             glGenTextures(1, &glBitmap);
2002          if(glBitmap == 0)
2003          {
2004             //int error = glGetError();
2005             return false;
2006          }
2007
2008          glBindTexture(target, glBitmap);
2009          glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
2010
2011          glTexParameteri(target, GL_TEXTURE_MIN_FILTER, mipMaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
2012          glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2013
2014          //glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2015
2016          //glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP);
2017          //glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP);
2018
2019          glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2020          glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2021
2022 #ifndef GL_TEXTURE_WRAP_R
2023    #define GL_TEXTURE_WRAP_R 0x8072
2024 #endif
2025
2026 #if !defined(__EMSCRIPTEN__)
2027          if(cubeMapFace)
2028             glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
2029 #endif
2030
2031 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
2032          glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0 );
2033 #endif
2034
2035 #if ENABLE_GL_FFP
2036       if(!capabilities.shaders)
2037          glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
2038 #endif
2039
2040          result = true;
2041
2042          for(level = 0; result && (w >= 1 || h >= 1); level++, w >>= 1, h >>= 1)
2043          {
2044             Bitmap mipMap;
2045             if(!w) w = 1;
2046             if(!h) h = 1;
2047             if(bitmap.width != w || bitmap.height != h)
2048             {
2049                mipMap = Bitmap { };
2050                if(mipMap.Allocate(null, w, h, w, convBitmap.pixelFormat, false))
2051                {
2052                   Surface mipSurface = mipMap.GetSurface(0,0,null);
2053                   mipSurface.blend = false;
2054                   mipSurface.Filter(convBitmap, 0,0,0,0, w, h, convBitmap.width, convBitmap.height);
2055                   delete mipSurface;
2056                }
2057                else
2058                {
2059                   result = false;
2060                   delete mipMap;
2061                }
2062             }
2063             else
2064                mipMap = convBitmap;
2065
2066             if(result)
2067             {
2068                int error;
2069                //int width = 0;
2070                glGetError();
2071                // glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture);
2072                glTexImage2D(cubeMapFace ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + face : GL_TEXTURE_2D, level, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture);
2073                //printf("Calling glTexImage2D\n");
2074                //glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, &width);
2075                //printf("width = %d (Should be %d, %d)\n", width, w, h);
2076                if((error = glGetError()))
2077                {
2078                   //Logf("OpenGL Bitmap MakeDD error: %d...\n", error);
2079                   //printf("OpenGL Bitmap MakeDD error: %d...\n", error);
2080                   result = false;
2081                }
2082             }
2083             if(mipMap != convBitmap)
2084                delete mipMap;
2085             if(!mipMaps) break;
2086          }
2087
2088          convBitmap.driver.FreeBitmap(convBitmap.displaySystem, convBitmap);
2089          bitmap.driverData = (void *)(uintptr)glBitmap;
2090          bitmap.driver = displaySystem.driver;
2091          if(bitmap.keepData)
2092             delete convBitmap;
2093
2094          if(!result)
2095             FreeBitmap(displaySystem, bitmap);
2096          else if(oglSystem.loadingFont)
2097          {
2098             glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2099             glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2100             oglSystem.loadingFont = false;
2101          }
2102       }
2103       return result;
2104    }
2105
2106    void ReleaseSurface(Display display, Surface surface)
2107    {
2108       glDisable(GL_SCISSOR_TEST);
2109       delete surface.driverData;
2110       surface.driverData = null;
2111    }
2112
2113    bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x, int y, Box clip)
2114    {
2115       return false;
2116    }
2117
2118    bool GetSurface(Display display, Surface surface, int x,int y, Box clip)
2119    {
2120       bool result = false;
2121       OGLDisplay oglDisplay = display.driverData;
2122       OGLSurface oglSurface = surface.driverData = OGLSurface { };
2123       if(oglSurface)
2124       {
2125          SETCAPS(oglDisplay.capabilities);
2126          if(displayWidth != display.width || displayHeight != display.height)
2127          {
2128             displayWidth = display.width;
2129             displayHeight = display.height;
2130
2131             glViewport(0,0,display.width,display.height);
2132             GLLoadIdentity();
2133             GLOrtho(0,display.width,display.height,0,0.0,1.0);
2134          }
2135
2136          surface.offset.x = x;
2137          surface.offset.y = y;
2138          surface.unclippedBox = surface.box = clip;
2139          oglSurface.bitmapMult[0] = 1;
2140          oglSurface.bitmapMult[1] = 1;
2141          oglSurface.bitmapMult[2] = 1;
2142          oglSurface.bitmapMult[3] = 1;
2143
2144          glEnable(GL_SCISSOR_TEST);
2145          glScissor(
2146             x+clip.left,
2147             (display.height) -(y+clip.bottom)-1,
2148             clip.right-clip.left+1,
2149             clip.bottom-clip.top+1);
2150          result = true;
2151       }
2152       return result;
2153    }
2154
2155    void Clip(Display display, Surface surface, Box clip)
2156    {
2157       Box box;
2158
2159       if(clip != null)
2160       {
2161          box = clip;
2162          box.Clip(surface.unclippedBox);
2163          surface.box = box;
2164       }
2165       else
2166          box = surface.box = surface.unclippedBox;
2167       box.left += surface.offset.x;
2168       box.top  += surface.offset.y;
2169       box.right+= surface.offset.x;
2170       box.bottom += surface.offset.y;
2171
2172       glScissor(
2173          box.left,display.height - box.bottom - 1,
2174          box.right-box.left+1, box.bottom-box.top+1);
2175    }
2176
2177    bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
2178    {
2179       bool result = false;
2180       OGLDisplay oglDisplay = display.driverData;
2181       ColorAlpha * flippingBuffer = oglDisplay.flippingBuffer;
2182
2183       if(oglDisplay.flippingBuffer)
2184       {
2185          if(bitmap.pixelFormat != pixelFormat888 || bitmap.width < w || bitmap.height < h)
2186          {
2187             bitmap.Free();
2188             bitmap.Allocate(null, w,h,w, pixelFormat888, false);
2189          }
2190          if(bitmap)
2191          {
2192             uint row;
2193
2194             glPixelStorei(GL_PACK_ALIGNMENT, 4);
2195 #if ENABLE_GL_LEGACY
2196             glPixelStorei(GL_PACK_ROW_LENGTH, bitmap.stride);
2197             glPixelStorei(GL_PACK_SKIP_ROWS, 0);
2198             glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
2199 #endif
2200             glReadPixels(x,display.height-h-y,w,h,GL_BGRA_EXT,GL_UNSIGNED_BYTE, flippingBuffer);
2201
2202             // Need a flip...
2203             for(row = 0; row<h; row++)
2204                CopyBytesBy4(((ColorAlpha *)bitmap.picture) + row * w, ((ColorAlpha *)flippingBuffer) + (h-row-1) * w, w);
2205             result = true;
2206          }
2207       }
2208       return result;
2209    }
2210
2211    void SetForeground(Display display, Surface surface, ColorAlpha color)
2212    {
2213       OGLSurface oglSurface = surface.driverData;
2214
2215       oglSurface.foreground[0] = color.color.r/255.0f;
2216       oglSurface.foreground[1] = color.color.g/255.0f;
2217       oglSurface.foreground[2] = color.color.b/255.0f;
2218       //oglSurface.foreground[3] = 1.0f;
2219       oglSurface.foreground[3] = color.a/255.0f;
2220
2221       //if(!oglSurface.foreground[3])printf("bug");
2222    }
2223
2224    void SetBackground(Display display, Surface surface, ColorAlpha color)
2225    {
2226       OGLSurface oglSurface = surface.driverData;
2227
2228       oglSurface.background[0] = color.color.r/255.0f;
2229       oglSurface.background[1] = color.color.g/255.0f;
2230       oglSurface.background[2] = color.color.b/255.0f;
2231       //oglSurface.background[3] = 1.0;
2232       oglSurface.background[3] = color.a/255.0f;
2233    }
2234
2235    void SetBlitTint(Display display, Surface surface, ColorAlpha color)
2236    {
2237       OGLSurface oglSurface = surface.driverData;
2238
2239       oglSurface.bitmapMult[0] = color.color.r/255.0f;
2240       oglSurface.bitmapMult[1] = color.color.g/255.0f;
2241       oglSurface.bitmapMult[2] = color.color.b/255.0f;
2242       oglSurface.bitmapMult[3] = color.a/255.0f;
2243    }
2244
2245    ColorAlpha GetPixel(Display display, Surface surface,int x,int y)
2246    {
2247       return 0;
2248    }
2249
2250    void PutPixel(Display display, Surface surface,int x,int y)
2251    {
2252       OGLSurface oglSurface = surface.driverData;
2253       GLColor4fv(oglSurface.foreground);
2254       GLBegin(GL_POINTS);
2255       // glVertex2i(x+surface.offset.x, y+surface.offset.y);
2256       GLVertex2f(x+surface.offset.x + 0.5f, y+surface.offset.y + 0.5f);
2257       GLEnd();
2258    }
2259
2260    void DrawLine(Display display, Surface surface, int _x1, int _y1, int _x2, int _y2)
2261    {
2262       OGLSurface oglSurface = surface.driverData;
2263       float x1 = _x1, x2 = _x2, y1 = _y1, y2 = _y2;
2264       if(_x1 == _x2)
2265       {
2266          if(_y2 >= _y1)
2267             y2 += 1;
2268          else
2269             y1 += 1;
2270       }
2271       else if(_y1 == _y2)
2272       {
2273          if(_x2 >= _x1)
2274             x2 += 1;
2275          else
2276             x1 += 1;
2277       }
2278       x1 += surface.offset.x;
2279       y1 += surface.offset.y;
2280       x2 += surface.offset.x;
2281       y2 += surface.offset.y;
2282
2283       GLColor4fv(oglSurface.foreground);
2284       GLBegin(GL_LINES);
2285       if(stippleEnabled)
2286       {
2287          GLTexCoord2f(0.5f, 0);
2288          GLVertex2f(x1 + 0.5f, y1 + 0.5f);
2289          GLTexCoord2f(Max(x2-x1, y2-y1) + 0.5f, 0);
2290          GLVertex2f(x2 + 0.5f, y2 + 0.5f);
2291       }
2292       else
2293       {
2294          /*
2295          GLVertex2i(x1, y1);
2296          GLVertex2i(x2, y2);
2297          */
2298          GLVertex2f(x1 + 0.5f, y1 + 0.5f);
2299          GLVertex2f(x2 + 0.5f, y2 + 0.5f);
2300       }
2301
2302       GLEnd();
2303    }
2304
2305    void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
2306    {
2307       OGLSurface oglSurface = surface.driverData;
2308       x1 += surface.offset.x;
2309       y1 += surface.offset.y;
2310       x2 += surface.offset.x;
2311       y2 += surface.offset.y;
2312
2313       GLColor4fv(oglSurface.foreground);
2314       if(stippleEnabled)
2315       {
2316          GLBegin(GL_LINES);
2317
2318          GLTexCoord2f(0.5f, 0);
2319          GLVertex2f(x1 + 0.5f, y1 + 0.5f);
2320          GLTexCoord2f(y2-y1 + 0.5f, 0);
2321          GLVertex2f(x1 + 0.5f, y2 + 0.5f);
2322
2323          GLTexCoord2f(0.5f, 0);
2324          GLVertex2f(x1 + 0.5f, y2 + 0.5f);
2325          GLTexCoord2f(x2 - x1 + 0.5f, 0);
2326          GLVertex2f(x2 + 0.5f, y2 + 0.5f);
2327
2328          GLTexCoord2f(0.5f, 0);
2329          GLVertex2f(x2 + 0.5f, y2 + 0.5f);
2330          GLTexCoord2f(y1 - y2 + 0.5f, 0);
2331          GLVertex2f(x2 + 0.5f, y1 + 0.5f);
2332
2333          GLTexCoord2f(0.5f, 0);
2334          GLVertex2f(x2 + 0.5f, y1 + 0.5f);
2335          GLTexCoord2f(x1 - x2 + 0.5f, 0);
2336          GLVertex2f(x1 + 0.5f, y1 + 0.5f);
2337       }
2338       else
2339       {
2340          GLBegin(GL_LINE_LOOP);
2341          /*
2342          glVertex2i(x1, y1);
2343          glVertex2i(x1, y2);
2344          glVertex2i(x2, y2);
2345          glVertex2i(x2, y1);
2346          */
2347          GLVertex2f(x1 + 0.5f, y1 + 0.5f);
2348          GLVertex2f(x1 + 0.5f, y2 + 0.5f);
2349          GLVertex2f(x2 + 0.5f, y2 + 0.5f);
2350          GLVertex2f(x2 + 0.5f, y1 + 0.5f);
2351       }
2352       GLEnd();
2353    }
2354
2355    void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
2356    {
2357       OGLSurface oglSurface = surface.driverData;
2358
2359       GLColor4fv(oglSurface.background);
2360
2361       GLRecti(x1+surface.offset.x, y1+surface.offset.y,
2362               x2+surface.offset.x + 1, y2+surface.offset.y + 1);
2363       /*
2364       GLRectf(x1+surface.offset.x, y1+surface.offset.y,
2365               x2+surface.offset.x + 1, y2+surface.offset.y + 1);
2366       */
2367    }
2368
2369    void Clear(Display display, Surface surface, ClearType type)
2370    {
2371       OGLDisplay oglDisplay = display.driverData;
2372       OGLSurface oglSurface = surface.driverData;
2373
2374       //Logf("Clear\n");
2375       if(type != depthBuffer)
2376          glClearColor(oglSurface.background[0], oglSurface.background[1], oglSurface.background[2], oglSurface.background[3]);
2377       if(type != colorBuffer && !oglDisplay.depthWrite)
2378       {
2379          glDepthMask((byte)bool::true);
2380       }
2381       glClear(((type != depthBuffer) ? GL_COLOR_BUFFER_BIT : 0) |
2382               ((type != colorBuffer) ? GL_DEPTH_BUFFER_BIT : 0));
2383       if(type != colorBuffer && !oglDisplay.depthWrite)
2384       {
2385          glDepthMask((byte)bool::false);
2386       }
2387    }
2388
2389    bool ConvertBitmap(DisplaySystem displaySystem, Bitmap bitmap, PixelFormat format, ColorAlpha * palette)
2390    {
2391       return true;
2392    }
2393
2394    void Blit(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h)
2395    {
2396       OGLSurface oglSurface = surface.driverData;
2397       GLuint tex = (GLuint)(uintptr)bitmap.driverData;
2398       if(!tex) return;
2399
2400       if(!oglSurface.writingText)
2401       {
2402          // glTranslatef(-0.375f, -0.375f, 0.0f);
2403          GLSetupTexturing(true);
2404          GLColor4fv(oglSurface.bitmapMult);
2405          glBindTexture(GL_TEXTURE_2D, tex);
2406          GLBegin(GLIMTKMode::quads);
2407       }
2408       else if(lastBlitTex != tex)
2409       {
2410          if(lastBlitTex)
2411             GLEnd();
2412          glBindTexture(GL_TEXTURE_2D, tex);
2413          GLBegin(GLIMTKMode::quads);
2414          lastBlitTex = tex;
2415       }
2416
2417       if(h < 0)
2418       {
2419          GLTexCoord2f((float)sx/ bitmap.width, (float)(sy-h)/ bitmap.height);
2420          GLVertex2i(dx+surface.offset.x, dy+surface.offset.y);
2421          GLTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy-h)/ bitmap.height);
2422          GLVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
2423          GLTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height);
2424          GLVertex2i(dx+w+surface.offset.x, dy-h+surface.offset.y);
2425          GLTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height);
2426          GLVertex2i(dx+surface.offset.x, dy-h+surface.offset.y);
2427       }
2428       else
2429       {
2430          /*
2431          GLTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height);
2432          GLVertex2i(dx+surface.offset.x, dy+surface.offset.y);
2433          GLTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height);
2434          GLVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
2435          GLTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy+h)/ bitmap.height);
2436          GLVertex2i(dx+w+surface.offset.x, dy+h+surface.offset.y);
2437          GLTexCoord2f((float)sx/ bitmap.width, (float)(sy+h)/ bitmap.height);
2438          GLVertex2i(dx+surface.offset.x, dy+h+surface.offset.y);
2439          */
2440
2441          GLTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height);
2442          GLVertex2f((float)dx+surface.offset.x, (float)dy+surface.offset.y);
2443          GLTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height);
2444          GLVertex2f((float)dx+w+surface.offset.x, (float)dy+surface.offset.y);
2445          GLTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy+h)/ bitmap.height);
2446          GLVertex2f((float)dx+w+surface.offset.x, (float)dy+h+surface.offset.y);
2447          GLTexCoord2f((float)sx/ bitmap.width, (float)(sy+h)/ bitmap.height);
2448          GLVertex2f((float)dx+surface.offset.x, (float)dy+h+surface.offset.y);
2449       }
2450       if(!oglSurface.writingText)
2451       {
2452          GLEnd();
2453          GLSetupTexturing(false);
2454          //glTranslate(0.375, 0.375, 0.0);
2455       }
2456    }
2457
2458    void Stretch(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2459    {
2460       OGLSurface oglSurface = surface.driverData;
2461
2462       //glTranslate(-0.375, -0.375, 0.0);
2463
2464       GLSetupTexturing(true);
2465       glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)bitmap.driverData);
2466
2467       GLColor4fv(oglSurface.bitmapMult);
2468
2469       GLBegin(GLIMTKMode::quads);
2470
2471       if(h < 0)
2472       {
2473          GLTexCoord2f((float)(sx)/ bitmap.width, (float)(sy+sh)/ bitmap.height);
2474          GLVertex2i(dx+surface.offset.x, dy+surface.offset.y);
2475
2476          GLTexCoord2f((float)(sx+sw) / bitmap.width, (float)(sy+sh)/ bitmap.height);
2477          GLVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
2478
2479          GLTexCoord2f((float)(sx+sw)/ bitmap.width, (float)(sy)/ bitmap.height);
2480          GLVertex2i(dx+w+surface.offset.x, dy-h+surface.offset.y);
2481
2482          GLTexCoord2f((float)(sx) / bitmap.width, (float)(sy)/ bitmap.height);
2483          GLVertex2i(dx+surface.offset.x, dy-h+surface.offset.y);
2484       }
2485       else
2486       {
2487          GLTexCoord2f((float)(sx) / bitmap.width, (float)(sy)/ bitmap.height);
2488          GLVertex2i(dx+surface.offset.x, dy+surface.offset.y);
2489
2490          GLTexCoord2f((float)(sx+sw)/ bitmap.width, (float)(sy)/ bitmap.height);
2491          GLVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
2492
2493          GLTexCoord2f((float)(sx+sw) / bitmap.width, (float)(sy+sh)/ bitmap.height);
2494          GLVertex2i(dx+w+surface.offset.x, dy+h+surface.offset.y);
2495
2496          GLTexCoord2f((float)(sx)/ bitmap.width, (float)(sy+sh)/ bitmap.height);
2497          GLVertex2i(dx+surface.offset.x, dy+h+surface.offset.y);
2498       }
2499
2500       GLEnd();
2501
2502       GLSetupTexturing(false);
2503
2504       //glTranslate(0.375, 0.375, 0.0);
2505    }
2506
2507    void Filter(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2508    {
2509       Stretch(display, surface, bitmap, dx, dy, sx, sy, w, h, sw, sh);
2510    }
2511
2512    void StretchDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2513    {
2514       float s2dw,s2dh,d2sw,d2sh;
2515       //bool flipX = false, flipY = false;
2516
2517       if(Sgn(w) != Sgn(sw))
2518       {
2519          w = Abs(w);
2520          sw = Abs(sw);
2521          //flipX = true;
2522       }
2523       if(Sgn(h) != Sgn(sh))
2524       {
2525          h = Abs(h);
2526          sh = Abs(sh);
2527          //flipY = true;
2528       }
2529
2530       s2dw=(float)w / sw;
2531       s2dh=(float)h / sh;
2532       d2sw=(float)sw / w;
2533       d2sh=(float)sh / h;
2534
2535       //Clip against the edges of the source
2536       if(sx<0)
2537       {
2538          dx+=(int)((0-sx) * s2dw);
2539          w-=(int)((0-sx) * s2dw);
2540          sw-=0-sx;
2541          sx=0;
2542       }
2543       if(sy<0)
2544       {
2545          dy+=(int)((0-sy) * s2dh);
2546          h-=(int)((0-sy) * s2dh);
2547
2548          sh-=0-sy;
2549          sy=0;
2550       }
2551       if(sx+sw>bitmap.width-1)
2552       {
2553          w-=(int)((sx+sw-(bitmap.width-1)-1)*s2dw);
2554          sw-=sx+sw-(bitmap.width-1)-1;
2555       }
2556       if(sy+sh>(bitmap.height-1))
2557       {
2558          h-=(int)((sy+sh-(bitmap.height-1)-1)*s2dh);
2559          sh-=sy+sh-(bitmap.height-1)-1;
2560       }
2561       //Clip against the edges of the surfaceination
2562       if(dx<surface.box.left)
2563       {
2564          //if(!flip)
2565          sx+=(int)((surface.box.left-dx)*d2sw);
2566          sw-=(int)((surface.box.left-dx)*d2sw);
2567          w-=surface.box.left-dx;
2568          dx=surface.box.left;
2569       }
2570       if(dy<surface.box.top)
2571       {
2572          sy+=(int)((surface.box.top-dy)*d2sh);
2573          sh-=(int)((surface.box.top-dy)*d2sh);
2574          h-=surface.box.top-dy;
2575          dy=surface.box.top;
2576       }
2577       if(dx+w>surface.box.right)
2578       {
2579          //if(flip) sx+=(int)((dx+w-surface.box.right-1)*d2sw);
2580          sw-=(int)((dx+w-surface.box.right-1)*d2sw);
2581          w-=dx+w-surface.box.right-1;
2582       }
2583       if(dy+h>surface.box.bottom)
2584       {
2585          sh-=(int)((dy+h-surface.box.bottom-1)*d2sh);
2586          h-=dy+h-surface.box.bottom-1;
2587       }
2588       if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2589
2590       dx += surface.offset.x;
2591       dy += surface.offset.y;
2592
2593       if(bitmap.pixelFormat == pixelFormat888 && !bitmap.paletteShades)
2594       {
2595          glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
2596 #if ENABLE_GL_LEGACY
2597          if(glCaps_legacy)
2598          {
2599             glPixelStorei(GL_UNPACK_ROW_LENGTH, bitmap.stride);
2600             glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx);
2601             glPixelStorei(GL_UNPACK_SKIP_ROWS, sy);
2602             glRasterPos2d(dx,dy);
2603             //glPixelZoom(flipX ? -s2dw : s2dw, flipY ? s2dh : -s2dh);
2604             glPixelZoom(s2dw, -s2dh);
2605             glDrawPixels(sw,sh,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 BlitDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h)
2616    {
2617       //Clip against the edges of the source
2618       if(sx<0)
2619       {
2620          dx+=-sx;
2621          w-=-sx;
2622          sx=0;
2623       }
2624       if(sy<0)
2625       {
2626          dy+=0-sy;
2627          h-=0-sy;
2628          sy=0;
2629       }
2630       if(sx+w>bitmap.width-1)
2631          w-=sx+w-(bitmap.width-1)-1;
2632       if(sy+h>bitmap.height-1)
2633          h-=sy+h-(bitmap.height-1)-1;
2634       //Clip against the edges of the surfaceination
2635       if(dx<surface.box.left)
2636       {
2637          //if(!flip)
2638          sx+=surface.box.left-dx;
2639          w-=surface.box.left-dx;
2640          dx=surface.box.left;
2641       }
2642       if(dy<surface.box.top)
2643       {
2644          sy+=surface.box.top-dy;
2645          h-=surface.box.top-dy;
2646          dy=surface.box.top;
2647       }
2648       if(dx+w>surface.box.right)
2649       {
2650          //if(flip) sx+=dx+w-surface.box.right-1;
2651          w-=dx+w-surface.box.right-1;
2652       }
2653       if(dy+h>surface.box.bottom)
2654          h-=dy+h-surface.box.bottom-1;
2655       if((w<=0)||(h<=0))
2656          return;
2657
2658       dx += surface.offset.x;
2659       dy += surface.offset.y;
2660
2661       if(bitmap.pixelFormat == pixelFormat888 && !bitmap.paletteShades)
2662       {
2663          glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
2664 #if ENABLE_GL_LEGACY
2665          if(glCaps_legacy)
2666          {
2667             glPixelStorei(GL_UNPACK_ROW_LENGTH, bitmap.stride);
2668             glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx);
2669             glPixelStorei(GL_UNPACK_SKIP_ROWS, sy);
2670             glRasterPos2d(dx,dy);
2671             glPixelZoom(1,-1);
2672             glDrawPixels(w,h,GL_BGRA_EXT,GL_UNSIGNED_BYTE, bitmap.picture);
2673             glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
2674             glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
2675             glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
2676          }
2677 #endif
2678          glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2679       }
2680    }
2681
2682    void FilterDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2683    {
2684       StretchDI(display, surface, bitmap, dx, dy, sx, sy, w, h, sw, sh);
2685    }
2686
2687    void UnloadFont(DisplaySystem displaySystem, Font font)
2688    {
2689       ((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, font);
2690    }
2691
2692    Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
2693    {
2694       Font font;
2695       OGLSystem oglSystem = displaySystem.driverData;
2696       oglSystem.loadingFont = true;
2697       font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags, outlineSize, outlineFade);
2698       return font;
2699    }
2700
2701    void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * adv)
2702    {
2703       ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(displaySystem, font, text, len, width, height, prevGlyph, rPrevGlyph, adv);
2704    }
2705
2706    void WriteText(Display display, Surface surface, int x, int y, const char * text, int len, int prevGlyph, int * rPrevGlyph)
2707    {
2708       if(len && text[0])
2709       {
2710          OGLSurface oglSurface = surface.driverData;
2711          OGLSystem oglSystem = display.displaySystem.driverData;
2712          oglSystem.loadingFont = true;
2713
2714          //glTranslated(-0.375, -0.375, 0.0);
2715
2716          if(surface.textOpacity)
2717          {
2718             int w = 0, h, adv = 0;
2719             FontExtent(display.displaySystem, surface.font, text, len, &w, &h, 0, null, &adv);
2720             w += adv;
2721             display.displaySystem.driver.Area(display, surface,x,y,x+w-1,y+h-1);
2722          }
2723
2724          oglSurface.writingText = true;
2725
2726          GLSetupTexturing(true);
2727
2728          x <<= 6;
2729          if(surface.font.outlineSize)
2730          {
2731             ColorAlpha outlineColor = surface.outlineColor;
2732             int fx = x;
2733
2734             GLColor4ub(outlineColor.color.r, outlineColor.color.g, outlineColor.color.b, outlineColor.a);
2735             oglSurface.writingOutline = true;
2736             lastBlitTex = 0;
2737             oglSurface.font.ProcessString(surface.displaySystem, (const byte *)text, len, true, surface, display, &fx, y, prevGlyph, rPrevGlyph, null);
2738             if(lastBlitTex) GLEnd();
2739             oglSurface.writingOutline = false;
2740          }
2741          GLColor4fv(oglSurface.foreground);
2742
2743          lastBlitTex = 0;
2744          oglSurface.font.ProcessString(surface.displaySystem, (const byte *)text, len, true, surface, display, &x, y, prevGlyph, rPrevGlyph, null);
2745
2746          if(lastBlitTex) GLEnd();
2747          lastBlitTex = 0;
2748
2749          oglSurface.writingText = false;
2750          oglSystem.loadingFont = false;
2751
2752          GLSetupTexturing(false);
2753
2754          //glTranslated(0.375, 0.375, 0.0);
2755       }
2756    }
2757
2758    void TextFont(Display display, Surface surface, Font font)
2759    {
2760       ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextFont(display, surface, font);
2761    }
2762
2763    void TextOpacity(Display display, Surface surface, bool opaque)
2764    {
2765       OGLSurface oglSurface = surface.driverData;
2766       oglSurface.opaqueText = opaque;
2767    }
2768
2769    void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * adv)
2770    {
2771       OGLSurface oglSurface = surface.driverData;
2772       OGLSystem oglSystem = display.displaySystem.driverData;
2773       oglSystem.loadingFont = true;
2774       FontExtent(display.displaySystem, oglSurface.font, text, len, width, height, prevGlyph, rPrevGlyph, adv);
2775       oglSystem.loadingFont = false;
2776    }
2777
2778    void DrawingChar(Display display, Surface surface, char character)
2779    {
2780
2781    }
2782
2783    void LineStipple(Display display, Surface surface, uint32 stipple)
2784    {
2785       if(stipple)
2786       {
2787 #if ENABLE_GL_LEGACY
2788          if(glCaps_legacy)
2789          {
2790             glLineStipple(1, (uint16)stipple);
2791             glEnable(GL_LINE_STIPPLE);
2792          }
2793          else
2794 #endif
2795          {
2796             stippleEnabled = true;
2797             glsupLineStipple(1, (uint16)stipple);
2798          }
2799       }
2800       else
2801       {
2802 #if ENABLE_GL_LEGACY
2803          if(glCaps_legacy)
2804             glDisable(GL_LINE_STIPPLE);
2805          else
2806 #endif
2807          {
2808             stippleEnabled = false;
2809             GLMatrixMode(GL_TEXTURE);
2810             GLLoadIdentity();
2811             GLMatrixMode(MatrixMode::projection);
2812             GLSetupTexturing(false);   // TODO: Special shading code for stipple?
2813          }
2814       }
2815    }
2816
2817 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
2818    void SetRenderState(Display display, RenderState state, uint value)
2819    {
2820       OGLDisplay oglDisplay = display.driverData;
2821       switch(state)
2822       {
2823          case antiAlias:
2824 #ifndef __EMSCRIPTEN__
2825             if(value)
2826                glEnable(GL_MULTISAMPLE);
2827             else
2828                glDisable(GL_MULTISAMPLE);
2829 #endif
2830             break;
2831          case fillMode:
2832 #if ENABLE_GL_LEGACY
2833             if(glCaps_legacy)
2834                glPolygonMode(GL_FRONT_AND_BACK, ((FillModeValue)value == solid) ? GL_FILL : GL_LINE);
2835 #endif
2836             break;
2837          case depthTest:
2838             if(value) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
2839             break;
2840          case depthWrite:
2841             if(value) glDepthMask((byte)bool::true); else glDepthMask((byte)bool::false);
2842             oglDisplay.depthWrite = (bool)value;
2843             break;
2844          case fogColor:
2845          {
2846             float color[4] = { ((Color)value).r/255.0f, ((Color)value).g/255.0f, ((Color)value).b/255.0f, 1.0f };
2847 #if ENABLE_GL_SHADERS
2848             if(glCaps_shaders)
2849                defaultShader.setFogColor(color[0], color[1], color[2]);
2850 #endif
2851
2852 #if ENABLE_GL_FFP
2853             if(!glCaps_shaders)
2854                glFogfv(GL_FOG_COLOR, (float *)&color);
2855 #endif
2856             break;
2857          }
2858          case fogDensity:
2859 #if ENABLE_GL_SHADERS
2860             if(glCaps_shaders)
2861                defaultShader.setFogDensity((float)(RenderStateFloat { ui = value }.f * nearPlane));
2862 #endif
2863
2864 #if ENABLE_GL_FFP
2865             if(!glCaps_shaders)
2866                glFogf(GL_FOG_DENSITY, (float)(RenderStateFloat { ui = value }.f * nearPlane));
2867 #endif
2868             break;
2869          case blend:
2870 //#if !defined(__EMSCRIPTEN__)
2871             if(value) glEnable(GL_BLEND); else glDisable(GL_BLEND);
2872 //#endif
2873             break;
2874          case ambient:
2875          {
2876 #if ENABLE_GL_SHADERS
2877             if(glCaps_shaders)
2878                defaultShader.setGlobalAmbient(((Color)value).r / 255.0f, ((Color)value).g / 255.0f, ((Color)value).b / 255.0f, 1.0f);
2879 #endif
2880
2881 #if ENABLE_GL_FFP
2882             if(!glCaps_shaders)
2883             {
2884                float ambient[4] = { ((Color)value).r/255.0f, ((Color)value).g/255.0f, ((Color)value).b/255.0f, 1.0f };
2885                glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
2886             }
2887 #endif
2888             break;
2889          }
2890          case alphaWrite:
2891          {
2892             if(value) glColorMask(1,1,1,1); else glColorMask(1,1,1,0);
2893             break;
2894          }
2895          case vSync:
2896          {
2897 #if defined(__WIN32__)
2898             if(wglSwapIntervalEXT)
2899                wglSwapIntervalEXT(value ? 1 : 0);
2900 #endif
2901             break;
2902          }
2903       }
2904    }
2905
2906    void SetLight(Display display, int id, Light light)
2907    {
2908 #if ENABLE_GL_SHADERS
2909       if(glCaps_shaders)
2910          defaultShader.setLight(display, id, light);
2911 #endif
2912
2913 #if ENABLE_GL_FFP
2914       if(!glCaps_shaders)
2915       {
2916          if(light != null && !light.flags.off)
2917          {
2918             Object lightObject = light.lightObject;
2919             float position[4] = { 0, 0, 0, 0 };
2920             float color[4] = { 0, 0, 0, 1 };
2921             Vector3D l;
2922
2923             glEnable(GL_LIGHT0 + id);
2924
2925             if(!light.multiplier) light.multiplier = 1.0f;
2926
2927             GLFlushMatrices();
2928
2929             color[0] = light.diffuse.r * light.multiplier;
2930             color[1] = light.diffuse.g * light.multiplier;
2931             color[2] = light.diffuse.b * light.multiplier;
2932             glLightfv(GL_LIGHT0 + id, GL_DIFFUSE, color);
2933
2934             color[0] = light.ambient.r * light.multiplier;
2935             color[1] = light.ambient.g * light.multiplier;
2936             color[2] = light.ambient.b * light.multiplier;
2937             glLightfv(GL_LIGHT0 + id, GL_AMBIENT, color);
2938
2939             color[0] = light.specular.r * light.multiplier;
2940             color[1] = light.specular.g * light.multiplier;
2941             color[2] = light.specular.b * light.multiplier;
2942             glLightfv(GL_LIGHT0 + id, GL_SPECULAR,color);
2943
2944             if(lightObject)
2945             {
2946                // Positional Lights, including Spot Lights (and omni light with flags.spot not set)
2947                Matrix * mat = &lightObject.matrix;
2948                l = { mat->m[3][0], mat->m[3][1], mat->m[3][2] };
2949                if(display.display3D && display.display3D.camera)
2950                   l.Subtract(l, display.display3D.camera.cPosition);
2951
2952                position[0] = (float)l.x, position[1] = (float)l.y, position[2] = (float)l.z, position[3] = 1;
2953
2954                if(light.flags.attenuation)
2955                {
2956                   glLightf(GL_LIGHT0 + id, GL_CONSTANT_ATTENUATION, light.Kc);
2957                   glLightf(GL_LIGHT0 + id, GL_LINEAR_ATTENUATION, light.Kl);
2958                   glLightf(GL_LIGHT0 + id, GL_QUADRATIC_ATTENUATION, light.Kq);
2959                }
2960                else
2961                {
2962                   glLightf(GL_LIGHT0 + id, GL_CONSTANT_ATTENUATION, 1);
2963                   glLightf(GL_LIGHT0 + id, GL_LINEAR_ATTENUATION, 0);
2964                   glLightf(GL_LIGHT0 + id, GL_QUADRATIC_ATTENUATION, 0);
2965                }
2966
2967                if((light.flags.spot && light.fallOff < 360) || (lightObject && (light.direction.x || light.direction.y || light.direction.z)))
2968                {
2969                   // Figure out exponent out of the hot spot
2970                   #define MAXLIGHT  0.9
2971                   float exponent = light.flags.spot ? (float)(log(MAXLIGHT) / log(cos(light.hotSpot / 2))) : 1;
2972                   Degrees cutOff = light.flags.spot ? light.fallOff/2 : 90;
2973                   float direction[4] = { (float)light.direction.x, (float)light.direction.y, (float)light.direction.z, 1 };
2974
2975                   glLightfv(GL_LIGHT0 + id, GL_SPOT_DIRECTION, direction);
2976                   glLightf(GL_LIGHT0 + id, GL_SPOT_CUTOFF, (float)cutOff);
2977                   glLightf(GL_LIGHT0 + id, GL_SPOT_EXPONENT, exponent);
2978                }
2979                else
2980                {
2981                   float d[4] = { 0, 0, 1, 0 };
2982                   glLightfv(GL_LIGHT0 + id, GL_SPOT_DIRECTION, d);
2983                   glLightf(GL_LIGHT0 + id, GL_SPOT_CUTOFF, 180);
2984                   glLightf(GL_LIGHT0 + id, GL_SPOT_EXPONENT, 1);
2985                }
2986
2987                /*
2988                if(lightObject)
2989                {
2990                   // Display Light Position
2991                   glDisable(GL_LIGHTING);
2992                   glDisable(GL_DEPTH_TEST);
2993                   glColor3f(1,1,1);
2994                   glPointSize(10);
2995                   glBegin(GL_POINTS);
2996                   glVertex3fv(position);
2997                   glEnd();
2998                   glEnable(GL_DEPTH_TEST);
2999                   glEnable(GL_LIGHTING);
3000
3001
3002                   // Display Target
3003                   if(lightObject.flags.root || !lightObject.parent)
3004                   {
3005                      positionVector = light.target.transform.position;
3006                      positionVector.Subtract(positionVector, display.camera.cPosition);
3007                   }
3008                   else
3009                   {
3010                      positionVector.MultMatrix(light.target.transform.position,
3011                         lightObject.light.target.parent.matrix);
3012                      positionVector.Subtract(positionVector, display.camera.cPosition);
3013                   }
3014
3015                   position[0] = positionVector.x;
3016                   position[1] = positionVector.y;
3017                   position[2] = positionVector.z;
3018
3019                   glDisable(GL_LIGHTING);
3020                   glDisable(GL_DEPTH_TEST);
3021                   glColor3f(1,1,0);
3022                   glPointSize(10);
3023                   glBegin(GL_POINTS);
3024                   glVertex3fv(position);
3025                   glEnd();
3026                   glEnable(GL_DEPTH_TEST);
3027                   glEnable(GL_LIGHTING);
3028                }
3029                */
3030             }
3031             else
3032             {
3033                // Directional Light
3034                Vector3D vector { 0,0,-1 };
3035                Vector3D direction;
3036                Matrix mat;
3037                mat.RotationQuaternion(light.orientation);
3038                direction.MultMatrix(vector, mat);
3039                l.Normalize(direction);
3040                position[0] = (float)l.x, position[1] = (float)l.y, position[2] = (float)l.z, position[3] = 0;
3041             }
3042             glLightfv(GL_LIGHT0 + id, GL_POSITION, position);
3043             if(display.display3D)
3044             {
3045                Matrix m;
3046                Vector3Df v { position[0], position[1], position[2] };
3047                Vector3Df l;
3048                float * lp = display.display3D.light0Pos;
3049                if(display.display3D.camera)
3050                   m = display.display3D.camera.viewMatrix;
3051                else
3052                   m.Identity();
3053                l.MultMatrix(v, m);
3054                lp[0] = l.x;
3055                lp[1] =-l.y;
3056                lp[2] =-l.z;
3057                lp[3] = position[3];
3058             }
3059          }
3060          else
3061             glDisable(GL_LIGHT0 + id);
3062       }
3063 #endif
3064    }
3065
3066    void SetCamera(Display display, Surface surface, Camera camera)
3067    {
3068       OGLDisplay oglDisplay = display.driverData;
3069
3070       if(surface && camera)
3071       {
3072          int left = surface.box.left + surface.offset.x;
3073          int top = surface.box.top  + surface.offset.y;
3074          int right = surface.box.right + surface.offset.x;
3075          int bottom = surface.box.bottom + surface.offset.y;
3076          float origX = surface.offset.x + camera.origin.x;
3077          float origY = surface.offset.y + camera.origin.y;
3078          int x = left;
3079          int y = display.height - bottom - 1;
3080          int w = right - left + 1;
3081          int h = bottom - top + 1;
3082
3083          // *** ViewPort ***
3084          glViewport(x, y, w, h);
3085
3086          GLMatrixMode(MatrixMode::texture);
3087          if(!display.display3D.camera)
3088             GLPushMatrix();
3089          GLLoadIdentity();
3090
3091          // *** Projection Matrix ***
3092          GLMatrixMode(MatrixMode::projection);
3093          if(!display.display3D.camera)
3094             GLPushMatrix();
3095
3096          if(display.display3D.collectingHits)
3097          {
3098             float pickX = display.display3D.pickX + surface.offset.x;
3099             float pickY = display.height - (display.display3D.pickY + surface.offset.y) - 1;
3100             Matrix pickMatrix
3101             {
3102                {
3103                   w / display.display3D.pickWidth, 0, 0, 0,
3104                   0, h / display.display3D.pickHeight, 0, 0,
3105                   0, 0, 1, 0,
3106                   (w + 2.0f * (x - pickX)) / display.display3D.pickWidth,
3107                   (h + 2.0f * (y - pickY)) / display.display3D.pickHeight, 0, 1
3108                }
3109             };
3110             GLLoadMatrixd(pickMatrix.array);
3111          }
3112          else
3113             GLLoadIdentity();
3114          GLFrustum(
3115             (left   - origX) * camera.zMin / camera.focalX,
3116             (right  - origX) * camera.zMin / camera.focalX,
3117             (bottom - origY) * camera.zMin / camera.focalY,
3118             (top    - origY) * camera.zMin / camera.focalY,
3119             camera.zMin, camera.zMax);
3120
3121          glDisable(GL_BLEND);
3122
3123          // *** Z Inverted Identity Matrix ***
3124          GLMatrixMode(MatrixMode::modelView);
3125          if(!display.display3D.camera)
3126             GLPushMatrix();
3127
3128          GLLoadIdentity();
3129
3130          GLScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane);
3131
3132          // *** View Matrix ***
3133          GLMultMatrixd(camera.viewMatrix.array);
3134
3135 #if ENABLE_GL_SHADERS
3136          if(glCaps_shaders)
3137          {
3138             defaultShader.select();
3139             defaultShader.setCamera(camera);
3140          }
3141 #endif
3142
3143          // *** Lights ***
3144          // ...
3145
3146          glEnable(GL_DEPTH_TEST);
3147
3148          GLSetupLighting(true);
3149 #if ENABLE_GL_FFP
3150          if(!glCaps_shaders)
3151             glShadeModel(GL_SMOOTH);
3152 #endif
3153          glDepthMask((byte)bool::true);
3154          oglDisplay.depthWrite = true;
3155
3156 #ifndef __EMSCRIPTEN__
3157          glEnable(GL_MULTISAMPLE);
3158 #endif
3159       }
3160       else if(surface && display.display3D.camera)
3161       {
3162          nearPlane = 1;
3163          oglDisplay.depthWrite = false;
3164          glViewport(0,0,display.width,display.height);
3165
3166          glDisable(GL_CULL_FACE);
3167          glDisable(GL_DEPTH_TEST);
3168
3169          GLDisableClientState(COLORS);
3170 #if ENABLE_GL_SHADERS
3171          if(glCaps_shaders)
3172          {
3173             GLDisableClientState(TANGENTS1);
3174             GLDisableClientState(TANGENTS2);
3175          }
3176 #endif
3177          GLDisableClientState(NORMALS);
3178 #if ENABLE_GL_FFP
3179          if(!glCaps_shaders)
3180             GLDisableClientState(LIGHTVECTORS);
3181 #endif
3182
3183          // *** Restore 2D MODELVIEW Matrix ***
3184          GLPopMatrix();
3185
3186          // *** Restore 2D PROJECTION Matrix ***
3187          GLMatrixMode(MatrixMode::projection);
3188          GLPopMatrix();
3189
3190          // *** Restore 2D TEXTURE Matrix ***
3191          GLMatrixMode(MatrixMode::texture);
3192          GLPopMatrix();
3193
3194 #if ENABLE_GL_SHADERS
3195          if(glCaps_shaders)
3196             defaultShader.select();
3197 #endif
3198
3199 #if ENABLE_GL_FFP
3200          if(!glCaps_shaders)
3201          {
3202             disableRemainingTMUs(1);
3203             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
3204             glDisable(GL_TEXTURE_CUBE_MAP);
3205          #if _GLES
3206             glDisable(GL_TEXTURE_GEN_STR);
3207          #else
3208             glDisable(GL_TEXTURE_GEN_R);
3209             glDisable(GL_TEXTURE_GEN_S);
3210             glDisable(GL_TEXTURE_GEN_T);
3211          #endif
3212          }
3213 #endif
3214
3215          GLSetupTexturing(false);
3216          GLSetupLighting(false);
3217          GLSetupFog(false);
3218
3219 #if ENABLE_GL_SHADERS
3220          if(glCaps_shaders)
3221          {
3222             defaultShader.setPerVertexColor(false);
3223             defaultShader.setMaterial(null, 0);
3224          }
3225 #endif
3226
3227 #if ENABLE_GL_FFP
3228          if(!glCaps_shaders)
3229             glShadeModel(GL_FLAT);
3230 #endif
3231          glEnable(GL_BLEND);
3232 #if !defined(__EMSCRIPTEN__)
3233          glDisable(GL_MULTISAMPLE);
3234 #endif
3235       }
3236    }
3237
3238    void ApplyMaterial(Display display, Material material, Mesh mesh)
3239    {
3240       Shader shader = material.shader ? material.shader : defaultShader;
3241       MaterialFlags flags = material.flags;
3242 #if ENABLE_GL_FFP
3243       static int lastSeparate = 0;
3244       int tmu = 0;
3245       bool normalMapped = false;
3246       OGLMesh oglMesh = mesh ? mesh.data : null;
3247 #endif
3248
3249 #if ENABLE_GL_SHADERS
3250       if(glCaps_shaders && shader)
3251          shader.select();
3252 #endif
3253
3254       // Basic Properties
3255       if(flags.doubleSided)
3256       {
3257 #if ENABLE_GL_FFP
3258          if(!glCaps_shaders)
3259             GLLightModeli(GL_LIGHT_MODEL_TWO_SIDE, !flags.singleSideLight);
3260 #endif
3261          glDisable(GL_CULL_FACE);
3262       }
3263       else
3264       {
3265 #if ENABLE_GL_FFP
3266          if(!glCaps_shaders)
3267             GLLightModeli(GL_LIGHT_MODEL_TWO_SIDE, bool::false);
3268 #endif
3269          glEnable(GL_CULL_FACE);
3270       }
3271
3272       // Fog
3273       GLSetupFog(!flags.noFog);
3274
3275 #if ENABLE_GL_SHADERS
3276       if(glCaps_shaders)
3277          activeShader.setMaterial(material, mesh.flags);
3278 #endif
3279
3280 #if ENABLE_GL_FFP
3281       if(!glCaps_shaders)
3282       {
3283          if(material.bumpMap && mesh.lightVectors)
3284          {
3285             float color[4] = { 1,1,1,1 };
3286             glActiveTexture(GL_TEXTURE0 + tmu);
3287             glClientActiveTexture(GL_TEXTURE0 + tmu++);
3288             glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)material.bumpMap.driverData);
3289             glDisable(GL_TEXTURE_CUBE_MAP);
3290             glEnable(GL_TEXTURE_2D);
3291
3292             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
3293             glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB);
3294             glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
3295             glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PRIMARY_COLOR);
3296             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
3297             glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
3298             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
3299
3300             if(0) //((DefaultShaderBits)defaultShader.state).debugging)
3301             {
3302                glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
3303                glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PRIMARY_COLOR);
3304                glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT);
3305                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
3306                glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color );
3307             }
3308
3309          #if _GLES
3310             glDisable(GL_TEXTURE_GEN_STR);
3311          #else
3312             glDisable(GL_TEXTURE_GEN_R);
3313             glDisable(GL_TEXTURE_GEN_S);
3314             glDisable(GL_TEXTURE_GEN_T);
3315          #endif
3316             glDisable(GL_LIGHTING);
3317             lightingEnabled = false;
3318
3319             GLMatrixMode(GL_TEXTURE);
3320             GLLoadIdentity();
3321             if(material.uScale && material.vScale)
3322                GLScalef(material.uScale, material.vScale, 1);
3323             GLMatrixMode(MatrixMode::modelView);
3324
3325             if(flags.tile)
3326             {
3327                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
3328                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
3329             }
3330             else
3331             {
3332                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3333                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3334             }
3335
3336             glActiveTexture(GL_TEXTURE0 + tmu);
3337             glClientActiveTexture(GL_TEXTURE0 + tmu);
3338
3339             normalMapped = true;
3340
3341             // Modulate base color
3342             if(material.diffuse.r < 1 || material.diffuse.g < 1 || material.diffuse.b < 1)
3343             {
3344                tmu++;
3345                glDisable(GL_TEXTURE_CUBE_MAP);
3346                glEnable(GL_TEXTURE_2D);
3347                glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)material.bumpMap.driverData);
3348                glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
3349                glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
3350                glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
3351
3352                glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
3353                glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
3354                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
3355                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
3356
3357                glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
3358                glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_CONSTANT);
3359                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
3360                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
3361
3362                color[0] = material.diffuse.r, color[1] = material.diffuse.g, color[2] = material.diffuse.b, color[3] = 1.0;
3363                glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color );
3364                glActiveTexture(GL_TEXTURE0 + tmu);
3365                glClientActiveTexture(GL_TEXTURE0 + tmu);
3366             }
3367
3368             // Add ambient light
3369             {
3370                ColorRGB ambient { material.ambient.r * 0.2f, material.ambient.g * 0.2f, material.ambient.g * 0.2f };
3371                if(ambient.r > 0 || ambient.g > 0 || ambient.b > 0)
3372                {
3373                   tmu++;
3374                   glDisable(GL_TEXTURE_CUBE_MAP);
3375                   glEnable(GL_TEXTURE_2D);
3376                   glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)material.bumpMap.driverData);
3377                   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
3378                   glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
3379                   glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
3380
3381                   glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
3382                   glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT);
3383                   glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
3384                   glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
3385
3386                   glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
3387                   glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_CONSTANT);
3388                   glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
3389                   glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
3390
3391                   color[0] = ambient.r, color[1] = ambient.g, color[2] = ambient.b, color[3] = 1.0;
3392                   glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color );
3393                   glActiveTexture(GL_TEXTURE0 + tmu);
3394                   glClientActiveTexture(GL_TEXTURE0 + tmu);
3395                }
3396             }
3397          }
3398          else
3399          {
3400             GLDisableClientState(LIGHTVECTORS);
3401             if(!lightingEnabled)
3402             {
3403                glEnable(GL_LIGHTING);
3404                lightingEnabled = true;
3405             }
3406          }
3407       }
3408 #endif
3409       // Maps
3410       if(flags.cubeMap || (material.baseMap && (mesh.texCoords || mesh.flags.texCoords1)))
3411       {
3412          Bitmap map = material.baseMap;
3413          int diffuseTarget = flags.cubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
3414
3415 #if ENABLE_GL_FFP
3416          if(!glCaps_shaders)
3417          {
3418             glActiveTexture(GL_TEXTURE0 + tmu);
3419             glClientActiveTexture(GL_TEXTURE0 + tmu++);
3420             glEnable(diffuseTarget);
3421             glDisable(flags.cubeMap ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP);
3422          }
3423 #endif
3424
3425 #if ENABLE_GL_SHADERS
3426          if(glCaps_shaders && !flags.cubeMap)
3427             GLSetupTexturing(true);
3428 #endif
3429
3430          glBindTexture(diffuseTarget, (GLuint)(uintptr)map.driverData);
3431
3432 #if ENABLE_GL_FFP
3433          if(!glCaps_shaders)
3434          {
3435             if(tmu > 1)
3436             {
3437                oglMesh.texCoords.use(texCoord, 2, GL_FLOAT, 0, oglMesh.texCoords.buffer ? null : mesh.texCoords);
3438                GLEnableClientState(TEXCOORDS);
3439             }
3440             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
3441             /* // This did not have the desired effect with a GL_ALPHA texture
3442             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
3443             glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
3444             glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
3445             glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
3446             glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
3447             glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
3448             glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
3449             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
3450             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
3451             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
3452             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
3453             */
3454
3455             if(flags.cubeMap)
3456             {
3457             #if _GLES
3458                glEnable(GL_TEXTURE_GEN_STR);
3459                // GL_OBJECT_LINEAR: No extension support?
3460                // glTexGeni(GL_TEXTURE_GEN_STR_OES, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
3461             #else
3462                GLfloat xPlane[] = { 1.0f, 0.0f, 0.0f, 0 };
3463                GLfloat yPlane[] = { 0.0f,-1.0f, 0.0f, 0 };
3464                GLfloat zPlane[] = { 0.0f, 0.0f,-1.0f, 0 };
3465                glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
3466                glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
3467                glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
3468                glTexGenfv(GL_R, GL_OBJECT_PLANE, zPlane);
3469                glTexGenfv(GL_S, GL_OBJECT_PLANE, xPlane);
3470                glTexGenfv(GL_T, GL_OBJECT_PLANE, yPlane);
3471
3472                glEnable(GL_TEXTURE_GEN_R);
3473                glEnable(GL_TEXTURE_GEN_S);
3474                glEnable(GL_TEXTURE_GEN_T);
3475             #endif
3476             }
3477             else
3478             {
3479             #if _GLES
3480                glDisable(GL_TEXTURE_GEN_STR);
3481             #else
3482                glDisable(GL_TEXTURE_GEN_R);
3483                glDisable(GL_TEXTURE_GEN_S);
3484                glDisable(GL_TEXTURE_GEN_T);
3485             #endif
3486             }
3487             glClientActiveTexture(GL_TEXTURE0);
3488          }
3489 #endif
3490          if(flags.tile)
3491          {
3492             glTexParameteri(diffuseTarget, GL_TEXTURE_WRAP_S, GL_REPEAT);
3493             glTexParameteri(diffuseTarget, GL_TEXTURE_WRAP_T, GL_REPEAT);
3494          }
3495          else
3496          {
3497             glTexParameteri(diffuseTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3498             glTexParameteri(diffuseTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3499          }
3500       }
3501       else
3502       {
3503          GLSetupTexturing(false);
3504       }
3505
3506 #if ENABLE_GL_FFP && !defined(_GLES)
3507       if(!glCaps_shaders)
3508       {
3509          int separate = material.flags.separateSpecular ? GL_SEPARATE_SPECULAR_COLOR : GL_SINGLE_COLOR;
3510          if(separate != lastSeparate)
3511          {
3512             GLLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, separate);
3513             lastSeparate = separate;
3514          }
3515       }
3516 #endif
3517
3518       if((flags.cubeMap && material.baseMap) ||
3519          (mesh.texCoords && (material.baseMap || material.bumpMap || material.specularMap || material.reflectMap)))
3520       {
3521 #if ENABLE_GL_FFP
3522          if(!glCaps_shaders)
3523          {
3524             glActiveTexture(GL_TEXTURE0 + tmu - 1);
3525             glClientActiveTexture(GL_TEXTURE0 + tmu - 1);
3526          }
3527 #endif
3528          GLMatrixMode(GL_TEXTURE);
3529          GLLoadIdentity();
3530          if(material.uScale && material.vScale)
3531             GLScalef(material.uScale, material.vScale, 1);
3532          GLMatrixMode(MatrixMode::modelView);
3533 #if ENABLE_GL_FFP
3534          if(!glCaps_shaders)
3535          {
3536             glActiveTexture(GL_TEXTURE0);
3537             glClientActiveTexture(GL_TEXTURE0);
3538          }
3539 #endif
3540       }
3541
3542 #if ENABLE_GL_FFP
3543       if(!glCaps_shaders)
3544       {
3545          if(material.envMap && material.refractiveIndex)
3546          {
3547             float color[4] = { material.opacity, material.opacity, material.opacity, 1.0 };
3548             glActiveTexture(GL_TEXTURE0 + tmu);
3549             glClientActiveTexture(GL_TEXTURE0 + tmu++);
3550             glBindTexture(GL_TEXTURE_CUBE_MAP, (GLuint)(uintptr)material.envMap.driverData);
3551             glEnable(GL_TEXTURE_CUBE_MAP);
3552          #if _GLES
3553             glEnable(GL_TEXTURE_GEN_STR);
3554             glTexGeni(GL_TEXTURE_GEN_STR_OES, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
3555          #else
3556             glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
3557             glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
3558             glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
3559             glEnable(GL_TEXTURE_GEN_R);
3560             glEnable(GL_TEXTURE_GEN_S);
3561             glEnable(GL_TEXTURE_GEN_T);
3562          #endif
3563
3564             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
3565
3566             if(normalMapped)
3567                glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
3568             else
3569                glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
3570             glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
3571
3572             glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
3573             glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
3574
3575             glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
3576             glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
3577
3578             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
3579             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
3580
3581             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
3582             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
3583
3584             if(!normalMapped)
3585             {
3586                glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT);
3587                glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_ALPHA, GL_CONSTANT);
3588                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
3589                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);
3590             }
3591
3592             glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color );
3593
3594             GLMatrixMode(MatrixMode::texture);
3595             {
3596                double * s = display.display3D.camera.inverseTranspose.array;
3597                Quaternion q = display.display3D.camera.cOrientation;
3598                Matrix mat;
3599                Euler e = q;
3600                //e.yaw *= -1;
3601                q = e;
3602                mat.RotationQuaternion(q);
3603                mat.Scale(2,-2,-2);
3604                s = mat.array;
3605
3606                Matrix m
3607                { {
3608                   s[0],s[1],s[2],0,
3609                   s[4],s[5],s[6],0,
3610                   s[8],s[9],s[10],0,
3611                   0,0,0,1
3612                } };
3613                GLLoadMatrixd(m.array);
3614             }
3615             GLMatrixMode(MatrixMode::modelView);
3616          }
3617
3618          if(material.envMap && material.reflectivity)
3619          {
3620             float color[4] = { 1.0f - material.reflectivity, 1.0f - material.reflectivity, 1.0f - material.reflectivity, 1.0 };
3621             glActiveTexture(GL_TEXTURE0 + tmu);
3622             glClientActiveTexture(GL_TEXTURE0 + tmu++);
3623             glBindTexture(GL_TEXTURE_CUBE_MAP, (GLuint)(uintptr)material.envMap.driverData);
3624             glEnable(GL_TEXTURE_CUBE_MAP);
3625          #if _GLES
3626             glEnable(GL_TEXTURE_GEN_STR);
3627             glTexGeni(GL_TEXTURE_GEN_STR_OES, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
3628          #else
3629             glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
3630             glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
3631             glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
3632             glEnable(GL_TEXTURE_GEN_R);
3633             glEnable(GL_TEXTURE_GEN_S);
3634             glEnable(GL_TEXTURE_GEN_T);
3635          #endif
3636
3637             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
3638
3639             if(normalMapped)
3640                glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
3641             else
3642                glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
3643             glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
3644
3645             glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
3646             glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
3647
3648             glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
3649             glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
3650             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
3651             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
3652             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
3653             glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
3654
3655             if(!normalMapped)
3656             {
3657                glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT);
3658                glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_ALPHA, GL_CONSTANT);
3659                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
3660                glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA);
3661             }
3662
3663             glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color );
3664
3665             GLMatrixMode(MatrixMode::texture);
3666             {
3667                double * s = display.display3D.camera.inverseTranspose.array;
3668                Matrix m
3669                { {
3670                   s[0],s[1],-s[2],0,
3671                   s[4],-s[5],-s[6],0,
3672                   -s[8],s[9],s[10],0,
3673                   0,0,0,1
3674                } };
3675                GLLoadMatrixd(m.array);
3676             }
3677             GLMatrixMode(MatrixMode::modelView);
3678          }
3679       }
3680 #endif
3681
3682 #if ENABLE_GL_FFP
3683       if(!glCaps_shaders)
3684       {
3685          disableRemainingTMUs(tmu);
3686
3687          if(mesh.flags.colors)
3688          {
3689             GLColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
3690             glEnable(GL_COLOR_MATERIAL);
3691          }
3692          else
3693          {
3694             glDisable(GL_COLOR_MATERIAL);
3695             {
3696                float color[4] = { material.diffuse.r, material.diffuse.g, material.diffuse.b, material.opacity };
3697                glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
3698             }
3699             {
3700                float color[4] = { material.ambient.r, material.ambient.g, material.ambient.b, 0 };
3701                glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
3702             }
3703          }
3704          if(material.power > 0.1)
3705          {
3706             float color[4] = { material.specular.r, material.specular.g, material.specular.b, 0 };
3707             glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
3708          }
3709          else
3710          {
3711             float color[4] = { 0,0,0,0 };
3712             glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
3713          }
3714          {
3715             float color[4] = { material.emissive.r, material.emissive.g, material.emissive.b, 0 };
3716             glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color);
3717          }
3718          glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &material.power);
3719       }
3720 #endif
3721    }
3722
3723    void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
3724    {
3725       OGLMesh oglMesh = mesh.data;
3726       if(oglMesh)
3727       {
3728          OGLSystem oglSystem = displaySystem.driverData;
3729          SETCAPS(oglSystem.capabilities);
3730          if(!mesh.flags.vertices)
3731          {
3732             oglMesh.vertices.free(glCaps_vertexBuffer);
3733             delete mesh.vertices;
3734          }
3735          if(!mesh.flags.normals)
3736          {
3737             oglMesh.normals.free(glCaps_vertexBuffer);
3738             delete mesh.normals;
3739          }
3740          if(!mesh.flags.tangents)
3741          {
3742             oglMesh.tangents.free(glCaps_vertexBuffer);
3743             delete mesh.tangents;
3744          }
3745          if(!mesh.flags.lightVectors)
3746          {
3747             oglMesh.lightVectors.free(glCaps_vertexBuffer);
3748             delete mesh.lightVectors;
3749          }
3750          if(!mesh.flags.texCoords1)
3751          {
3752             oglMesh.texCoords.free(glCaps_vertexBuffer);
3753             delete mesh.texCoords;
3754          }
3755          if(!mesh.flags.texCoords2)
3756          {
3757             oglMesh.texCoords2.free(glCaps_vertexBuffer);
3758             // delete mesh.texCoords2;
3759          }
3760          if(!mesh.flags.colors)
3761          {
3762             oglMesh.colors.free(glCaps_vertexBuffer);
3763             delete mesh.colors;
3764          }
3765          if(!mesh.flags)
3766          {
3767             delete oglMesh;
3768             mesh.data = null;
3769          }
3770       }
3771    }
3772
3773    bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags, int nVertices)
3774    {
3775       bool result = false;
3776
3777       if(!mesh.data)
3778          mesh.data = OGLMesh { };
3779       if(mesh.data)
3780       {
3781          if(mesh.nVertices == nVertices)
3782          {
3783             // Same number of vertices, adding features (Leaves the other features pointers alone)
3784             if(mesh.flags != flags)
3785             {
3786                if(!mesh.flags.vertices && flags.vertices)
3787                {
3788                   if(flags.doubleVertices)
3789                   {
3790                      mesh.vertices = (Vector3Df *)new Vector3D[nVertices];
3791                   }
3792                   else
3793                      mesh.vertices = new Vector3Df[nVertices];
3794                }
3795                if(!mesh.flags.normals && flags.normals)
3796                {
3797                   if(flags.doubleNormals)
3798                   {
3799                      mesh.normals = (Vector3Df *)new Vector3D[nVertices];
3800                   }
3801                   else
3802                      mesh.normals = new Vector3Df[nVertices];
3803                }
3804                if(!mesh.flags.tangents && flags.tangents)
3805                {
3806                   mesh.tangents = new Vector3Df[2*nVertices];
3807                }
3808                if(!mesh.flags.lightVectors && flags.lightVectors)
3809                {
3810                   mesh.lightVectors = new ColorRGB[nVertices];
3811                }
3812                if(!mesh.flags.texCoords1 && flags.texCoords1)
3813                {
3814                   mesh.texCoords = new Pointf[nVertices];
3815                }
3816                if(!mesh.flags.colors && flags.colors)
3817                {
3818                   mesh.colors = new ColorRGBAf[nVertices];
3819                }
3820             }
3821          }
3822          else
3823          {
3824             // New number of vertices, reallocate all current and new features
3825             flags |= mesh.flags;
3826             if(flags.vertices)
3827             {
3828                if(flags.doubleVertices)
3829                {
3830                   mesh.vertices = (Vector3Df *)renew mesh.vertices Vector3D[nVertices];
3831                }
3832                else
3833                   mesh.vertices = renew mesh.vertices Vector3Df[nVertices];
3834             }
3835             if(flags.normals)
3836             {
3837                if(flags.doubleNormals)
3838                {
3839                   mesh.normals = (Vector3Df *)renew mesh.normals Vector3D[nVertices];
3840                }
3841                else
3842                   mesh.normals = renew mesh.normals Vector3Df[nVertices];
3843             }
3844             if(flags.texCoords1)
3845             {
3846                mesh.texCoords = renew mesh.texCoords Pointf[nVertices];
3847             }
3848             if(flags.colors)
3849             {
3850                mesh.colors = renew mesh.colors ColorRGBAf[nVertices];
3851             }
3852             if(flags.tangents)
3853             {
3854                mesh.tangents = renew mesh.tangents Vector3Df[2 * nVertices];
3855             }
3856             if(flags.lightVectors)
3857             {
3858                mesh.lightVectors = renew mesh.lightVectors ColorRGB[nVertices];
3859             }
3860          }
3861          result = true;
3862       }
3863       return result;
3864    }
3865
3866    void UnlockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags)
3867    {
3868       OGLSystem oglSystem = displaySystem.driverData;
3869       SETCAPS(oglSystem.capabilities);
3870       if(glCaps_vertexBuffer)
3871       {
3872          OGLMesh oglMesh = mesh.data;
3873          if(!flags) flags = mesh.flags;
3874          if(flags.vertices)
3875             oglMesh.vertices.allocate(
3876                mesh.nVertices * (mesh.flags.doubleVertices ? sizeof(Vector3D) : sizeof(Vector3Df)), mesh.vertices, staticDraw);
3877
3878          if(flags.normals)
3879             oglMesh.normals.allocate(
3880                mesh.nVertices * (mesh.flags.doubleNormals ? sizeof(Vector3D) : sizeof(Vector3Df)), mesh.normals, staticDraw);
3881
3882          if(flags.texCoords1)
3883             oglMesh.texCoords.allocate(
3884                mesh.nVertices * sizeof(Pointf), mesh.texCoords, staticDraw);
3885
3886          if(flags.colors)
3887             oglMesh.colors.allocate(
3888                mesh.nVertices * sizeof(ColorRGBAf), mesh.colors, staticDraw);
3889
3890          if(flags.tangents)
3891             oglMesh.tangents.allocate(mesh.nVertices * 2*sizeof(Vector3Df), mesh.tangents, staticDraw);
3892
3893          if(flags.lightVectors)
3894             oglMesh.lightVectors.allocate(mesh.nVertices * sizeof(ColorRGB), mesh.lightVectors, staticDraw);
3895       }
3896    }
3897
3898    bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags)
3899    {
3900       bool result = true;
3901
3902       return result;
3903    }
3904
3905    void FreeIndices(DisplaySystem displaySystem, OGLIndices oglIndices)
3906    {
3907       OGLSystem oglSystem = displaySystem.driverData;
3908       SETCAPS(oglSystem.capabilities);
3909       if(oglIndices)
3910       {
3911          oglIndices.buffer.free(glCaps_vertexBuffer);
3912          delete oglIndices.indices;
3913          delete oglIndices;
3914       }
3915    }
3916
3917    void * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
3918    {
3919       OGLIndices oglIndices = OGLIndices { };
3920       if(oglIndices)
3921       {
3922          oglIndices.indices = (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
3923          oglIndices.nIndices = nIndices;
3924       }
3925       return oglIndices;
3926    }
3927
3928    void UnlockIndices(DisplaySystem displaySystem, OGLIndices oglIndices, bool indices32bit, int nIndices)
3929    {
3930       OGLSystem oglSystem = displaySystem.driverData;
3931       SETCAPS(oglSystem.capabilities);
3932       if(glCaps_vertexBuffer)
3933       {
3934          if(!glCaps_intAndDouble && indices32bit)
3935          {
3936             if(!oglIndices.buffer.buffer)
3937                glGenBuffers(1, &oglIndices.buffer.buffer);
3938             if(glabCurElementBuffer != oglIndices.buffer.buffer)
3939                GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, oglIndices.buffer.buffer);
3940
3941             {
3942                uint * pointer = (uint *)oglIndices.indices;
3943                int i;
3944                uint16 * b;
3945                if(nIndices > oglSystem.shortBDSize)
3946                {
3947                   oglSystem.shortBDSize = nIndices;
3948                   oglSystem.shortBDBuffer = renew oglSystem.shortBDBuffer uint16[oglSystem.shortBDSize];
3949                }
3950                b = oglSystem.shortBDBuffer;
3951                for(i = 0; i < nIndices; i++)
3952                   b[i] = (uint16)pointer[i];
3953
3954                glBufferData(GL_ELEMENT_ARRAY_BUFFER, nIndices * sizeof(uint16), b, GL_STATIC_DRAW);
3955             }
3956          }
3957          else
3958             oglIndices.buffer.allocate(
3959                nIndices * (indices32bit ? sizeof(uint32) : sizeof(uint16)),
3960                oglIndices.indices, staticDraw);
3961       }
3962    }
3963
3964    uint16 * LockIndices(DisplaySystem displaySystem, OGLIndices oglIndices)
3965    {
3966
3967       return oglIndices.indices;
3968    }
3969
3970    void SelectMesh(Display display, Mesh mesh)
3971    {
3972 #if !defined( __ANDROID__) && !defined(__APPLE__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
3973 #if defined(__WIN32__)
3974       if(glUnlockArraysEXT)
3975 #endif
3976          if(!glCaps_vertexBuffer && display.display3D.mesh)
3977             glUnlockArraysEXT();
3978 #endif
3979       if(mesh)
3980       {
3981          OGLMesh oglMesh = mesh.data;
3982
3983          // *** Vertex Stream ***
3984          GLEnableClientState(VERTICES);
3985          if(!display.display3D.collectingHits && oglMesh)
3986          {
3987             oglMesh.vertices.use(vertex, 3, (mesh.flags.doubleVertices ? GL_DOUBLE : GL_FLOAT), 0, oglMesh.vertices.buffer ? null : (double *)mesh.vertices);
3988
3989             // *** Normals Stream ***
3990             if(mesh.normals || mesh.flags.normals)
3991             {
3992                GLEnableClientState(NORMALS);
3993                oglMesh.normals.use(normal, 3, GL_FLOAT, 0, oglMesh.normals.buffer ? null : mesh.normals);
3994             }
3995             else
3996                GLDisableClientState(NORMALS);
3997
3998 #if ENABLE_GL_SHADERS
3999             if(glCaps_shaders)
4000             {
4001                // *** Tangents Stream ***
4002                if(mesh.tangents || mesh.flags.tangents)
4003                {
4004                   GLEnableClientState(TANGENTS1);
4005                   GLEnableClientState(TANGENTS2);
4006                   oglMesh.tangents.use(tangent1, 3, GL_FLOAT, sizeof(Vector3Df)*2, oglMesh.tangents.buffer ? null : mesh.tangents);
4007                   oglMesh.tangents.use(tangent2, 3, GL_FLOAT, sizeof(Vector3Df)*2, oglMesh.tangents.buffer ? (void *)sizeof(Vector3Df) : mesh.tangents+1);
4008                }
4009                else
4010                {
4011                   GLDisableClientState(TANGENTS1);
4012                   GLDisableClientState(TANGENTS2);
4013                }
4014             }
4015 #endif
4016
4017             // *** Texture Coordinates Stream ***
4018             if(mesh.texCoords || mesh.flags.texCoords1)
4019             {
4020                GLEnableClientState(TEXCOORDS);
4021                oglMesh.texCoords.use(texCoord, 2, GL_FLOAT, 0, oglMesh.texCoords.buffer ? null : mesh.texCoords);
4022             }
4023             else
4024                GLDisableClientState(TEXCOORDS);
4025
4026 #if ENABLE_GL_FFP
4027             if(!glCaps_shaders)
4028             {
4029                // *** Normal Map Aligned Light Vector ***
4030                if(mesh.lightVectors || mesh.flags.lightVectors)
4031                {
4032                   GLEnableClientState(LIGHTVECTORS);
4033                   oglMesh.lightVectors.use(lightVector, 3, GL_FLOAT, 0, oglMesh.lightVectors.buffer ? null : mesh.lightVectors);
4034                }
4035                else
4036                   GLDisableClientState(LIGHTVECTORS);
4037             }
4038             else
4039 #endif
4040             // *** Color Stream ***
4041             if(mesh.colors || mesh.flags.colors)
4042             {
4043                GLEnableClientState(COLORS);
4044                oglMesh.colors.use(color, 4, GL_FLOAT, 0, oglMesh.colors.buffer ? null : mesh.colors);
4045             }
4046             else
4047                GLDisableClientState(COLORS);
4048          }
4049          else
4050          {
4051             noAB.use(vertex, 3, (mesh.flags.doubleVertices ? GL_DOUBLE : GL_FLOAT), 0, (double *)mesh.vertices);
4052             if((mesh.normals || mesh.flags.normals) && !display.display3D.collectingHits)
4053             {
4054                GLEnableClientState(NORMALS);
4055                noAB.use(normal, 3, GL_FLOAT, 0, mesh.normals);
4056             }
4057             else
4058                GLDisableClientState(NORMALS);
4059 #if ENABLE_GL_SHADERS
4060             if(glCaps_shaders)
4061             {
4062                if((mesh.tangents || mesh.flags.tangents) && !display.display3D.collectingHits)
4063                {
4064                   GLEnableClientState(TANGENTS1);
4065                   GLEnableClientState(TANGENTS2);
4066                   noAB.use(tangent1, 3, GL_FLOAT, sizeof(Vector3Df)*2, mesh.tangents);
4067                   noAB.use(tangent2, 3, GL_FLOAT, sizeof(Vector3Df)*2, mesh.tangents+1);
4068                }
4069                else
4070                {
4071                   GLDisableClientState(TANGENTS1);
4072                   GLDisableClientState(TANGENTS2);
4073                }
4074             }
4075 #endif
4076
4077             if((mesh.texCoords || mesh.flags.texCoords1) && !display.display3D.collectingHits)
4078             {
4079                GLEnableClientState(TEXCOORDS);
4080                noAB.use(texCoord, 2, GL_FLOAT, 0, mesh.texCoords);
4081             }
4082             else
4083                GLDisableClientState(TEXCOORDS);
4084
4085 #if ENABLE_GL_FFP
4086             if(!glCaps_shaders)
4087             {
4088                if((mesh.lightVectors || mesh.flags.lightVectors) && !display.display3D.collectingHits)
4089                {
4090                   GLEnableClientState(LIGHTVECTORS);
4091                   noAB.use(lightVector, 3, GL_FLOAT, sizeof(ColorRGB), mesh.lightVectors);
4092                }
4093                else
4094                   GLDisableClientState(LIGHTVECTORS);
4095             }
4096             else
4097 #endif
4098             if((mesh.colors || mesh.flags.colors) && !display.display3D.collectingHits)
4099             {
4100                GLEnableClientState(COLORS);
4101                noAB.use(color, 4, GL_FLOAT, 0, mesh.colors);
4102             }
4103             else
4104                GLDisableClientState(COLORS);
4105          }
4106
4107 #if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
4108
4109 #if defined(__WIN32__)
4110          if(glLockArraysEXT)
4111 #endif
4112             if(!glCaps_vertexBuffer)
4113                glLockArraysEXT(0, mesh.nVertices);
4114 #endif
4115       }
4116    }
4117
4118    void DrawPrimitives(Display display, PrimitiveSingle * primitive, Mesh mesh)
4119    {
4120       if(primitive->type.vertexRange)
4121       {
4122          GLFlushMatrices();
4123          glDrawArrays(getPrimitiveType(primitive->type.primitiveType), primitive->first, primitive->nVertices);
4124       }
4125       else
4126       {
4127          OGLIndices oglIndices = primitive->data;
4128          GLEAB eab = ((!display.display3D.collectingHits && oglIndices && glCaps_vertexBuffer) ? oglIndices.buffer : noEAB);
4129          if(!glCaps_intAndDouble && !glCaps_vertexBuffer && primitive->type.indices32bit)
4130          {
4131             uint16 * temp = new uint16[primitive->nIndices];
4132             uint32 * src = (uint32 *)(oglIndices ? oglIndices.indices : primitive->indices);
4133             int i;
4134             for(i = 0; i < primitive->nIndices; i++)
4135                temp[i] = (uint16)src[i];
4136             eab.draw(getPrimitiveType(primitive->type.primitiveType), primitive->nIndices, GL_UNSIGNED_SHORT, temp);
4137             delete temp;
4138          }
4139          else
4140             eab.draw(getPrimitiveType(primitive->type.primitiveType), primitive->nIndices,
4141                primitive->type.indices32bit ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT,
4142                eab.buffer ? 0 : (oglIndices ? oglIndices.indices : primitive->indices));
4143          GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
4144       }
4145    }
4146
4147    void PushMatrix(Display display)
4148    {
4149       GLPushMatrix();
4150    }
4151
4152    void PopMatrix(Display display, bool setMatrix)
4153    {
4154       GLPopMatrix();
4155    }
4156
4157    void SetTransform(Display display, Matrix transMatrix, bool viewSpace, bool useCamera)
4158    {
4159       Matrix matrix = transMatrix;
4160       Camera camera = useCamera ? display.display3D.camera : null;
4161
4162       if(viewSpace)
4163       {
4164          GLLoadIdentity();
4165          GLScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane);
4166       }
4167       else if(camera)
4168       {
4169          GLTranslated(
4170             matrix.m[3][0] - camera.cPosition.x,
4171             matrix.m[3][1] - camera.cPosition.y,
4172             matrix.m[3][2] - camera.cPosition.z);
4173       }
4174       else
4175          GLTranslated(
4176             matrix.m[3][0],
4177             matrix.m[3][1],
4178             matrix.m[3][2]);
4179
4180       matrix.m[3][0] = 0;
4181       matrix.m[3][1] = 0;
4182       matrix.m[3][2] = 0;
4183
4184       GLMultMatrixd(matrix.array);
4185    }
4186 #endif
4187 }
4188
4189 public void UseSingleGLContext(bool useSingle)
4190 {
4191    useSingleGLContext = useSingle;
4192 }
4193
4194 default dllexport void *
4195 #if defined(__WIN32__)
4196 __attribute__((stdcall))
4197 #endif
4198 IS_GLGetContext(DisplaySystem displaySystem)
4199 {
4200    if(displaySystem)
4201    {
4202 #if defined(__WIN32__)
4203       OGLSystem system = displaySystem.driverData;
4204       return system.glrc;
4205 #elif defined(__ANDROID__) || defined(__ODROID__)
4206       return eglContext;
4207 #elif defined(__EMSCRIPTEN__)
4208       OGLSystem system = displaySystem.driverData;
4209       return (void *)system.glc;
4210 #else
4211       OGLSystem system = displaySystem.driverData;
4212       return system.glContext;
4213 #endif
4214    }
4215    return null;
4216 }
4217
4218 #endif