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