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