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