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