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