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