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