24fd64099130efaefdf40781a43adc78ebaced89
[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
2668          if(!result)
2669             FreeBitmap(displaySystem, bitmap);
2670          else if(oglSystem.loadingFont)
2671          {
2672             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2673             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2674             oglSystem.loadingFont = false;
2675          }
2676       }
2677       return result;
2678    }
2679
2680    void ReleaseSurface(Display display, Surface surface)
2681    {
2682       glDisable(GL_SCISSOR_TEST);
2683       delete surface.driverData;
2684       surface.driverData = null;
2685    }
2686
2687    bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x, int y, Box clip)
2688    {
2689       return false;
2690    }
2691
2692    bool GetSurface(Display display, Surface surface, int x,int y, Box clip)
2693    {
2694       bool result = false;
2695       OGLSurface oglSurface = surface.driverData = OGLSurface { };
2696
2697       //Logf("GetSurface\n");
2698
2699       if(oglSurface)
2700       {
2701          if(displayWidth != display.width || displayHeight != display.height)
2702          {
2703             displayWidth = display.width;
2704             displayHeight = display.height;
2705
2706             glViewport(0,0,display.width,display.height);
2707             glLoadIdentity();
2708             glOrtho(0,display.width,display.height,0,0.0,1.0);
2709          }
2710
2711          surface.offset.x = x;
2712          surface.offset.y = y;
2713          surface.unclippedBox = surface.box = clip;
2714          oglSurface.bitmapMult[0] = 1;
2715          oglSurface.bitmapMult[1] = 1;
2716          oglSurface.bitmapMult[2] = 1;
2717          oglSurface.bitmapMult[3] = 1;
2718
2719          glEnable(GL_SCISSOR_TEST);
2720          glScissor(
2721             x+clip.left,
2722             (display.height) -(y+clip.bottom)-1,
2723             clip.right-clip.left+1,
2724             clip.bottom-clip.top+1);
2725          result = true;
2726       }
2727       return result;
2728    }
2729
2730    void Clip(Display display, Surface surface, Box clip)
2731    {
2732       Box box;
2733
2734       //Logf("Clip\n");
2735
2736       if(clip != null)
2737       {
2738          box = clip;
2739          box.Clip(surface.unclippedBox);
2740          surface.box = box;
2741       }
2742       else
2743          box = surface.box = surface.unclippedBox;
2744       box.left += surface.offset.x;
2745       box.top  += surface.offset.y;
2746       box.right+= surface.offset.x;
2747       box.bottom += surface.offset.y;
2748
2749       glScissor(
2750          box.left,display.height - box.bottom - 1,
2751          box.right-box.left+1, box.bottom-box.top+1);
2752    }
2753
2754    bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
2755    {
2756       bool result = false;
2757       OGLDisplay oglDisplay = display.driverData;
2758       ColorAlpha * flippingBuffer = oglDisplay.flippingBuffer;
2759
2760       if(oglDisplay.flippingBuffer)
2761       {
2762          if(bitmap.pixelFormat != pixelFormat888 || bitmap.width < w || bitmap.height < h)
2763          {
2764             bitmap.Free();
2765             bitmap.Allocate(null, w,h,w, pixelFormat888, false);
2766          }
2767          if(bitmap)
2768          {
2769             uint row;
2770
2771             glPixelStorei(GL_PACK_ALIGNMENT, 4);
2772             glPixelStorei(GL_PACK_ROW_LENGTH, bitmap.stride);
2773             glPixelStorei(GL_PACK_SKIP_ROWS, 0);
2774             glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
2775             glReadPixels(x,display.height-h-y,w,h,GL_BGRA_EXT,GL_UNSIGNED_BYTE, flippingBuffer);
2776
2777             // Need a flip...
2778             for(row = 0; row<h; row++)
2779                CopyBytesBy4(((ColorAlpha *)bitmap.picture) + row * w, ((ColorAlpha *)flippingBuffer) + (h-row-1) * w, w);
2780             result = true;
2781          }
2782       }
2783       return result;
2784    }
2785
2786    void SetForeground(Display display, Surface surface, ColorAlpha color)
2787    {
2788       OGLSurface oglSurface = surface.driverData;
2789
2790       //Logf("SetForeground\n");
2791
2792       oglSurface.foreground[0] = color.color.r/255.0f;
2793       oglSurface.foreground[1] = color.color.g/255.0f;
2794       oglSurface.foreground[2] = color.color.b/255.0f;
2795       //oglSurface.foreground[3] = 1.0f;
2796       oglSurface.foreground[3] = color.a/255.0f;
2797
2798       //if(!oglSurface.foreground[3])printf("bug");
2799    }
2800
2801    void SetBackground(Display display, Surface surface, ColorAlpha color)
2802    {
2803       OGLSurface oglSurface = surface.driverData;
2804
2805       //Logf("SetBackground\n");
2806
2807       oglSurface.background[0] = color.color.r/255.0f;
2808       oglSurface.background[1] = color.color.g/255.0f;
2809       oglSurface.background[2] = color.color.b/255.0f;
2810       //oglSurface.background[3] = 1.0;
2811       oglSurface.background[3] = color.a/255.0f;
2812    }
2813
2814    void SetBlitTint(Display display, Surface surface, ColorAlpha color)
2815    {
2816       OGLSurface oglSurface = surface.driverData;
2817
2818       oglSurface.bitmapMult[0] = color.color.r/255.0f;
2819       oglSurface.bitmapMult[1] = color.color.g/255.0f;
2820       oglSurface.bitmapMult[2] = color.color.b/255.0f;
2821       oglSurface.bitmapMult[3] = color.a/255.0f;
2822    }
2823
2824    ColorAlpha GetPixel(Display display, Surface surface,int x,int y)
2825    {
2826       return 0;
2827    }
2828
2829    void PutPixel(Display display, Surface surface,int x,int y)
2830    {
2831       OGLSurface oglSurface = surface.driverData;
2832
2833       //Logf("PutPixel\n");
2834
2835       glColor4fv(oglSurface.foreground);
2836       glBegin(GL_POINTS);
2837       // glVertex2i(x+surface.offset.x, y+surface.offset.y);
2838       glVertex2f(x+surface.offset.x + 0.5f, y+surface.offset.y + 0.5f);
2839
2840       glEnd();
2841    }
2842
2843    void DrawLine(Display display, Surface surface, int _x1, int _y1, int _x2, int _y2)
2844    {
2845       OGLSurface oglSurface = surface.driverData;
2846       float x1 = _x1, x2 = _x2, y1 = _y1, y2 = _y2;
2847       if(_x1 == _x2)
2848       {
2849          if(_y2 >= _y1)
2850             y2 += 1;
2851          else
2852             y1 += 1;
2853       }
2854       else if(_y1 == _y2)
2855       {
2856          if(_x2 >= _x1)
2857             x2 += 1;
2858          else
2859             x1 += 1;
2860       }
2861       x1 += surface.offset.x;
2862       y1 += surface.offset.y;
2863       x2 += surface.offset.x;
2864       y2 += surface.offset.y;
2865
2866       //Logf("Line\n");
2867
2868       glColor4fv(oglSurface.foreground);
2869       glBegin(GL_LINES);
2870 #if defined(_GLES) || defined(EM_MODE)
2871       if(stippleEnabled)
2872       {
2873          glTexCoord2f(0.5f, 0);
2874          glVertex2f(x1 + 0.5f, y1 + 0.5f);
2875          glTexCoord2f(Max(x2-x1, y2-y1) + 0.5f, 0);
2876          glVertex2f(x2 + 0.5f, y2 + 0.5f);
2877       }
2878       else
2879 #endif
2880       {
2881          /*
2882          glVertex2i(x1, y1);
2883          glVertex2i(x2, y2);
2884          */
2885          glVertex2f(x1 + 0.5f, y1 + 0.5f);
2886          glVertex2f(x2 + 0.5f, y2 + 0.5f);
2887       }
2888
2889       glEnd();
2890    }
2891
2892    void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
2893    {
2894       OGLSurface oglSurface = surface.driverData;
2895       x1 += surface.offset.x;
2896       y1 += surface.offset.y;
2897       x2 += surface.offset.x;
2898       y2 += surface.offset.y;
2899
2900       //Logf("Rectangle\n");
2901
2902       glColor4fv(oglSurface.foreground);
2903 #if defined(_GLES) || defined(EM_MODE)
2904       if(stippleEnabled)
2905       {
2906          glBegin(GL_LINES);
2907
2908          glTexCoord2f(0.5f, 0);
2909          glVertex2f(x1 + 0.5f, y1 + 0.5f);
2910          glTexCoord2f(y2-y1 + 0.5f, 0);
2911          glVertex2f(x1 + 0.5f, y2 + 0.5f);
2912
2913          glTexCoord2f(0.5f, 0);
2914          glVertex2f(x1 + 0.5f, y2 + 0.5f);
2915          glTexCoord2f(x2 - x1 + 0.5f, 0);
2916          glVertex2f(x2 + 0.5f, y2 + 0.5f);
2917
2918          glTexCoord2f(0.5f, 0);
2919          glVertex2f(x2 + 0.5f, y2 + 0.5f);
2920          glTexCoord2f(y1 - y2 + 0.5f, 0);
2921          glVertex2f(x2 + 0.5f, y1 + 0.5f);
2922
2923          glTexCoord2f(0.5f, 0);
2924          glVertex2f(x2 + 0.5f, y1 + 0.5f);
2925          glTexCoord2f(x1 - x2 + 0.5f, 0);
2926          glVertex2f(x1 + 0.5f, y1 + 0.5f);
2927       }
2928       else
2929 #endif
2930       {
2931          glBegin(GL_LINE_LOOP);
2932          /*
2933          glVertex2i(x1, y1);
2934          glVertex2i(x1, y2);
2935          glVertex2i(x2, y2);
2936          glVertex2i(x2, y1);
2937          */
2938          glVertex2f(x1 + 0.5f, y1 + 0.5f);
2939          glVertex2f(x1 + 0.5f, y2 + 0.5f);
2940          glVertex2f(x2 + 0.5f, y2 + 0.5f);
2941          glVertex2f(x2 + 0.5f, y1 + 0.5f);
2942       }
2943       glEnd();
2944    }
2945
2946    void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
2947    {
2948       OGLSurface oglSurface = surface.driverData;
2949       //Logf("Area\n");
2950
2951       glColor4fv(oglSurface.background);
2952
2953 #ifdef EM_MODE
2954       glBegin(GL_QUADS);
2955       glVertex2f(x1+surface.offset.x, y1+surface.offset.y);
2956       glVertex2f(x1+surface.offset.x, y2+surface.offset.y+1);
2957       glVertex2f(x2+surface.offset.x+1, y2+surface.offset.y+1);
2958       glVertex2f(x2+surface.offset.x+1, y1+surface.offset.y);
2959       glEnd();
2960 #else
2961       glRecti(x1+surface.offset.x, y1+surface.offset.y,
2962               x2+surface.offset.x + 1, y2+surface.offset.y + 1);
2963 #endif
2964       /*
2965       glRectf(x1+surface.offset.x, y1+surface.offset.y,
2966               x2+surface.offset.x + 1, y2+surface.offset.y + 1);
2967       */
2968    }
2969
2970    void Clear(Display display, Surface surface, ClearType type)
2971    {
2972       OGLDisplay oglDisplay = display.driverData;
2973       OGLSurface oglSurface = surface.driverData;
2974
2975       //Logf("Clear\n");
2976       if(type != depthBuffer)
2977          glClearColor(oglSurface.background[0], oglSurface.background[1], oglSurface.background[2], oglSurface.background[3]);
2978       if(type != colorBuffer && !oglDisplay.depthWrite)
2979       {
2980          glDepthMask((byte)bool::true);
2981       }
2982       glClear(((type != depthBuffer) ? GL_COLOR_BUFFER_BIT : 0) |
2983               ((type != colorBuffer) ? GL_DEPTH_BUFFER_BIT : 0));
2984       if(type != colorBuffer && !oglDisplay.depthWrite)
2985       {
2986          glDepthMask((byte)bool::false);
2987       }
2988    }
2989
2990    bool ConvertBitmap(DisplaySystem displaySystem, Bitmap bitmap, PixelFormat format, ColorAlpha * palette)
2991    {
2992       return true;
2993    }
2994
2995    void Blit(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h)
2996    {
2997       OGLSurface oglSurface = surface.driverData;
2998
2999 #if !defined(__OLDX__)
3000          // WHY DO WE HAVE GL_ONE HERE ?
3001          /*if(glBlendFuncSeparate && !oglSurface.writingText)
3002             glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);*/
3003 #endif
3004
3005       if(!oglSurface.writingText)
3006       {
3007          // glTranslatef(-0.375f, -0.375f, 0.0f);
3008          glEnable(GL_TEXTURE_2D);
3009          glColor4fv(oglSurface.bitmapMult);
3010       }
3011       else if(oglSurface.xOffset)
3012          glTranslated(oglSurface.xOffset / 64.0/*-0.375*/, 0.0, 0.0);
3013
3014       glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)bitmap.driverData);
3015       glBegin(GL_QUADS);
3016
3017       if(h < 0)
3018       {
3019          glTexCoord2f((float)sx/ bitmap.width, (float)(sy-h)/ bitmap.height);
3020          glVertex2i(dx+surface.offset.x, dy+surface.offset.y);
3021          glTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy-h)/ bitmap.height);
3022          glVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
3023          glTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height);
3024          glVertex2i(dx+w+surface.offset.x, dy-h+surface.offset.y);
3025          glTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height);
3026          glVertex2i(dx+surface.offset.x, dy-h+surface.offset.y);
3027       }
3028       else
3029       {
3030          /*
3031          glTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height);
3032          glVertex2i(dx+surface.offset.x, dy+surface.offset.y);
3033          glTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height);
3034          glVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
3035          glTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy+h)/ bitmap.height);
3036          glVertex2i(dx+w+surface.offset.x, dy+h+surface.offset.y);
3037          glTexCoord2f((float)sx/ bitmap.width, (float)(sy+h)/ bitmap.height);
3038          glVertex2i(dx+surface.offset.x, dy+h+surface.offset.y);
3039          */
3040
3041          glTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height);
3042          glVertex2f((float)dx+surface.offset.x, (float)dy+surface.offset.y);
3043          glTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height);
3044          glVertex2f((float)dx+w+surface.offset.x, (float)dy+surface.offset.y);
3045          glTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy+h)/ bitmap.height);
3046          glVertex2f((float)dx+w+surface.offset.x, (float)dy+h+surface.offset.y);
3047          glTexCoord2f((float)sx/ bitmap.width, (float)(sy+h)/ bitmap.height);
3048          glVertex2f((float)dx+surface.offset.x, (float)dy+h+surface.offset.y);
3049       }
3050       glEnd();
3051
3052       if(!oglSurface.writingText)
3053       {
3054          glDisable(GL_TEXTURE_2D);
3055
3056          //glTranslate(0.375, 0.375, 0.0);
3057       }
3058       else if(oglSurface.xOffset)
3059          glTranslated(-oglSurface.xOffset / 64.0/*+0.375*/, 0.0, 0.0);
3060
3061 #if !defined(__OLDX__)
3062          /*if(glBlendFuncSeparate && !oglSurface.writingText)
3063             glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);*/
3064 #endif
3065    }
3066
3067    void Stretch(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
3068    {
3069       OGLSurface oglSurface = surface.driverData;
3070
3071       //glTranslate(-0.375, -0.375, 0.0);
3072
3073       //Logf("Stretch\n");
3074
3075 #if !defined(__OLDX__)
3076       /*if(glBlendFuncSeparate)
3077          glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);*/
3078 #endif
3079
3080       glEnable(GL_TEXTURE_2D);
3081       glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)bitmap.driverData);
3082
3083       glColor4fv(oglSurface.bitmapMult);
3084
3085       glBegin(GL_QUADS);
3086
3087       if(h < 0)
3088       {
3089          glTexCoord2f((float)(sx)/ bitmap.width, (float)(sy+sh)/ bitmap.height);
3090          glVertex2i(dx+surface.offset.x, dy+surface.offset.y);
3091
3092          glTexCoord2f((float)(sx+sw) / bitmap.width, (float)(sy+sh)/ bitmap.height);
3093          glVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
3094
3095          glTexCoord2f((float)(sx+sw)/ bitmap.width, (float)(sy)/ bitmap.height);
3096          glVertex2i(dx+w+surface.offset.x, dy-h+surface.offset.y);
3097
3098          glTexCoord2f((float)(sx) / bitmap.width, (float)(sy)/ bitmap.height);
3099          glVertex2i(dx+surface.offset.x, dy-h+surface.offset.y);
3100       }
3101       else
3102       {
3103          glTexCoord2f((float)(sx) / bitmap.width, (float)(sy)/ bitmap.height);
3104          glVertex2i(dx+surface.offset.x, dy+surface.offset.y);
3105
3106          glTexCoord2f((float)(sx+sw)/ bitmap.width, (float)(sy)/ bitmap.height);
3107          glVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
3108
3109          glTexCoord2f((float)(sx+sw) / bitmap.width, (float)(sy+sh)/ bitmap.height);
3110          glVertex2i(dx+w+surface.offset.x, dy+h+surface.offset.y);
3111
3112          glTexCoord2f((float)(sx)/ bitmap.width, (float)(sy+sh)/ bitmap.height);
3113          glVertex2i(dx+surface.offset.x, dy+h+surface.offset.y);
3114       }
3115
3116       glEnd();
3117
3118       glDisable(GL_TEXTURE_2D);
3119
3120       //glTranslate(0.375, 0.375, 0.0);
3121 #if !defined(__OLDX__)
3122       /*if(glBlendFuncSeparate)
3123          glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);*/
3124 #endif
3125
3126    }
3127
3128    void Filter(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
3129    {
3130       Stretch(display, surface, bitmap, dx, dy, sx, sy, w, h, sw, sh);
3131    }
3132
3133    void StretchDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
3134    {
3135 #if !defined(EM_MODE)
3136       float s2dw,s2dh,d2sw,d2sh;
3137       //bool flipX = false, flipY = false;
3138
3139       //Logf("StretchDI\n");
3140
3141       if(Sgn(w) != Sgn(sw))
3142       {
3143          w = Abs(w);
3144          sw = Abs(sw);
3145          //flipX = true;
3146       }
3147       if(Sgn(h) != Sgn(sh))
3148       {
3149          h = Abs(h);
3150          sh = Abs(sh);
3151          //flipY = true;
3152       }
3153
3154       s2dw=(float)w / sw;
3155       s2dh=(float)h / sh;
3156       d2sw=(float)sw / w;
3157       d2sh=(float)sh / h;
3158
3159       //Clip against the edges of the source
3160       if(sx<0)
3161       {
3162          dx+=(int)((0-sx) * s2dw);
3163          w-=(int)((0-sx) * s2dw);
3164          sw-=0-sx;
3165          sx=0;
3166       }
3167       if(sy<0)
3168       {
3169          dy+=(int)((0-sy) * s2dh);
3170          h-=(int)((0-sy) * s2dh);
3171
3172          sh-=0-sy;
3173          sy=0;
3174       }
3175       if(sx+sw>bitmap.width-1)
3176       {
3177          w-=(int)((sx+sw-(bitmap.width-1)-1)*s2dw);
3178          sw-=sx+sw-(bitmap.width-1)-1;
3179       }
3180       if(sy+sh>(bitmap.height-1))
3181       {
3182          h-=(int)((sy+sh-(bitmap.height-1)-1)*s2dh);
3183          sh-=sy+sh-(bitmap.height-1)-1;
3184       }
3185       //Clip against the edges of the surfaceination
3186       if(dx<surface.box.left)
3187       {
3188          //if(!flip)
3189          sx+=(int)((surface.box.left-dx)*d2sw);
3190          sw-=(int)((surface.box.left-dx)*d2sw);
3191          w-=surface.box.left-dx;
3192          dx=surface.box.left;
3193       }
3194       if(dy<surface.box.top)
3195       {
3196          sy+=(int)((surface.box.top-dy)*d2sh);
3197          sh-=(int)((surface.box.top-dy)*d2sh);
3198          h-=surface.box.top-dy;
3199          dy=surface.box.top;
3200       }
3201       if(dx+w>surface.box.right)
3202       {
3203          //if(flip) sx+=(int)((dx+w-surface.box.right-1)*d2sw);
3204          sw-=(int)((dx+w-surface.box.right-1)*d2sw);
3205          w-=dx+w-surface.box.right-1;
3206       }
3207       if(dy+h>surface.box.bottom)
3208       {
3209          sh-=(int)((dy+h-surface.box.bottom-1)*d2sh);
3210          h-=dy+h-surface.box.bottom-1;
3211       }
3212       if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
3213
3214       dx += surface.offset.x;
3215       dy += surface.offset.y;
3216
3217       if(bitmap.pixelFormat == pixelFormat888 && !bitmap.paletteShades)
3218       {
3219          glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
3220          glPixelStorei(GL_UNPACK_ROW_LENGTH, bitmap.stride);
3221          glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx);
3222          glPixelStorei(GL_UNPACK_SKIP_ROWS, sy);
3223          glRasterPos2d(dx,dy);
3224          //glPixelZoom(flipX ? -s2dw : s2dw, flipY ? s2dh : -s2dh);
3225          glPixelZoom(s2dw, -s2dh);
3226          glDrawPixels(sw,sh,GL_BGRA_EXT,GL_UNSIGNED_BYTE, bitmap.picture);
3227          glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
3228          glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3229          glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
3230          glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
3231       }
3232 #endif
3233    }
3234
3235    void BlitDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h)
3236    {
3237 #if !defined(EM_MODE)
3238       //Logf("BlitDI\n");
3239
3240       //Clip against the edges of the source
3241       if(sx<0)
3242       {
3243          dx+=-sx;
3244          w-=-sx;
3245          sx=0;
3246       }
3247       if(sy<0)
3248       {
3249          dy+=0-sy;
3250          h-=0-sy;
3251          sy=0;
3252       }
3253       if(sx+w>bitmap.width-1)
3254          w-=sx+w-(bitmap.width-1)-1;
3255       if(sy+h>bitmap.height-1)
3256          h-=sy+h-(bitmap.height-1)-1;
3257       //Clip against the edges of the surfaceination
3258       if(dx<surface.box.left)
3259       {
3260          //if(!flip)
3261          sx+=surface.box.left-dx;
3262          w-=surface.box.left-dx;
3263          dx=surface.box.left;
3264       }
3265       if(dy<surface.box.top)
3266       {
3267          sy+=surface.box.top-dy;
3268          h-=surface.box.top-dy;
3269          dy=surface.box.top;
3270       }
3271       if(dx+w>surface.box.right)
3272       {
3273          //if(flip) sx+=dx+w-surface.box.right-1;
3274          w-=dx+w-surface.box.right-1;
3275       }
3276       if(dy+h>surface.box.bottom)
3277          h-=dy+h-surface.box.bottom-1;
3278       if((w<=0)||(h<=0))
3279          return;
3280
3281       dx += surface.offset.x;
3282       dy += surface.offset.y;
3283
3284       if(bitmap.pixelFormat == pixelFormat888 && !bitmap.paletteShades)
3285       {
3286          glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
3287          glPixelStorei(GL_UNPACK_ROW_LENGTH, bitmap.stride);
3288          glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx);
3289          glPixelStorei(GL_UNPACK_SKIP_ROWS, sy);
3290          glRasterPos2d(dx,dy);
3291          glPixelZoom(1,-1);
3292          glDrawPixels(w,h,GL_BGRA_EXT,GL_UNSIGNED_BYTE, bitmap.picture);
3293          glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
3294          glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3295          glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
3296          glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
3297       }
3298 #endif
3299    }
3300
3301    void FilterDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
3302    {
3303       StretchDI(display, surface, bitmap, dx, dy, sx, sy, w, h, sw, sh);
3304    }
3305
3306    void UnloadFont(DisplaySystem displaySystem, Font font)
3307    {
3308       ((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, font);
3309    }
3310
3311    Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
3312    {
3313       Font font;
3314       OGLSystem oglSystem = displaySystem.driverData;
3315       oglSystem.loadingFont = true;
3316       font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags);
3317       return font;
3318    }
3319
3320    void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height)
3321    {
3322       ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(displaySystem, font, text, len, width, height);
3323    }
3324
3325    void WriteText(Display display, Surface surface, int x, int y, const char * text, int len)
3326    {
3327       OGLSurface oglSurface = surface.driverData;
3328       OGLSystem oglSystem = display.displaySystem.driverData;
3329       oglSystem.loadingFont = true;
3330
3331       //glTranslated(-0.375, -0.375, 0.0);
3332
3333       //Logf("Blit\n");
3334
3335       if(surface.textOpacity)
3336       {
3337          int w, h;
3338          FontExtent(display.displaySystem, surface.font, text, len, &w, &h);
3339          display.displaySystem.driver.Area(display, surface,x,y,x+w-1,y+h-1);
3340       }
3341
3342       oglSurface.writingText = true;
3343
3344       glEnable(GL_TEXTURE_2D);
3345
3346       if(surface.outline.size)
3347       {
3348          ColorAlpha outlineColor = surface.outline.color;
3349          glColor4ub(outlineColor.color.r, outlineColor.color.g, outlineColor.color.b, outlineColor.a);
3350          //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3351          //glEnable(GL_BLEND);
3352
3353          oglSurface.writingOutline = true;
3354          ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len);
3355          oglSurface.writingOutline = false;
3356       }
3357       glColor4fv(oglSurface.foreground);
3358
3359       ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len);
3360       oglSurface.writingText = false;
3361       oglSystem.loadingFont = false;
3362
3363       glDisable(GL_TEXTURE_2D);
3364
3365       //glTranslated(0.375, 0.375, 0.0);
3366    }
3367
3368    void TextFont(Display display, Surface surface, Font font)
3369    {
3370       ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextFont(display, surface, font);
3371    }
3372
3373    void TextOpacity(Display display, Surface surface, bool opaque)
3374    {
3375       OGLSurface oglSurface = surface.driverData;
3376       oglSurface.opaqueText = opaque;
3377    }
3378
3379    void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height)
3380    {
3381       OGLSurface oglSurface = surface.driverData;
3382       OGLSystem oglSystem = display.displaySystem.driverData;
3383       oglSystem.loadingFont = true;
3384       FontExtent(display.displaySystem, oglSurface.font, text, len, width, height);
3385       oglSystem.loadingFont = false;
3386    }
3387
3388    void DrawingChar(Display display, Surface surface, char character)
3389    {
3390
3391    }
3392
3393    void LineStipple(Display display, Surface surface, uint32 stipple)
3394    {
3395       //Logf("Stipple\n");
3396
3397       if(stipple)
3398       {
3399 #if defined(_GLES) || defined(EM_MODE)
3400          stippleEnabled = true;
3401          glesLineStipple(1, (uint16)stipple);
3402 #else
3403          glLineStipple(1, (uint16)stipple);
3404          glEnable(GL_LINE_STIPPLE);
3405 #endif
3406       }
3407       else
3408       {
3409 #if defined(_GLES) || defined(EM_MODE)
3410          stippleEnabled = false;
3411          glMatrixMode(GL_TEXTURE);
3412          glLoadIdentity();
3413          glMatrixMode(GL_PROJECTION);
3414          glDisable(GL_TEXTURE_2D);
3415 #else
3416          glDisable(GL_LINE_STIPPLE);
3417 #endif
3418       }
3419    }
3420 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
3421    void SetRenderState(Display display, RenderState state, uint value)
3422    {
3423       OGLDisplay oglDisplay = display.driverData;
3424       //Logf("RenderState\n");
3425
3426       switch(state)
3427       {
3428          case antiAlias:
3429             if(value)
3430                glEnable(GL_MULTISAMPLE_ARB);
3431             else
3432                glDisable(GL_MULTISAMPLE_ARB);
3433             break;
3434          case fillMode:
3435 #if !defined(_GLES)
3436             glPolygonMode(GL_FRONT_AND_BACK, ((FillModeValue)value == solid) ? GL_FILL : GL_LINE);
3437 #endif
3438             break;
3439          case depthTest:
3440             if(value) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
3441             break;
3442          case depthWrite:
3443             if(value) glDepthMask((byte)bool::true); else glDepthMask((byte)bool::false);
3444             oglDisplay.depthWrite = (bool)value;
3445             break;
3446          case fogColor:
3447          {
3448             float color[4] = { ((Color)value).r/255.0f, ((Color)value).g/255.0f, ((Color)value).b/255.0f, 1.0f };
3449             glFogfv(GL_FOG_COLOR, (float *)&color);
3450             break;
3451          }
3452          case fogDensity:
3453             glFogf(GL_FOG_DENSITY, (float)(RenderStateFloat { ui = value }.f * nearPlane));
3454             break;
3455          case blend:
3456             if(value) glEnable(GL_BLEND); else glDisable(GL_BLEND);
3457             break;
3458          case ambient:
3459          {
3460 #if !defined(EM_MODE)
3461             float ambient[4] = { ((Color)value).r/255.0f, ((Color)value).g/255.0f, ((Color)value).b/255.0f, 1.0f };
3462             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
3463 #endif
3464             break;
3465          }
3466          case alphaWrite:
3467          {
3468             if(value) glColorMask(1,1,1,1); else glColorMask(1,1,1,0);
3469             break;
3470          }
3471          case vSync:
3472          {
3473 #if defined(__WIN32__)
3474             wglSwapIntervalEXT(value ? 1 : 0);
3475 #endif
3476             break;
3477          }
3478       }
3479    }
3480
3481    void SetLight(Display display, int id, Light light)
3482    {
3483 #if !defined(EM_MODE)
3484       //Logf("SetLight\n");
3485
3486       if(light != null)
3487       {
3488          Object lightObject = light.lightObject;
3489          float position[4] = { 0, 0, 0, 0 };
3490          float color[4] = { 0, 0, 0, 1 };
3491
3492          glEnable(GL_LIGHT0 + id);
3493          /*
3494          glLightfv(GL_LIGHT0 + id, GL_DIFFUSE, (float *)&light.diffuse);
3495          glLightfv(GL_LIGHT0 + id, GL_AMBIENT, (float *)&light.ambient);
3496          glLightfv(GL_LIGHT0 + id, GL_SPECULAR,(float *)&light.specular);
3497          */
3498
3499          if(!light.multiplier) light.multiplier = 1.0f;
3500
3501          color[0] = light.diffuse.r * light.multiplier;
3502          color[1] = light.diffuse.g * light.multiplier;
3503          color[2] = light.diffuse.b * light.multiplier;
3504          glLightfv(GL_LIGHT0 + id, GL_DIFFUSE, color);
3505
3506          color[0] = light.ambient.r * light.multiplier;
3507          color[1] = light.ambient.g * light.multiplier;
3508          color[2] = light.ambient.b * light.multiplier;
3509          glLightfv(GL_LIGHT0 + id, GL_AMBIENT, color);
3510          color[0] = light.specular.r * light.multiplier;
3511          color[1] = light.specular.g * light.multiplier;
3512          color[2] = light.specular.b * light.multiplier;
3513          glLightfv(GL_LIGHT0 + id, GL_SPECULAR,color);
3514
3515          if(lightObject)
3516          {
3517             Vector3D positionVector;
3518             if(light.flags.spot)
3519             {
3520                if(lightObject.flags.root || !lightObject.parent)
3521                {
3522                   positionVector = lightObject.transform.position;
3523                   positionVector.Subtract(positionVector, display.display3D.camera.cPosition);
3524                }
3525                else
3526                {
3527                   positionVector.MultMatrix(lightObject.transform.position, lightObject.parent.matrix);
3528                   if(display.display3D.camera)
3529                      positionVector.Subtract(positionVector, display.display3D.camera.cPosition);
3530                }
3531                position[3] = 1;
3532             }
3533             else
3534             {
3535                if(!light.direction.x && !light.direction.y && !light.direction.z)
3536                {
3537                   Vector3Df vector { 0,0,-1 };
3538                   Matrix mat;
3539                   mat.RotationQuaternion(light.orientation);
3540                   positionVector.MultMatrixf(vector, mat);
3541                }
3542                else
3543                {
3544                   positionVector = light.direction;
3545                   position[3] = 1;
3546                }
3547             }
3548
3549             position[0] = (float)positionVector.x;
3550             position[1] = (float)positionVector.y;
3551             position[2] = (float)positionVector.z;
3552
3553             glLightfv(GL_LIGHT0 + id, GL_POSITION, position);
3554
3555             /*
3556             // Display Light Position
3557             glDisable(GL_LIGHTING);
3558             glDisable(GL_DEPTH_TEST);
3559             glColor3f(1,1,1);
3560             glPointSize(10);
3561             glBegin(GL_POINTS);
3562             glVertex3fv(position);
3563             glEnd();
3564             glEnable(GL_DEPTH_TEST);
3565             glEnable(GL_LIGHTING);
3566
3567
3568             // Display Target
3569             if(lightObject.flags.root || !lightObject.parent)
3570             {
3571                positionVector = light.target.transform.position;
3572                positionVector.Subtract(positionVector, display.camera.cPosition);
3573             }
3574             else
3575             {
3576                positionVector.MultMatrix(light.target.transform.position,
3577                   lightObject.light.target.parent.matrix);
3578                positionVector.Subtract(positionVector, display.camera.cPosition);
3579             }
3580
3581             position[0] = positionVector.x;
3582             position[1] = positionVector.y;
3583             position[2] = positionVector.z;
3584
3585             glDisable(GL_LIGHTING);
3586             glDisable(GL_DEPTH_TEST);
3587             glColor3f(1,1,0);
3588             glPointSize(10);
3589             glBegin(GL_POINTS);
3590             glVertex3fv(position);
3591             glEnd();
3592             glEnable(GL_DEPTH_TEST);
3593             glEnable(GL_LIGHTING);
3594             */
3595
3596             if(light.flags.attenuation)
3597             {
3598                glLightf(GL_LIGHT0 + id, GL_CONSTANT_ATTENUATION, light.Kc);
3599                glLightf(GL_LIGHT0 + id, GL_LINEAR_ATTENUATION, light.Kl);
3600                glLightf(GL_LIGHT0 + id, GL_QUADRATIC_ATTENUATION, light.Kq);
3601             }
3602
3603             if(light.flags.spot)
3604             {
3605                float exponent = 0;
3606                #define MAXLIGHT  0.9
3607                float direction[4] = { (float)light.direction.x, (float)light.direction.y, (float)light.direction.z, 1 };
3608                // Figure out exponent out of the hot spot
3609                exponent = (float)(log(MAXLIGHT) / log(cos((light.hotSpot / 2))));
3610
3611                glLightfv(GL_LIGHT0 + id, GL_SPOT_DIRECTION, direction);
3612                glLightf(GL_LIGHT0 + id, GL_SPOT_CUTOFF, (float)(light.fallOff / 2));
3613                glLightf(GL_LIGHT0 + id, GL_SPOT_EXPONENT, exponent);
3614             }
3615          }
3616          else
3617          {
3618
3619             Vector3Df vector { 0,0,-1 };
3620             Vector3Df direction;
3621             Matrix mat;
3622
3623             mat.RotationQuaternion(light.orientation);
3624             direction.MultMatrix(vector, mat);
3625
3626             position[0] = direction.x;
3627             position[1] = direction.y;
3628             position[2] = direction.z;
3629
3630             glLightfv(GL_LIGHT0 + id, GL_POSITION, position);
3631          }
3632       }
3633       else
3634          glDisable(GL_LIGHT0 + id);
3635 #endif
3636    }
3637
3638    void SetCamera(Display display, Surface surface, Camera camera)
3639    {
3640       OGLDisplay oglDisplay = display.driverData;
3641       //Logf("SetCamera\n");
3642
3643       if(camera)
3644       {
3645          int left = surface.box.left + surface.offset.x;
3646          int top = surface.box.top  + surface.offset.y;
3647          int right = surface.box.right + surface.offset.x;
3648          int bottom = surface.box.bottom + surface.offset.y;
3649          float origX = surface.offset.x + camera.origin.x;
3650          float origY = surface.offset.y + camera.origin.y;
3651          int x = left;
3652          int y = display.height - bottom - 1;
3653          int w = right - left + 1;
3654          int h = bottom - top + 1;
3655
3656          // *** ViewPort ***
3657          glViewport(x, y, w, h);
3658
3659          // *** Projection Matrix ***
3660          if(!display.display3D.camera)
3661          {
3662             glMatrixMode(GL_PROJECTION);
3663             glPushMatrix();
3664          }
3665          else
3666             glMatrixMode(GL_PROJECTION);
3667          if(display.display3D.collectingHits)
3668          {
3669             float pickX = display.display3D.pickX + surface.offset.x;
3670             float pickY = display.height - (display.display3D.pickY + surface.offset.y) - 1;
3671             Matrix pickMatrix
3672             {
3673                {
3674                   w / display.display3D.pickWidth, 0, 0, 0,
3675                   0, h / display.display3D.pickHeight, 0, 0,
3676                   0, 0, 1, 0,
3677                   (w + 2.0f * (x - pickX)) / display.display3D.pickWidth,
3678                   (h + 2.0f * (y - pickY)) / display.display3D.pickHeight, 0, 1
3679                }
3680             };
3681             glLoadMatrixd(pickMatrix.array);
3682          }
3683          else
3684             glLoadIdentity();
3685          glFrustum(
3686             (left   - origX) * camera.zMin / camera.focalX,
3687             (right  - origX) * camera.zMin / camera.focalX,
3688             (bottom - origY) * camera.zMin / camera.focalY,
3689             (top    - origY) * camera.zMin / camera.focalY,
3690             camera.zMin, camera.zMax);
3691
3692          glDisable(GL_BLEND);
3693
3694          // *** Z Inverted Identity Matrix ***
3695          glMatrixMode(GL_MODELVIEW);
3696          if(!display.display3D.camera)
3697             glPushMatrix();
3698
3699          glLoadIdentity();
3700
3701          glScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane);
3702
3703          // *** View Matrix ***
3704          glMultMatrixd(camera.viewMatrix.array);
3705
3706          // *** Lights ***
3707          // ...
3708
3709          glEnable(GL_DEPTH_TEST);
3710 //#if !defined(EM_MODE)
3711          glEnable(GL_LIGHTING);
3712          glShadeModel(GL_SMOOTH);
3713 //#endif
3714          glDepthMask((byte)bool::true);
3715          oglDisplay.depthWrite = true;
3716
3717          glEnable(GL_MULTISAMPLE_ARB);
3718       }
3719       else if(display.display3D.camera)
3720       {
3721          oglDisplay.depthWrite = false;
3722          glViewport(0,0,display.width,display.height);
3723
3724          glDisable(GL_CULL_FACE);
3725          glDisable(GL_DEPTH_TEST);
3726          glDisable(GL_LIGHTING);
3727          glDisable(GL_FOG);
3728          glDisable(GL_TEXTURE_2D);
3729 //#if !defined(EM_MODE)
3730          glShadeModel(GL_FLAT);
3731 //#endif
3732          glEnable(GL_BLEND);
3733          glDisable(GL_MULTISAMPLE_ARB);
3734
3735          // *** Restore 2D MODELVIEW Matrix ***
3736          glPopMatrix();
3737
3738          // *** Restore 2D PROJECTION Matrix ***
3739          glMatrixMode(GL_PROJECTION);
3740          glPopMatrix();
3741       }
3742
3743       GLBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
3744    }
3745
3746    void ApplyMaterial(Display display, Material material, Mesh mesh)
3747    {
3748       //Logf("ApplyMaterial\n");
3749
3750       // Basic Properties
3751       if(material.flags.doubleSided)
3752       {
3753 #if !defined(EM_MODE)
3754          glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, !material.flags.singleSideLight);
3755 #endif
3756          glDisable(GL_CULL_FACE);
3757       }
3758       else
3759       {
3760 #if !defined(EM_MODE)
3761          glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, bool::false);
3762 #endif
3763          glEnable(GL_CULL_FACE);
3764       }
3765
3766       // Fog
3767       if(material.flags.noFog)
3768          glDisable(GL_FOG);
3769       else
3770          glEnable(GL_FOG);
3771
3772       // Maps
3773       if(material.baseMap && (mesh.texCoords || mesh.flags.texCoords1))
3774       {
3775          Bitmap map = material.baseMap;
3776          glEnable(GL_TEXTURE_2D);
3777          glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)map.driverData);
3778
3779          glMatrixMode(GL_TEXTURE);
3780          glLoadIdentity();
3781          if(material.uScale && material.vScale)
3782             glScalef(material.uScale, material.vScale, 1);
3783          glMatrixMode(GL_MODELVIEW);
3784
3785          if(material.flags.tile)
3786          {
3787             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
3788             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
3789          }
3790          else
3791          {
3792             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3793             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3794          }
3795       }
3796       else
3797          glDisable(GL_TEXTURE_2D);
3798
3799 #ifdef EM_MODE
3800       glColor4f(material.diffuse.r, material.diffuse.g, material.diffuse.b, material.opacity);
3801 #else
3802       if(mesh.flags.colors)
3803       {
3804          glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
3805          glEnable(GL_COLOR_MATERIAL);
3806       }
3807       else
3808       {
3809          glDisable(GL_COLOR_MATERIAL);
3810          {
3811             float color[4] = { material.diffuse.r, material.diffuse.g, material.diffuse.b, material.opacity };
3812             glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
3813          }
3814          {
3815             float color[4] = { material.ambient.r, material.ambient.g, material.ambient.b, 0 };
3816             glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
3817          }
3818       }
3819       {
3820          float color[4] = { material.specular.r, material.specular.g, material.specular.b, 0 };
3821          glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
3822       }
3823       {
3824          float color[4] = { material.emissive.r, material.emissive.g, material.emissive.b, 0 };
3825          glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color);
3826       }
3827
3828       glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &material.power);
3829 #endif
3830    }
3831
3832    void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
3833    {
3834       OGLMesh oglMesh = mesh.data;
3835       if(oglMesh)
3836       {
3837          if(!mesh.flags.vertices)
3838          {
3839             if(oglMesh.vertices)
3840             {
3841                GLDeleteBuffers(1, &oglMesh.vertices);
3842                oglMesh.vertices = 0;
3843             }
3844             delete mesh.vertices;
3845          }
3846          if(!mesh.flags.normals)
3847          {
3848             if(oglMesh.normals)
3849             {
3850                GLDeleteBuffers(1, &oglMesh.normals);
3851                oglMesh.normals = 0;
3852             }
3853             delete mesh.normals;
3854          }
3855          if(!mesh.flags.texCoords1)
3856          {
3857             if(oglMesh.texCoords)
3858             {
3859                GLDeleteBuffers(1, &oglMesh.texCoords);
3860                oglMesh.texCoords = 0;
3861             }
3862             delete mesh.texCoords;
3863          }
3864          if(!mesh.flags.texCoords2)
3865          {
3866             if(oglMesh.texCoords2)
3867             {
3868                GLDeleteBuffers(1, &oglMesh.texCoords2);
3869                oglMesh.texCoords2 = 0;
3870             }
3871             /*
3872             delete mesh.texCoords2;
3873             */
3874          }
3875          if(!mesh.flags.colors)
3876          {
3877             if(oglMesh.colors)
3878             {
3879                GLDeleteBuffers(1, &oglMesh.colors);
3880                oglMesh.colors = 0;
3881             }
3882          }
3883          if(!mesh.flags)
3884          {
3885             delete oglMesh;
3886             mesh.data = null;
3887          }
3888       }
3889    }
3890
3891    bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags, int nVertices)
3892    {
3893       bool result = false;
3894
3895       if(!mesh.data)
3896          mesh.data = OGLMesh { };
3897       if(mesh.data)
3898       {
3899          if(mesh.nVertices == nVertices)
3900          {
3901             // Same number of vertices, adding features (Leaves the other features pointers alone)
3902             if(mesh.flags != flags)
3903             {
3904                if(!mesh.flags.vertices && flags.vertices)
3905                {
3906                   if(flags.doubleVertices)
3907                   {
3908                      mesh.vertices = (Vector3Df *)new Vector3D[nVertices];
3909                   }
3910                   else
3911                      mesh.vertices = new Vector3Df[nVertices];
3912                }
3913                if(!mesh.flags.normals && flags.normals)
3914                {
3915                   if(flags.doubleNormals)
3916                   {
3917                      mesh.normals = (Vector3Df *)new Vector3D[nVertices];
3918                   }
3919                   else
3920                      mesh.normals = new Vector3Df[nVertices];
3921                }
3922                if(!mesh.flags.texCoords1 && flags.texCoords1)
3923                {
3924                   mesh.texCoords = new Pointf[nVertices];
3925                }
3926                if(!mesh.flags.colors && flags.colors)
3927                {
3928                   mesh.colors = new ColorRGBAf[nVertices];
3929                }
3930             }
3931          }
3932          else
3933          {
3934             // New number of vertices, reallocate all current and new features
3935             flags |= mesh.flags;
3936             if(flags.vertices)
3937             {
3938                if(flags.doubleVertices)
3939                {
3940                   mesh.vertices = (Vector3Df *)renew mesh.vertices Vector3D[nVertices];
3941                }
3942                else
3943                   mesh.vertices = renew mesh.vertices Vector3Df[nVertices];
3944             }
3945             if(flags.normals)
3946             {
3947                if(flags.doubleNormals)
3948                {
3949                   mesh.normals = (Vector3Df *)renew mesh.normals Vector3D[nVertices];
3950                }
3951                else
3952                   mesh.normals = renew mesh.normals Vector3Df[nVertices];
3953             }
3954             if(flags.texCoords1)
3955             {
3956                mesh.texCoords = renew mesh.texCoords Pointf[nVertices];
3957             }
3958             if(flags.colors)
3959             {
3960                mesh.colors = renew mesh.colors ColorRGBAf[nVertices];
3961             }
3962          }
3963          result = true;
3964       }
3965       return result;
3966    }
3967
3968    void UnlockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags)
3969    {
3970       OGLMesh oglMesh = mesh.data;
3971       if(!flags) flags = mesh.flags;
3972
3973       if(vboAvailable)
3974       {
3975          if(flags.vertices)
3976          {
3977             if(!oglMesh.vertices)
3978                GLGenBuffers(1, &oglMesh.vertices);
3979             GLBindBuffer(GL_ARRAY_BUFFER_ARB, oglMesh.vertices);
3980             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 );
3981          }
3982
3983          if(flags.normals)
3984          {
3985             if(!oglMesh.normals)
3986                GLGenBuffers(1, &oglMesh.normals);
3987             GLBindBuffer(GL_ARRAY_BUFFER_ARB, oglMesh.normals);
3988             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 );
3989          }
3990
3991          if(flags.texCoords1)
3992          {
3993             if(!oglMesh.texCoords)
3994                GLGenBuffers(1, &oglMesh.texCoords);
3995             GLBindBuffer(GL_ARRAY_BUFFER_ARB, oglMesh.texCoords);
3996             GLBufferData( GL_FLOAT, GL_ARRAY_BUFFER_ARB, mesh.nVertices * sizeof(Pointf), mesh.texCoords, GL_STATIC_DRAW_ARB );
3997          }
3998
3999          if(flags.colors)
4000          {
4001             if(!oglMesh.colors)
4002                GLGenBuffers( 1, &oglMesh.colors);
4003             GLBindBuffer( GL_ARRAY_BUFFER_ARB, oglMesh.colors);
4004             GLBufferData( GL_FLOAT, GL_ARRAY_BUFFER_ARB, mesh.nVertices * sizeof(ColorRGBAf), mesh.colors, GL_STATIC_DRAW_ARB );
4005          }
4006
4007          GLBindBuffer( GL_ARRAY_BUFFER_ARB, 0);
4008       }
4009    }
4010
4011    bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags)
4012    {
4013       bool result = true;
4014
4015         return result;
4016    }
4017
4018    void FreeIndices(DisplaySystem displaySystem, OGLIndices oglIndices)
4019    {
4020       if(oglIndices)
4021       {
4022          if(oglIndices.buffer)
4023             GLDeleteBuffers(1, &oglIndices.buffer);
4024          delete oglIndices.indices;
4025          delete oglIndices;
4026       }
4027    }
4028
4029    void * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
4030    {
4031       OGLIndices oglIndices = OGLIndices { };
4032       if(oglIndices)
4033       {
4034          oglIndices.indices = (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
4035          GLGenBuffers( 1, &oglIndices.buffer);
4036          oglIndices.nIndices = nIndices;
4037       }
4038       return oglIndices;
4039    }
4040
4041    void UnlockIndices(DisplaySystem displaySystem, OGLIndices oglIndices, bool indices32bit, int nIndices)
4042    {
4043       if(vboAvailable)
4044       {
4045          GLBindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB, oglIndices.buffer);
4046          GLBufferData( indices32bit ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, GL_ELEMENT_ARRAY_BUFFER_ARB, nIndices * (indices32bit ? sizeof(uint32) : sizeof(uint16)),
4047             oglIndices.indices, GL_STATIC_DRAW_ARB);
4048          GLBindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
4049       }
4050    }
4051
4052    uint16 * LockIndices(DisplaySystem displaySystem, OGLIndices oglIndices)
4053    {
4054
4055       return oglIndices.indices;
4056    }
4057
4058    void SelectMesh(Display display, Mesh mesh)
4059    {
4060       //Logf("SelectMesh\n");
4061
4062 #if !defined( __ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
4063
4064 #if defined(__WIN32__)
4065       if(glUnlockArraysEXT)
4066 #endif
4067          if(!vboAvailable && display.display3D.mesh)
4068             glUnlockArraysEXT();
4069
4070 #endif
4071       if(mesh)
4072       {
4073          OGLMesh oglMesh = mesh.data;
4074
4075          // *** Vertex Stream ***
4076          glEnableClientState(GL_VERTEX_ARRAY);
4077          if(!display.display3D.collectingHits && oglMesh)
4078          {
4079             GLBindBuffer(GL_ARRAY_BUFFER_ARB, oglMesh.vertices );
4080             if(mesh.flags.doubleVertices)
4081                glVertexPointerd(3, 0, oglMesh.vertices ? null : (double *)mesh.vertices, mesh.nVertices);
4082             else
4083                glVertexPointer(3, GL_FLOAT, 0, oglMesh.vertices ? null : mesh.vertices);
4084
4085             // *** Normals Stream ***
4086             if(mesh.normals || mesh.flags.normals)
4087             {
4088                glEnableClientState(GL_NORMAL_ARRAY);
4089                GLBindBuffer(GL_ARRAY_BUFFER_ARB, oglMesh.normals);
4090                glNormalPointer(/*mesh.flags.doubleNormals ? GL_DOUBLE : */GL_FLOAT, 0, oglMesh.normals ? null : mesh.normals);
4091             }
4092             else
4093                glDisableClientState(GL_NORMAL_ARRAY);
4094
4095             // *** Texture Coordinates Stream ***
4096             if(mesh.texCoords || mesh.flags.texCoords1)
4097             {
4098                glEnableClientState(GL_TEXTURE_COORD_ARRAY);
4099                GLBindBuffer( GL_ARRAY_BUFFER_ARB, oglMesh.texCoords);
4100                glTexCoordPointer(2, GL_FLOAT, 0, oglMesh.texCoords ? null : mesh.texCoords);
4101             }
4102             else
4103                glDisableClientState(GL_TEXTURE_COORD_ARRAY);
4104
4105             // *** Color Stream ***
4106             if(mesh.colors || mesh.flags.colors)
4107             {
4108                glEnableClientState(GL_COLOR_ARRAY);
4109                GLBindBuffer( GL_ARRAY_BUFFER_ARB, oglMesh.colors);
4110                glColorPointer(4, GL_FLOAT, 0, oglMesh.colors ? null : mesh.colors);
4111             }
4112             else
4113                glDisableClientState(GL_COLOR_ARRAY);
4114          }
4115          else
4116          {
4117             GLBindBuffer( GL_ARRAY_BUFFER_ARB, 0);
4118             if(mesh.flags.doubleVertices)
4119                glVertexPointerd(3, 0, (double *)mesh.vertices, mesh.nVertices);
4120             else
4121                glVertexPointer(3, GL_FLOAT, 0, mesh.vertices);
4122             if((mesh.normals || mesh.flags.normals) && !display.display3D.collectingHits)
4123             {
4124                glEnableClientState(GL_NORMAL_ARRAY);
4125                glNormalPointer(/*mesh.flags.doubleNormals ? GL_DOUBLE : */GL_FLOAT, 0, mesh.normals);
4126             }
4127             else
4128                glDisableClientState(GL_NORMAL_ARRAY);
4129             if((mesh.texCoords || mesh.flags.texCoords1) && !display.display3D.collectingHits)
4130             {
4131                glEnableClientState(GL_TEXTURE_COORD_ARRAY);
4132                glTexCoordPointer(2, GL_FLOAT, 0, mesh.texCoords);
4133             }
4134             else
4135                glDisableClientState(GL_TEXTURE_COORD_ARRAY);
4136             if((mesh.colors || mesh.flags.colors) && !display.display3D.collectingHits)
4137             {
4138                glEnableClientState(GL_COLOR_ARRAY);
4139                glColorPointer(4, GL_FLOAT, 0, mesh.colors);
4140             }
4141             else
4142                glDisableClientState(GL_COLOR_ARRAY);
4143          }
4144
4145 #if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
4146
4147 #if defined(__WIN32__)
4148          if(glLockArraysEXT)
4149 #endif
4150             if(!vboAvailable)
4151                glLockArraysEXT(0, mesh.nVertices);
4152
4153 #endif
4154       }
4155       else
4156          GLBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
4157    }
4158
4159    void DrawPrimitives(Display display, PrimitiveSingle * primitive, Mesh mesh)
4160    {
4161       //Logf("DrawPrimitives\n");
4162
4163       if(primitive->type.vertexRange)
4164          glDrawArrays(primitiveTypes[primitive->type.primitiveType], primitive->first, primitive->nVertices);
4165       else
4166       {
4167          //    *** Hoping the data won't be uploaded at all (Won't really work if another group of the mesh is using the mesh ) ***
4168          // HACK TO SPEED THINGS UP...
4169 #ifndef __ANDROID__
4170          /*GLBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
4171          if(primitive->nIndices < (mesh.nVertices >> 2) && !primitive->type.indices32bit)
4172          {
4173             int c;
4174             glBegin(primitiveTypes[primitive->type.primitiveType]);
4175             if(primitive->data)
4176             {
4177                OGLIndices oglIndices = primitive->data;
4178                MeshFeatures flags = mesh.flags;
4179                for(c = 0; c<primitive->nIndices; c++)
4180                {
4181                   uint16 index = ((uint16 *) oglIndices.indices)[c];
4182                   if(flags.normals) glNormal3fv((float *)&mesh.normals[index]);
4183                   if(flags.texCoords1) glTexCoord2fv((float *)&mesh.texCoords[index]);
4184                   if(flags.colors) glColor4fv((float *)&mesh.colors[index]);
4185                   glVertex3fv((float *)&mesh.vertices[index]);
4186                }
4187             }
4188             glEnd();
4189          }
4190          else*/
4191 #endif
4192          {
4193             OGLIndices oglIndices = primitive->data;
4194
4195             if(!display.display3D.collectingHits && vboAvailable && oglIndices)
4196             {
4197                GLBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, oglIndices.buffer);
4198                if(primitive->type.indices32bit)
4199                   glDrawElementsi(primitiveTypes[primitive->type.primitiveType], primitive->nIndices, 0);
4200                else
4201                   glDrawElements(primitiveTypes[primitive->type.primitiveType], primitive->nIndices, GL_UNSIGNED_SHORT, 0);
4202                GLBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
4203             }
4204             else
4205             {
4206                if(primitive->type.indices32bit)
4207                   glDrawElementsi(primitiveTypes[primitive->type.primitiveType], primitive->nIndices,
4208                      oglIndices ? oglIndices.indices : primitive->indices);
4209                else
4210                   glDrawElements(primitiveTypes[primitive->type.primitiveType], primitive->nIndices,
4211                      GL_UNSIGNED_SHORT, oglIndices ? oglIndices.indices : primitive->indices);
4212             }
4213          }
4214       }
4215    }
4216
4217    void PushMatrix(Display display)
4218    {
4219       glPushMatrix();
4220    }
4221
4222    void PopMatrix(Display display, bool setMatrix)
4223    {
4224       glPopMatrix();
4225    }
4226
4227    void SetTransform(Display display, Matrix transMatrix, bool viewSpace, bool useCamera)
4228    {
4229       Matrix matrix = transMatrix;
4230       Camera camera = useCamera ? display.display3D.camera : null;
4231
4232       if(viewSpace)
4233       {
4234          glLoadIdentity();
4235          glScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane);
4236       }
4237       else if(camera)
4238       {
4239          glTranslated(
4240             matrix.m[3][0] - camera.cPosition.x,
4241             matrix.m[3][1] - camera.cPosition.y,
4242             matrix.m[3][2] - camera.cPosition.z);
4243       }
4244       else
4245          glTranslated(
4246             matrix.m[3][0],
4247             matrix.m[3][1],
4248             matrix.m[3][2]);
4249
4250       matrix.m[3][0] = 0;
4251       matrix.m[3][1] = 0;
4252       matrix.m[3][2] = 0;
4253
4254       glMultMatrixd(matrix.array);
4255    }
4256 #endif
4257 }
4258
4259 public void UseSingleGLContext(bool useSingle)
4260 {
4261    useSingleGLContext = useSingle;
4262 }
4263
4264 default dllexport void *
4265 #if defined(__WIN32__)
4266 __attribute__((stdcall))
4267 #endif
4268 IS_GLGetContext(DisplaySystem displaySystem)
4269 {
4270    if(displaySystem)
4271    {
4272 #if defined(__WIN32__)
4273       OGLSystem system = displaySystem.driverData;
4274       return system.glrc;
4275 #elif defined(__ANDROID__)
4276       return eglContext;
4277 #elif defined(__EMSCRIPTEN__)
4278 #else
4279       OGLSystem system = displaySystem.driverData;
4280       return system.glContext;
4281 #endif
4282    }
4283    return null;
4284 }
4285
4286 #endif