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