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