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