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