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