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