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