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