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