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