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