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