ecere/gfx/drivers/OpenGL: Added GLSetupLighting API
[sdk] / ecere / src / gfx / drivers / OpenGLDisplayDriver.ec
1 namespace gfx::drivers;
2
3 #if defined(_GLES)
4 #define ES1_1
5 #else
6 // #define SHADERS
7 #endif
8
9 #define GL_BGRA_EXT  0x80E1
10
11 #if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__)
12 #  if defined(SHADERS)
13 #     include "gl_core_3_3.h"
14 #  else
15 #     include "gl_compat_4_4.h"
16 #  endif
17 #endif
18
19 import "glab"
20 import "immediate"
21 import "matrixStack"
22 import "shading"
23
24 #ifdef SHADERS
25
26 #undef glEnableClientState
27 #undef glDisableClientState
28 #undef GL_VERTEX_ARRAY
29 #undef GL_NORMAL_ARRAY
30 #undef GL_TEXTURE_COORD_ARRAY
31 #undef GL_COLOR_ARRAY
32
33 #define glEnableClientState      glEnableVertexAttribArray
34 #define glDisableClientState     glDisableVertexAttribArray
35 #define GL_VERTEX_ARRAY          GLBufferContents::vertex
36 #define GL_NORMAL_ARRAY          GLBufferContents::normal
37 #define GL_TEXTURE_COORD_ARRAY   GLBufferContents::texCoord
38 #define GL_COLOR_ARRAY           GLBufferContents::color
39
40 #endif
41
42 // We were using PBUFFER for alpha compositing on Linux before, but it does not seem to work, nor be required anymore.
43 // #define USEPBUFFER
44 #if defined(__unix__) || defined(__APPLE__)
45
46 #if !defined(__MINGW32__)
47    #define GL_GLEXT_PROTOTYPES
48 #endif
49
50 #define pointer _pointer
51
52
53    #if !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
54
55       #define property _property
56       #define new _new
57       #define class _class
58
59       #define Window    X11Window
60       #define Cursor    X11Cursor
61       #define Font      X11Font
62       #define Display   X11Display
63       #define Time      X11Time
64       #define KeyCode   X11KeyCode
65       #define Picture   X11Picture
66       #define Glyph     X11Glyph
67       #define uint _uint
68
69       #include <X11/Xlib.h>
70       #include <X11/Xutil.h>
71       #include <GL/glx.h>
72       #include <X11/extensions/XShm.h>
73       #include <sys/ipc.h>
74       #include <sys/shm.h>
75       #include <X11/extensions/Xrender.h>
76       #include <X11/extensions/shape.h>
77
78       #undef Window
79       #undef Cursor
80       #undef Font
81       #undef Display
82       #undef Time
83       #undef KeyCode
84       #undef Picture
85       #undef Glyph
86       #undef uint
87       #undef new
88       #undef property
89       #undef class
90
91    #endif
92
93 #endif
94
95 #if defined(__APPLE__)
96 #include <OpenGl/gl.h>
97 #endif
98
99 #if defined(__WIN32__) || defined(__unix__) || defined(__APPLE__)
100
101 #if defined(__WIN32__)
102    //#define WIN32_LEAN_AND_MEAN
103    #undef _WIN32_WINNT
104    #define _WIN32_WINNT 0x0502
105    #define String Sting_
106    #include <windows.h>
107    #undef String
108 #endif
109
110 #if defined(__ANDROID__) || defined(__ODROID__)
111
112 #define uint _uint
113 #define property _property
114 #define new _new
115 #define class _class
116 #define Window    X11Window
117 #define Cursor    X11Cursor
118 #define Font      X11Font
119 #define Display   X11Display
120 #define Time      X11Time
121 #define KeyCode   X11KeyCode
122 #define Picture   X11Picture
123 #define Bool      X11Bool
124
125    #include <GLES/gl.h>
126
127 #undef Bool
128 #undef Picture
129 #undef Window
130 #undef Cursor
131 #undef Font
132 #undef Display
133 #undef Time
134 #undef KeyCode
135 #undef uint
136 #undef new
137 #undef property
138 #undef class
139
140 #elif defined(__EMSCRIPTEN__)
141
142    #define property _property
143    #define uint _uint
144
145    #include <GL/gl.h>
146
147    //#include <GLES/gl.h>
148    //#include <EGL/egl.h>
149
150    //#include <GLES2/gl.h>
151    //#include <EGL/egl.h>
152
153    //#include <GLES2/gl2.h>
154    #include <GL/glfw.h>
155    #include <emscripten/emscripten.h>
156
157    #undef property
158    #undef uint
159
160 #else
161    #include <GL/gl.h>
162 #endif
163
164 #if defined(__ODROID__) && !defined(ES1_1)
165 #define ES1_1
166 #endif
167
168 #if defined(__EMSCRIPTEN__)
169 #define EM_MODE
170 // #define ES1_1
171 #endif
172
173 #undef pointer
174
175 import "Display"
176
177 #if defined(__unix__) || defined(__APPLE__)
178
179    #if !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
180    import "XInterface"
181    #endif
182
183 #endif
184
185 #define glLoadMatrix glLoadMatrixd
186 #define glMultMatrix glMultMatrixd
187 #define glGetMatrix  glGetDoublev
188 #define glTranslate glTranslated
189 #define glScale glScaled
190
191 /*
192 #define glVertex3v glVertex3dv
193 #define glNormal3v glNormal3dv
194 */
195
196 /*
197 //#ifdef VERTEX_FORMAT_DOUBLE
198
199 #define glLoadMatrix glLoadMatrixd
200 #define glMultMatrix glMultMatrixd
201 #define glGetMatrix  glGetDoublev
202 #define glVertex3v glVertex3dv
203 #define glNormal3v glNormal3dv
204 #define glTranslate glTranslated
205 #define glScale glScaled
206 //#define GL_VERTEX_FORMAT   GL_DOUBLE
207
208 #else
209
210 #define glLoadMatrix glLoadMatrixf
211 #define glMultMatrix glMultMatrixf
212 #define glGetMatrix  glGetFloatv
213 #define glVertex3v glVertex3fv
214 #define glNormal3v glNormal3fv
215 #define glTranslate glTranslatef
216 #define glScale glScalef
217 //#define GL_VERTEX_FORMAT   GL_FLOAT
218
219 #endif
220 */
221
222 #define GL_ARRAY_BUFFER_ARB            0x8892
223 #define GL_ELEMENT_ARRAY_BUFFER_ARB    0x8893
224 #define GL_STATIC_DRAW_ARB             0x88E4
225 #define GL_LIGHT_MODEL_COLOR_CONTROL   0x81F8
226 #define GL_SEPARATE_SPECULAR_COLOR     0x81FA
227
228 #define GL_MULTISAMPLE_ARB             0x809D
229
230 #if defined(__WIN32__)
231    #include "wglDefs.h"
232
233    typedef void (APIENTRY * PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count);
234    typedef void (APIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void);
235
236    static PFNGLLOCKARRAYSEXTPROC glLockArraysEXT = null;
237    static PFNGLUNLOCKARRAYSEXTPROC glUnlockArraysEXT = null;
238
239    static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = null;
240    static PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = null;
241    static PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB = null;
242    static PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB = null;
243    static PFNWGLQUERYPBUFFERARBPROC wglQueryPbufferARB = null;
244    static PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB = null;
245    static PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB = null;
246    static PFNWGLBINDTEXIMAGEARBPROC wglBindTexImageARB = null;
247    static PFNWGLRELEASETEXIMAGEARBPROC wglReleaseTexImageARB = null;
248    static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = null;
249    static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = null;
250
251 #elif defined(__ANDROID__) || defined(__ODROID__)
252
253    #define GL_FRAMEBUFFER           GL_FRAMEBUFFER_OES
254    #define GL_RENDERBUFFER          GL_RENDERBUFFER_OES
255    #define GL_COLOR_ATTACHMENT0     GL_COLOR_ATTACHMENT0_OES
256
257    #define GL_POLYGON_STIPPLE 0xFFFF
258    #define GL_LINE_STIPPLE 0xFFFF
259    #define GL_LINE 0xFFFF
260    #define GL_FILL 0xFFFF
261    #define GL_ALL_ATTRIB_BITS 0xFFFF
262    #define GL_LIGHT_MODEL_LOCAL_VIEWER 0xFFFF
263
264    #define GL_POLYGON      9
265    #define GL_QUADS        7
266
267    //#define GL_QUADS              0
268    #define GL_QUAD_STRIP         0
269    //#define GL_DOUBLE             0
270    //#define GL_UNSIGNED_INT       0
271    //#define GL_FILL               0
272    //#define GL_LINE               0
273    //#define GL_LINE_STIPPLE       0
274    #define GL_BGRA_EXT           0
275    #define GL_UNPACK_ROW_LENGTH  0
276    #define GL_UNPACK_SKIP_PIXELS 0
277    #define GL_UNPACK_SKIP_ROWS   0
278    #define GL_RGBA8              0
279    #define GL_PACK_ROW_LENGTH    0
280    #define GL_PACK_SKIP_ROWS     0
281    #define GL_PACK_SKIP_PIXELS   0
282
283 #endif
284
285
286 #if defined(__ANDROID__) || defined(__ODROID__)
287    #define glBindFramebuffer        glBindFramebufferOES
288    #define glBindRenderbuffer       glBindRenderbufferOES
289    #define glFramebufferTexture2D   glFramebufferTexture2DOES
290    #define glGenFramebuffers        glGenFramebuffersOES
291    #define glGenRenderbuffers       glGenRenderbuffersOES
292    #define glDeleteFramebuffers     glDeleteFramebuffersOES
293    #define glDeleteRenderbuffers    glDeleteRenderbuffersOES
294
295    #define GL_INT                                  0x1404
296    #define GL_UNSIGNED_INT                         0x1405
297    #define GL_DOUBLE                               0x140A
298    #define APIENTRY
299 #endif
300
301 #if defined(ES1_1) || defined(SHADERS)
302
303    #undef glRecti
304    #undef glBegin
305    #undef glTexCoord2i
306    #undef glVertex2i
307    #undef glTexCoord2d
308    #undef glVertex2d
309    #undef glTexCoord2f
310    #undef glVertex2f
311    #undef glEnd
312    #undef glColor3f
313    #undef glColor4ub
314    #undef glColor4fv
315    #undef glNormal3fv
316    #undef glNormal3f
317    #undef glTexCoord2fv
318    #undef glVertex3d
319    #undef glVertex3dv
320    #undef glVertex3f
321    #undef glVertex3fv
322
323    #undef glLoadMatrixd
324    #undef glMultMatrixd
325    #undef glFrustum
326    #undef glOrtho
327    #undef glScaled
328    #undef glScalef
329    #undef glTranslated
330    #undef glRotated
331    #undef glMatrixMode
332    #undef glLoadIdentity
333    #undef glPushMatrix
334    #undef glPopMatrix
335
336    #undef glLineStipple
337    #undef glColorMaterial
338    #undef glLightModeli
339
340    #define glRecti               glimtkRecti
341    #define glBegin               glimtkBegin
342    #define glTexCoord2i          glimtkTexCoord2i
343    #define glVertex2i            glimtkVertex2i
344    #define glTexCoord2d          glimtkTexCoord2d
345    #define glVertex2d            glimtkVertex2d
346    #define glTexCoord2f          glimtkTexCoord2f
347    #define glVertex2f            glimtkVertex2f
348    #define glEnd                 glimtkEnd
349    #define glColor3f             glimtkColor3f
350    #define glColor4ub            glimtkColor4ub
351    #define glColor4fv            glimtkColor4fv
352    #define glNormal3fv           glimtkNormal3fv
353    #define glNormal3f            glimtkNormal3f
354    #define glTexCoord2fv         glimtkTexCoord2fv
355    #define glVertex3d            glimtkVertex3d
356    #define glVertex3dv           glimtkVertex3dv
357    #define glVertex3f            glimtkVertex3f
358    #define glVertex3fv           glimtkVertex3fv
359
360    #define glLoadMatrixd         glmsLoadMatrixd
361    #define glMultMatrixd         glmsMultMatrixd
362    #define glFrustum             glmsFrustum
363    #define glOrtho               glmsOrtho
364    #define glScaled              glmsScaled
365    #define glScalef              glmsScaled
366    #define glTranslated          glmsTranslated
367    #define glRotated             glmsRotated
368    #define glMatrixMode          glmsMatrixMode
369    #define glLoadIdentity        glmsLoadIdentity
370    #define glPushMatrix          glmsPushMatrix
371    #define glPopMatrix           glmsPopMatrix
372
373    #define glLineStipple         glesLineStipple
374    #define glColorMaterial       glesColorMaterial
375    #define glLightModeli         glesLightModeli
376
377 #endif
378
379 public void glesColorMaterial(int a, int b)
380 {
381    PrintLn("glColorMaterial stub");
382 }
383
384 static GLuint stippleTexture;
385 #if defined(ES1_1) || defined(SHADERS) || defined(EM_MODE)
386 static bool stippleEnabled;
387 #endif
388
389 public void glesLineStipple( int i, unsigned short j )
390 {
391    uint texture[1*16];
392    int x;
393    for(x = 0; x < 16; x++)
394    {
395       bool v = (j & (1 << x)) != 0;
396       texture[x] = v ? 0xFFFFFFFF : 0;
397    }
398    if(!stippleTexture)
399       glGenTextures(1, &stippleTexture);
400    glBindTexture(GL_TEXTURE_2D, stippleTexture);
401    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
402
403    // TOOD: Special shading code for stippling?
404    GLSetupTexturing(true);
405    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
406    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
407    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
408    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
409    glMatrixMode(GL_TEXTURE);
410    glLoadIdentity();
411    //glTranslated(1.0/backAttrib->texW/2.0f, 1.0/backAttrib->texH/2.0f, 0.0f);
412    glScaled(i/16.0, 1, 1.0f);
413    glTranslated(0.5, 0.5, 0);
414    glMatrixMode(MatrixMode::projection);
415 }
416
417 public void glesLightModeli( unsigned int pname, int param )
418 {
419 #if !defined(EM_MODE) && !defined(SHADERS)
420    if(pname == GL_LIGHT_MODEL_TWO_SIDE)
421       glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, param);
422 #endif
423 }
424
425 #if defined(__ANDROID__) || defined(__ODROID__)
426 void glClearDepth( double depth ) { glClearDepthf((float)depth); }
427 void glFogi( unsigned int pname, int param ) { }
428 void glPolygonMode( unsigned int i, unsigned int j ) { }
429
430
431 // *** Picking won't be supported for now ***
432 void glPushName( unsigned int i ) { }
433 void glLoadName( unsigned int i ) { }
434 void glPopName() { }
435
436 // Probably replace by regular glBlendFunc ...
437 void glBlendFuncSeparate(int a, int b, int c, int d)
438 {
439    glBlendFunc(a, b);
440 }
441
442 // For direct pixel blitting...
443 void glRasterPos2d(double a, double b) { }
444 void glPixelZoom(float a, float b) { }
445 void glDrawPixels(int a, int b, int c, int d, void * e) { }
446
447 #endif
448
449 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
450 static int primitiveTypes[RenderPrimitiveType] =
451 {
452    GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GLIMTKMode::quads, GLIMTKMode::quadStrip, GL_LINE_STRIP
453 };
454 #endif
455
456 public void GLSetupTexturing(bool enable)
457 {
458 #ifdef SHADERS
459    shader_texturing(enable);
460 #else
461    (enable ? glEnable : glDisable)(GL_TEXTURE_2D);
462 #endif
463 }
464
465 public void GLSetupLighting(bool enable)
466 {
467 #if defined(SHADERS)
468    shader_lighting(enable);
469 #elif !defined(EM_MODE)
470    (enable ? glEnable : glDisable)(GL_LIGHTING);
471 #endif
472 }
473
474 // Non OpenGL ES friendly stuff
475
476 #if defined(ES1_1)
477
478 //#undef GL_UNSIGNED_INT
479 //#undef GL_DOUBLE
480 #undef GL_INT
481 //#undef GL_POLYGON
482 //#undef GL_QUADS
483 #undef GL_QUAD_STRIP
484 #undef GL_POLYGON_STIPPLE
485 #undef GL_LINE_STIPPLE
486 #undef GL_LINE
487 #undef GL_FILL
488 #undef GL_ALL_ATTRIB_BITS
489 #undef GL_LIGHT_MODEL_LOCAL_VIEWER
490
491 #endif
492
493 static int displayWidth, displayHeight;
494
495 #define GL_CLAMP_TO_EDGE 0x812F
496
497 static bool vboAvailable;
498
499 static bool useSingleGLContext = false;
500 class OGLDisplay : struct
501 {
502 #if defined(__WIN32__)
503    HDC hdc;
504    HGLRC glrc;
505
506    HBITMAP memBitmap;
507    HDC memDC;
508    byte * picture;
509    uint stride;
510    void * pBuffer;
511    /*
512    int imageBuffers[2];
513    byte * pboMemory1, * pboMemory2;
514    */
515 #elif !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
516    GLXContext glContext;
517
518    Pixmap pixmap;
519    XShmSegmentInfo shminfo;
520    XImage * image;
521    XShmSegmentInfo shminfoShape;
522    XImage * shapeImage;
523    byte * picture;
524    uint stride;
525    GLXPbuffer pBuffer;
526    X11Picture windowPicture;
527    X11Picture pixmapPicture;
528    Pixmap shapePixmap;
529    X11Picture shapePicture;
530 #endif
531
532    ColorAlpha * flippingBuffer;
533    int flipBufH, flipBufW;
534    bool depthWrite;
535    int x, y;
536 };
537
538 #ifdef _DEBUG
539 static void APIENTRY openglCallbackFunction(GLenum source,
540                                            GLenum type,
541                                            GLuint id,
542                                            GLenum severity,
543                                            GLsizei length,
544                                            const GLchar* message,
545                                            const void* userParam)
546 {
547    PrintLn("---------------------opengl-callback-start------------");
548    PrintLn("message: ", message);
549    PrintLn("type: ");
550    switch (type)
551    {
552       case GL_DEBUG_TYPE_ERROR: PrintLn("ERROR"); break;
553       case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: PrintLn("DEPRECATED_BEHAVIOR"); break;
554       case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: PrintLn("UNDEFINED_BEHAVIOR"); break;
555       case GL_DEBUG_TYPE_PORTABILITY: PrintLn("PORTABILITY"); break;
556       case GL_DEBUG_TYPE_PERFORMANCE: PrintLn("PERFORMANCE"); break;
557       case GL_DEBUG_TYPE_OTHER: PrintLn("OTHER"); break;
558    }
559
560    PrintLn("id: ", id);
561    Print("severity: ");
562    switch (severity)
563    {
564       case GL_DEBUG_SEVERITY_LOW: PrintLn("LOW"); break;
565       case GL_DEBUG_SEVERITY_MEDIUM: PrintLn("MEDIUM"); break;
566       case GL_DEBUG_SEVERITY_HIGH: PrintLn("HIGH"); break;
567    }
568    PrintLn("---------------------opengl-callback-end--------------");
569 }
570 #endif
571
572 class OGLSystem : struct
573 {
574    int maxTextureSize;
575    bool loadingFont;
576    bool pow2textures;
577 #if defined(__WIN32__)
578    PIXELFORMATDESCRIPTOR pfd;
579    int format;
580    HDC hdc;
581    HGLRC glrc;
582    HWND hwnd;
583 #elif !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
584    XVisualInfo * visualInfo;
585    GLXContext glContext;
586    GLXDrawable glxDrawable;
587 #endif
588 };
589
590 class OGLSurface : struct
591 {
592    Font font;
593    bool opaqueText;
594    int xOffset;
595    bool writingText;
596    bool writingOutline;
597
598    float foreground[4], background[4], bitmapMult[4];
599 } OGLSurface;
600
601 class OGLMesh : struct
602 {
603    GLAB vertices;
604    GLAB normals;
605    GLAB texCoords;
606    GLAB texCoords2;
607    GLAB colors;
608 };
609
610 class OGLIndices : struct
611 {
612    uint16 * indices;
613    GLEAB buffer;
614    uint nIndices;
615 };
616
617 int current;
618 void * previous;
619
620 static void setupDebugging()
621 {
622 #ifdef _DEBUG
623    if(glDebugMessageCallback)
624    {
625       GLuint unusedIds = 0;
626
627       glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
628       glDebugMessageCallback(openglCallbackFunction, null);
629       glDebugMessageControl(GL_DONT_CARE,
630           GL_DONT_CARE,
631           GL_DONT_CARE,
632           0,
633           &unusedIds,
634           GL_TRUE);
635    }
636 #endif
637 }
638
639 #if defined(__WIN32__)
640 static HGLRC winCreateContext(HDC hdc)
641 {
642    if(wglCreateContextAttribsARB)
643    {
644       int attribs[] =
645       {
646          WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
647          WGL_CONTEXT_MINOR_VERSION_ARB, 4,
648          WGL_CONTEXT_FLAGS_ARB, /*WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB | */WGL_CONTEXT_DEBUG_BIT_ARB,
649          WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB /*WGL_CONTEXT_CORE_PROFILE_BIT_ARB*/,
650          0,0
651       };
652       return wglCreateContextAttribsARB(hdc, null, attribs);
653    }
654    else
655       return wglCreateContext(hdc);
656 }
657 #endif
658
659 class OpenGLDisplayDriver : DisplayDriver
660 {
661    class_property(name) = "OpenGL";
662
663    bool LockSystem(DisplaySystem displaySystem)
664    {
665 #if !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
666       OGLSystem oglSystem = displaySystem.driverData;
667       if(useSingleGLContext) return true;
668    #if defined(__WIN32__)
669       wglMakeCurrent(oglSystem.hdc, oglSystem.glrc);
670    #elif defined(__unix__) || defined(__APPLE__)
671       //if(previous) return true;
672       // printf("Making SYSTEM current\n");
673       glXMakeCurrent(xGlobalDisplay, (GLXDrawable)oglSystem.glxDrawable, oglSystem.glContext);
674       //previous = oglSystem.glContext;
675    #endif
676 #endif
677       GLABBindBuffer(GL_ARRAY_BUFFER, 0);
678       GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
679       return true;
680    }
681
682    void UnlockSystem(DisplaySystem displaySystem)
683    {
684       if(useSingleGLContext) return;
685    #if defined(__WIN32__)
686       wglMakeCurrent(null, null);
687    #elif defined(__unix__) || defined(__APPLE__)
688       // printf("Making NULL current\n");
689       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
690       #else
691       glXMakeCurrent(xGlobalDisplay, None, null);
692       #endif
693       // previous = null;
694    #endif
695    }
696
697    bool Lock(Display display)
698    {
699 #if !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
700       OGLDisplay oglDisplay = display.driverData;
701       if(useSingleGLContext) return true;
702    #if defined(__WIN32__)
703       wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
704    #elif defined(__unix__) || defined(__APPLE__)
705       // if(previous) glXMakeCurrent(xGlobalDisplay, None, null);
706       // printf("   Making DISPLAY current\n");
707       glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext);
708    #endif
709 #endif
710       GLABBindBuffer(GL_ARRAY_BUFFER, 0);
711       GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
712       return true;
713    }
714
715    void Unlock(Display display)
716    {
717       if(useSingleGLContext) return;
718       //printf("   Making NULL current\n");
719       //glXMakeCurrent(xGlobalDisplay, None, null);
720       // if(previous)
721          LockSystem(display.displaySystem);
722    }
723
724    void DestroyDisplay(Display display)
725    {
726       OGLDisplay oglDisplay = display.driverData;
727
728       if(oglDisplay)
729       {
730    #if defined(__WIN32__)
731          wglMakeCurrent( null, null );
732
733          if(oglDisplay.glrc)
734             wglDeleteContext(oglDisplay.glrc);
735
736          if(oglDisplay.hdc && oglDisplay.pBuffer)
737             wglReleasePbufferDCARB(oglDisplay.pBuffer, oglDisplay.hdc);
738
739          if(oglDisplay.pBuffer)
740             wglDestroyPbufferARB(oglDisplay.pBuffer);
741
742          if(oglDisplay.hdc)
743             ReleaseDC(display.window, oglDisplay.hdc);
744
745          if(oglDisplay.memDC) DeleteDC(oglDisplay.memDC);
746          if(oglDisplay.memBitmap) DeleteObject(oglDisplay.memBitmap);
747
748    #elif defined(__unix__) || defined(__APPLE__)
749       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
750       #else
751          if(oglDisplay.shapePixmap)
752             XFreePixmap(xGlobalDisplay, oglDisplay.shapePixmap);
753          if(oglDisplay.pixmap)
754             XFreePixmap(xGlobalDisplay, oglDisplay.pixmap);
755          if(oglDisplay.image)
756          {
757             if(oglDisplay.shminfoShape.shmid != -1)
758             {
759                XShmDetach(xGlobalDisplay, &oglDisplay.shminfo);
760                if(oglDisplay.shminfo.shmaddr != (void *)-1)
761                   shmdt(oglDisplay.shminfo.shmaddr);
762                shmctl(oglDisplay.shminfo.shmid, IPC_RMID, 0);
763             }
764          }
765          if(oglDisplay.shapeImage)
766          {
767             if(oglDisplay.shminfoShape.shmid != -1)
768             {
769                XShmDetach(xGlobalDisplay, &oglDisplay.shminfoShape);
770                if(oglDisplay.shminfoShape.shmaddr != (void *)-1)
771                   shmdt(oglDisplay.shminfoShape.shmaddr);
772                shmctl(oglDisplay.shminfoShape.shmid, IPC_RMID, 0);
773             }
774             XDestroyImage(oglDisplay.shapeImage);
775             oglDisplay.shapeImage = None;
776          }
777
778          glXMakeCurrent(xGlobalDisplay, None, null);
779
780          if(oglDisplay.glContext)
781             glXDestroyContext(xGlobalDisplay, oglDisplay.glContext);
782       #endif
783    #endif
784          delete oglDisplay.flippingBuffer;
785          delete oglDisplay;
786          display.driverData = null;
787       }
788    }
789
790    void ::CheckExtensions(OGLSystem oglSystem)
791    {
792       const char * extensions = (const char *)glGetString(GL_EXTENSIONS);
793       if(extensions)
794          oglSystem.pow2textures = strstr(extensions, "GL_ARB_texture_non_power_of_two") ? false : true;
795       glGetIntegerv(GL_MAX_TEXTURE_SIZE, &oglSystem.maxTextureSize);
796    }
797
798    bool CreateDisplaySystem(DisplaySystem displaySystem)
799    {
800       bool result = false;
801       OGLSystem oglSystem = displaySystem.driverData = OGLSystem { };
802
803    #ifdef __WIN32__
804       oglSystem.hwnd = CreateWindow("static", null, 0,0,0,0,0,null,null,null,null);
805
806       oglSystem.hdc = GetDC(oglSystem.hwnd);
807       if(oglSystem.hdc)
808       {
809
810          oglSystem.pfd.nSize = (short)sizeof(oglSystem.pfd);
811          oglSystem.pfd.nVersion = 1;
812          oglSystem.pfd.dwFlags = PFD_DRAW_TO_WINDOW /*PFD_DRAW_TO_BITMAP*/ | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
813          oglSystem.pfd.iPixelType = PFD_TYPE_RGBA;
814          oglSystem.pfd.cColorBits = 24;
815          oglSystem.pfd.cAlphaBits = 8;
816          oglSystem.pfd.cDepthBits = 24;
817          oglSystem.pfd.iLayerType = PFD_MAIN_PLANE;
818
819          oglSystem.format = ChoosePixelFormat(oglSystem.hdc, &oglSystem.pfd);
820          DescribePixelFormat(oglSystem.hdc, oglSystem.format, sizeof(oglSystem.pfd), &oglSystem.pfd);
821
822          if(oglSystem.pfd.cColorBits > 8)
823          {
824             SetPixelFormat(oglSystem.hdc, oglSystem.format, &oglSystem.pfd);
825             oglSystem.glrc = wglCreateContext(oglSystem.hdc);
826             if(oglSystem.glrc)
827             {
828                wglMakeCurrent(oglSystem.hdc, oglSystem.glrc);
829
830                wglChoosePixelFormatARB = (void *) wglGetProcAddress("wglChoosePixelFormatARB");
831                wglGetExtensionsStringARB = (void *)wglGetProcAddress("wglGetExtensionsStringARB");
832                wglCreatePbufferARB = (void *)wglGetProcAddress("wglCreatePbufferARB");
833                wglGetPbufferDCARB = (void *)wglGetProcAddress("wglGetPbufferDCARB");
834                wglQueryPbufferARB = (void *)wglGetProcAddress("wglQueryPbufferARB");
835                wglDestroyPbufferARB = (void *)wglGetProcAddress("wglDestroyPbufferARB");
836                wglReleasePbufferDCARB = (void *)wglGetProcAddress("wglReleasePbufferDCARB");
837                wglBindTexImageARB = (void *)wglGetProcAddress("wglBindTexImageARB");
838                wglReleaseTexImageARB = (void *)wglGetProcAddress("wglReleaseTexImageARB");
839                wglSwapIntervalEXT = (void *)wglGetProcAddress("wglSwapIntervalEXT");
840                wglCreateContextAttribsARB = (void *)wglGetProcAddress("wglCreateContextAttribsARB");
841
842                glLockArraysEXT = (void *) wglGetProcAddress("glLockArraysEXT" );
843                glUnlockArraysEXT = (void *) wglGetProcAddress("glUnlockArraysEXT");
844
845                // eSystem_LoggingMode(LOG_MSGBOX, null);
846
847                if(wglChoosePixelFormatARB)
848                {
849                   int pixelFormat;
850                   int valid;
851                   int numFormats;
852                   float fAttributes[] = {0,0};
853                   int iAttributes[] =
854                   {
855                      WGL_DRAW_TO_WINDOW_ARB,GL_TRUE,
856                      WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
857                      WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
858                      WGL_COLOR_BITS_ARB,24,
859                      WGL_ALPHA_BITS_ARB,8,
860                      WGL_DEPTH_BITS_ARB,16,
861                      WGL_STENCIL_BITS_ARB,0,
862                      WGL_DOUBLE_BUFFER_ARB,GL_TRUE,
863                      WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
864                      WGL_SAMPLES_ARB, 4,                  // Check For 4x Multisampling
865                      0,0
866                   };
867
868                   //Log("Found wglChoosePixelFormatARB\n");
869
870                   valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
871                   if(!valid || !numFormats)
872                   {
873                      //Log("Can't find 4x multi sampling\n");
874                      iAttributes[19] = 2;
875                      valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
876                      if(!valid || !numFormats)
877                      {
878                         // Log("Can't find 2x multi sampling\n");
879                         iAttributes[16] = 0;
880                         iAttributes[17] = 0;
881                         valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
882                      }
883                   }
884                   if(valid && numFormats)
885                   {
886                      oglSystem.format = pixelFormat;
887                      wglMakeCurrent(null, null);
888                      wglDeleteContext(oglSystem.glrc);
889
890                      // *** DescribePixelFormat does not support WGL pixel formats! ***
891                      //DescribePixelFormat(oglSystem.hdc, oglSystem.format, sizeof(oglSystem.pfd), &oglSystem.pfd);
892                      SetPixelFormat(oglSystem.hdc, oglSystem.format, &oglSystem.pfd);
893                      //Log("Successfully set pixel format\n");
894
895                      oglSystem.glrc = winCreateContext(oglSystem.hdc);
896                      wglMakeCurrent(oglSystem.hdc, oglSystem.glrc);
897                   }
898                }
899                /*else
900                   eSystem_Logf("Can't find wglChoosePixelFormatARB\n");*/
901
902                result = true;
903
904                wglMakeCurrent(null, null);
905
906                //eSystem_DumpErrors(true);
907             }
908          }
909       }
910    #elif defined(__unix__) || defined(__APPLE__)
911       vboAvailable = true;
912       #if defined(__ANDROID__)
913          egl_init_display(guiApp.desktop.windowHandle);
914       #elif defined(__ODROID__)
915          egl_init_display((uint)displaySystem.window);
916          CheckExtensions(oglSystem);
917          result = true;
918       #elif defined(__EMSCRIPTEN__)
919          if(glfwInit() == GL_TRUE)
920          {
921             const int width = 640, height = 480;
922             if(glfwOpenWindow(width, height, 8, 8, 8, 8, 16, 0, GLFW_WINDOW) == GL_TRUE)
923             {
924                //glfwSwapBuffers();
925                result = true;
926             }
927             else
928                printf("glfwOpenWindow() failed\n"); //glfwTerminate();
929          }
930          else
931             printf("glfwInit() failed\n"); //glfwTerminate();
932       #else
933       {
934          X11Window root = RootWindow( xGlobalDisplay, DefaultScreen( xGlobalDisplay ) );
935          XSetWindowAttributes attr;
936          unsigned long mask;
937
938          int attrList[] =
939          {
940       #ifndef ECERE_MINIGLX
941             GLX_USE_GL, GLX_DEPTH_SIZE, 1,
942       #endif
943             GLX_RGBA,
944             GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
945             GLX_DOUBLEBUFFER,
946             None
947          };
948          oglSystem.visualInfo = glXChooseVisual( xGlobalDisplay,  DefaultScreen( xGlobalDisplay ), attrList );
949          attr.background_pixel = 0;
950          attr.border_pixel = 0;
951          attr.colormap = XCreateColormap( xGlobalDisplay, root, oglSystem.visualInfo->visual, AllocNone);
952          attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
953          mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
954
955          oglSystem.glxDrawable = XCreateWindow( xGlobalDisplay, root, 0, 0, 1, 1, 0, oglSystem.visualInfo->depth, InputOutput,
956             oglSystem.visualInfo->visual, mask, &attr );
957       }
958       if(oglSystem.visualInfo)
959       {
960          oglSystem.glContext = glXCreateContext(xGlobalDisplay, oglSystem.visualInfo, null, True);
961          if(oglSystem.glContext)
962          {
963             glXMakeCurrent(xGlobalDisplay, oglSystem.glxDrawable, oglSystem.glContext);
964             // Setup Extensions
965             CheckExtensions(oglSystem);
966             glXMakeCurrent(xGlobalDisplay, None, null);
967             result = true;
968          }
969       }
970       #endif
971    #endif
972
973       displaySystem.flags.alpha = true;
974       displaySystem.flags.flipping = true;
975       displaySystem.pixelFormat = pixelFormat888;
976       return result;
977    }
978
979    void DestroyDisplaySystem(DisplaySystem displaySystem)
980    {
981       OGLSystem oglSystem = displaySystem.driverData;
982
983    #if defined(__WIN32__)
984       wglMakeCurrent( null, null );
985
986       if(oglSystem.glrc)
987          wglDeleteContext(oglSystem.glrc);
988
989       if(oglSystem.hdc)
990          ReleaseDC(oglSystem.hwnd, oglSystem.hdc);
991       DestroyWindow(oglSystem.hwnd);
992
993    #elif defined(__unix__) || defined(__APPLE__)
994       #if defined(__ANDROID__) || defined(__ODROID__)
995          egl_term_display();
996       #elif defined(__EMSCRIPTEN__)
997          glfwTerminate();
998       #else
999       if(oglSystem.visualInfo)
1000       {
1001    #ifdef   ECERE_MINIGLX
1002          __miniglx_XFree(oglSystem.visualInfo);
1003    #else
1004          XFree(oglSystem.visualInfo);
1005    #endif
1006       }
1007
1008       if(oglSystem.glxDrawable)
1009       {
1010          XDestroyWindow(xGlobalDisplay, oglSystem.glxDrawable);
1011          oglSystem.glxDrawable = 0;
1012       }
1013       #endif
1014    #endif
1015       delete oglSystem;
1016    }
1017
1018    static bool ::initialDisplaySetup(Display display)
1019    {
1020       bool result = true;
1021       #ifdef SHADERS
1022       loadShaders("<:ecere>shaders/fixed.vertex", "<:ecere>shaders/fixed.frag");
1023       #endif
1024       glEnableClientState(GL_VERTEX_ARRAY);
1025
1026       GLABBindBuffer(GL_ARRAY_BUFFER, 0);
1027       GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1028
1029 #if defined(__WIN32__)
1030       if(glBlendFuncSeparate)
1031          glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1032       else
1033          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1034 #else
1035       glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
1036 #endif
1037       glEnable(GL_BLEND);
1038
1039       glMatrixMode(MatrixMode::modelView);
1040       glLoadIdentity(); // For setting up GLES stack
1041       glScaled(1.0, 1.0, -1.0);
1042       // glTranslatef(0.375f, 0.375f, 0.0f);
1043       // glTranslatef(-0.625f, -0.625f, 0.0f);
1044       glMatrixMode(MatrixMode::projection);
1045 #if !defined(EM_MODE) && !defined(SHADERS)
1046       glShadeModel(GL_FLAT);
1047
1048       // #define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
1049
1050       // glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1051
1052       glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1053       glFogi(GL_FOG_MODE, GL_EXP);
1054       glFogf(GL_FOG_DENSITY, 0);
1055       glEnable(GL_NORMALIZE);
1056 #endif
1057       glDepthFunc(GL_LESS);
1058       glClearDepth(1.0);
1059       glDisable(GL_MULTISAMPLE_ARB);
1060 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
1061       display.ambient = Color { 50,50,50 };
1062 #endif
1063       return result;
1064    }
1065
1066    bool CreateDisplay(Display display)
1067    {
1068       bool result = false;
1069       OGLDisplay oglDisplay = display.driverData;
1070 #if !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
1071       OGLSystem oglSystem = display.displaySystem.driverData;
1072 #endif
1073
1074       if(!oglDisplay)
1075          oglDisplay = display.driverData = OGLDisplay { };
1076       //printf("Inside CreateDisplay\n");
1077
1078 #if defined(__WIN32__) || defined(USEPBUFFER)
1079       if(!display.alphaBlend)
1080 #endif
1081       {
1082    #if defined(__WIN32__)
1083          oglDisplay.hdc = GetDC(display.window);
1084          SetPixelFormat(oglDisplay.hdc, oglSystem.format, &oglSystem.pfd);
1085          if((oglDisplay.glrc = winCreateContext(oglDisplay.hdc)))
1086          {
1087             wglShareLists(oglSystem.glrc, oglDisplay.glrc);
1088             wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
1089             result = true;
1090          }
1091          else
1092             ReleaseDC(display.window, oglDisplay.hdc);
1093    #elif defined(__unix__) || defined(__APPLE__)
1094       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
1095       #else
1096          XVisualInfo * visualInfo = ((XWindowData)display.windowDriverData).visual;
1097          /*
1098 #if defined(__APPLE__)
1099          XVisualInfo template = { 0 };
1100          XWindowAttributes winAttr;
1101          int n;
1102          XGetWindowAttributes(xGlobalDisplay, (X11Window)display.window, &winAttr);
1103          template.visualid = XVisualIDFromVisual(winAttr.visual);
1104          visualInfo = XGetVisualInfo(xGlobalDisplay, VisualIDMask, &template, &n);
1105 #ifdef _DEBUG
1106          printf("XGetVisualInfo visual ID = %d\n", template.visualid);
1107          printf("visualInfo visual ID = %d\n", visualInfo->visualid);
1108          printf("oglSystem.visualInfo visual ID = %d\n", oglSystem.visualInfo->visualid);
1109          printf("((XWindowData)display.windowDriverData).visual visual ID = %d\n", ((XWindowData)display.windowDriverData).visual->visualid);
1110 #endif
1111          // visualInfo = oglSystem.visualInfo;
1112 //#endif
1113          */
1114          if(visualInfo)
1115          {
1116             //printf("visualInfo is not null\n");
1117             // printf("Creating Display Context, sharing with %x!\n", oglSystem.glContext);
1118             oglDisplay.glContext = glXCreateContext(xGlobalDisplay, visualInfo, oglSystem.glContext, True);
1119             //XFree(visualInfo);
1120          }
1121
1122          // oglDisplay.glContext = glXCreateContext(xGlobalDisplay, oglSystem.visualInfo, oglSystem.glContext, True);
1123          if(oglDisplay.glContext)
1124          {
1125             //printf("CreateDisplay Got a Context\n");
1126             glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext);
1127             result = true;
1128          }
1129       #endif
1130    #endif
1131       }
1132 #if defined(__WIN32__) || defined(USEPBUFFER)
1133       else
1134       {
1135          result = true;
1136          wglMakeCurrent(oglSystem.hdc, oglSystem.glrc);
1137       }
1138 #endif
1139       if(result)
1140       {
1141          ogl_LoadFunctions();
1142          CheckExtensions(oglSystem);
1143          vboAvailable = glBindBuffer != null;
1144          setupDebugging();
1145          initialDisplaySetup(display);
1146       }
1147
1148       if(!useSingleGLContext)
1149       {
1150    #if defined(__WIN32__)
1151          wglMakeCurrent(null, null);
1152    #elif defined(__unix__) || defined(__APPLE__)
1153       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
1154          result = true;
1155       #else
1156          glXMakeCurrent(xGlobalDisplay, None, null);
1157       #endif
1158    #endif
1159       }
1160       else
1161       {
1162       #if defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__ODROID__)
1163          result = true;
1164       #endif
1165       }
1166
1167       return result;
1168    }
1169
1170    bool DisplaySize(Display display, int width, int height)
1171    {
1172       OGLDisplay oglDisplay = display.driverData;
1173
1174       bool result = false;
1175
1176       //printf("Inside DisplaySize\n");
1177 #if defined(__WIN32__) || defined(USEPBUFFER)
1178       OGLSystem oglSystem = display.displaySystem.driverData;
1179       if(display.alphaBlend)
1180       {
1181 #if defined(__WIN32__)
1182          const int attributes[]=
1183          {
1184             /*WGL_TEXTURE_FORMAT_ARB, WGL_TEXTURE_RGBA_ARB,
1185             WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_2D_ARB, */0
1186          };
1187          int pixelFormat = 0;
1188          if(wglChoosePixelFormatARB)
1189          {
1190             int valid;
1191             int numFormats;
1192             float fAttributes[] = {0,0};
1193             int iAttributes[] =
1194             {
1195                //WGL_DRAW_TO_BITMAP_ARB, GL_TRUE,
1196                WGL_DRAW_TO_PBUFFER_ARB,GL_TRUE,
1197                WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
1198                WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
1199                WGL_COLOR_BITS_ARB,24,
1200                WGL_ALPHA_BITS_ARB,8,
1201                WGL_DEPTH_BITS_ARB,16,
1202                WGL_STENCIL_BITS_ARB,0,
1203                WGL_DOUBLE_BUFFER_ARB,GL_FALSE,
1204                WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
1205                WGL_SAMPLES_ARB, 4,                  // Check For 4x Multisampling
1206                0,0
1207             };
1208
1209             //Log("Found wglChoosePixelFormatARB\n");
1210
1211             valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
1212             if(!valid || !numFormats)
1213             {
1214                //Log("Can't find 4x multi sampling\n");
1215                iAttributes[19] = 2;
1216                valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
1217                if(!valid || !numFormats)
1218                {
1219                   // Log("Can't find 2x multi sampling\n");
1220                   iAttributes[16] = 0;
1221                   iAttributes[17] = 0;
1222                   valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
1223                   if(!valid || !numFormats)
1224                   {
1225                      int iAttributes[] =
1226                      {
1227                         WGL_DRAW_TO_PBUFFER_ARB,GL_TRUE,
1228                         //WGL_DRAW_TO_BITMAP_ARB,GL_TRUE,
1229                         WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
1230                         WGL_COLOR_BITS_ARB,24,
1231                         WGL_ALPHA_BITS_ARB,8,
1232                         WGL_DEPTH_BITS_ARB,16,
1233                         0,0
1234                      };
1235                      valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
1236                   }
1237                }
1238             }
1239             if(valid && numFormats)
1240             {
1241                wglMakeCurrent(null, null);
1242             }
1243          }
1244
1245          wglMakeCurrent( null, null );
1246          wglMakeCurrent( oglDisplay.hdc, oglDisplay.glrc );
1247          if(oglDisplay.hdc && oglDisplay.pBuffer)
1248             wglReleasePbufferDCARB(oglDisplay.pBuffer, oglDisplay.hdc);
1249
1250          wglDestroyPbufferARB(oglDisplay.pBuffer);
1251
1252          if(!useSingleGLContext)
1253             wglMakeCurrent( null, null );
1254
1255          if(oglDisplay.glrc)
1256             wglDeleteContext(oglDisplay.glrc);
1257
1258          oglDisplay.pBuffer = wglCreatePbufferARB(oglSystem.hdc, pixelFormat, width, height, attributes);
1259          oglDisplay.hdc = wglGetPbufferDCARB(oglDisplay.pBuffer);
1260          if((oglDisplay.glrc = winCreateContext(oglDisplay.hdc)))
1261          {
1262             BITMAPINFO * info;
1263             HDC hdc = GetDC(display.window);
1264
1265             wglShareLists(oglSystem.glrc, oglDisplay.glrc);
1266             wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
1267
1268             //wglQueryPbufferARB(pBuffer, WGL_PBUFFER_WIDTH_ARB, &width);
1269             //wglQueryPbufferARB(pBuffer, WGL_PBUFFER_HEIGHT_ARB, &height);
1270
1271             // glDeleteBuffersARB(2, oglDisplay.imageBuffers);
1272
1273             if((info = (BITMAPINFO *)new0 byte[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256]))
1274             {
1275                HBITMAP newBitmap;
1276
1277                if(oglDisplay.memDC) DeleteDC(oglDisplay.memDC);
1278                oglDisplay.memDC = CreateCompatibleDC(hdc);
1279                SetMapMode(oglDisplay.memDC, MM_TEXT);
1280                info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1281                info->bmiHeader.biPlanes = 1;
1282                info->bmiHeader.biCompression = BI_RGB;
1283                info->bmiHeader.biBitCount = 32; //(uint16)GetDeviceCaps(hdc, BITSPIXEL);
1284                info->bmiHeader.biWidth = width;
1285                info->bmiHeader.biHeight = height;
1286                newBitmap = CreateDIBSection(hdc, info, DIB_RGB_COLORS, &oglDisplay.picture, null, 0);
1287                if(newBitmap)
1288                {
1289                   SelectObject(oglDisplay.memDC, newBitmap);
1290                   if(oglDisplay.memBitmap) DeleteObject(oglDisplay.memBitmap);
1291                   /*
1292                   {
1293                      PIXELFORMATDESCRIPTOR pfd = { 0 };
1294                      pfd.nSize = (short)sizeof(pfd);
1295                      pfd.nVersion = 1;
1296                      pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL;
1297                      pfd.iPixelType = PFD_TYPE_RGBA;
1298                      pfd.cColorBits = 32;
1299                      //pfd.cAlphaBits = 8;
1300                      pfd.cDepthBits = 24;
1301                      pfd.iLayerType = PFD_MAIN_PLANE;
1302
1303                      oglDisplay.hdc = oglDisplay.memDC;
1304
1305                      pixelFormat = ChoosePixelFormat(oglSystem.hdc, &pfd);
1306                      DescribePixelFormat(oglDisplay.hdc, pixelFormat, sizeof(pfd), &pfd);
1307                      SetPixelFormat(oglDisplay.hdc, pixelFormat, &pfd);
1308
1309                      oglDisplay.glrc = wglCreateContext(oglDisplay.hdc);
1310                      wglShareLists(oglSystem.glrc, oglDisplay.glrc);
1311                      wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
1312                   }
1313                   */
1314                   /*
1315                   {
1316                      const int imageSize = width * height * 4;
1317
1318                      glGenBuffersARB(2, oglDisplay.imageBuffers);
1319
1320                      glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[0]);
1321                      glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, imageSize, null, GL_STREAM_READ);
1322                      // glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[1]);
1323                      // glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, imageSize / 2, null, GL_STREAM_READ);
1324                   }
1325                   */
1326                   oglDisplay.memBitmap = newBitmap;
1327                   oglDisplay.stride = width;
1328
1329                   result = true;
1330                }
1331                delete info;
1332             }
1333             ReleaseDC(display.window, hdc);
1334          }
1335 #elif defined(__unix__) || defined(__APPLE__)
1336       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
1337          result = true;
1338       #else
1339          int attrib[] =
1340          {
1341             GLX_DOUBLEBUFFER,  True,
1342             GLX_DEPTH_SIZE,    1,
1343             GLX_RED_SIZE,      8,
1344             GLX_GREEN_SIZE,    8,
1345             GLX_BLUE_SIZE,     8,
1346             GLX_ALPHA_SIZE,    8,
1347             GLX_STENCIL_SIZE,  1,
1348             //GLX_DEPTH_SIZE,    24,
1349             GLX_RENDER_TYPE,   GLX_RGBA_BIT,
1350             GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT,
1351             None
1352          };
1353
1354          int PBattrib[] =
1355          {
1356             GLX_PBUFFER_WIDTH,   width,
1357             GLX_PBUFFER_HEIGHT,  height,
1358             GLX_LARGEST_PBUFFER, False,
1359             None
1360          };
1361
1362          // choose a pixel format that meets our minimum requirements
1363          int count = 0;
1364
1365          GLXFBConfig *config = glXChooseFBConfig(xGlobalDisplay, DefaultScreen(xGlobalDisplay), attrib, &count);
1366          if(config)
1367          {
1368             if(oglDisplay.pixmap)
1369             {
1370                XFreePixmap(xGlobalDisplay, oglDisplay.pixmap);
1371                oglDisplay.pixmap = None;
1372             }
1373             if(oglDisplay.shapePixmap)
1374             {
1375                XFreePixmap(xGlobalDisplay, oglDisplay.shapePixmap);
1376                oglDisplay.shapePixmap = None;
1377             }
1378
1379             // Free Shared Memory Pixmap
1380             if(oglDisplay.image)
1381             {
1382                if(oglDisplay.shminfoShape.shmid != -1)
1383                {
1384                   XShmDetach(xGlobalDisplay, &oglDisplay.shminfo);
1385                   if(oglDisplay.shminfo.shmaddr != (void *)-1)
1386                      shmdt(oglDisplay.shminfo.shmaddr);
1387                   shmctl(oglDisplay.shminfo.shmid, IPC_RMID, 0);
1388                }
1389                XDestroyImage(oglDisplay.image);
1390                oglDisplay.image = None;
1391             }
1392             if(oglDisplay.shapeImage)
1393             {
1394                if(oglDisplay.shminfoShape.shmid != -1)
1395                {
1396                   XShmDetach(xGlobalDisplay, &oglDisplay.shminfoShape);
1397                   if(oglDisplay.shminfoShape.shmaddr != (void *)-1)
1398                      shmdt(oglDisplay.shminfoShape.shmaddr);
1399                   shmctl(oglDisplay.shminfoShape.shmid, IPC_RMID, 0);
1400                }
1401                XDestroyImage(oglDisplay.shapeImage);
1402                oglDisplay.shapeImage = None;
1403             }
1404
1405             if(oglDisplay.windowPicture)
1406                XRenderFreePicture(xGlobalDisplay, oglDisplay.windowPicture);
1407             if(oglDisplay.pixmapPicture)
1408                XRenderFreePicture(xGlobalDisplay, oglDisplay.pixmapPicture);
1409
1410             if(oglDisplay.pixmap)
1411                XFreePixmap(xGlobalDisplay, oglDisplay.pixmap);
1412
1413             if(oglDisplay.glContext)
1414               glXDestroyContext(xGlobalDisplay, oglDisplay.glContext);
1415             if(oglDisplay.pBuffer)
1416                glXDestroyPbuffer(xGlobalDisplay, oglDisplay.pBuffer);
1417
1418             oglDisplay.pBuffer = glXCreatePbuffer(xGlobalDisplay, config[0], PBattrib);
1419             if(oglDisplay.pBuffer)
1420             {
1421                oglDisplay.glContext = glXCreateNewContext(xGlobalDisplay, config[0], GLX_RGBA_TYPE, oglSystem.glContext, True);
1422                if(oglDisplay.glContext)
1423                {
1424                   glXMakeCurrent(xGlobalDisplay, None, null);
1425                   glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext);
1426
1427                   // Initialize Shared Memory Pixmap
1428                   oglDisplay.image = XShmCreateImage(xGlobalDisplay, DefaultVisual(xGlobalDisplay, DefaultScreen(xGlobalDisplay)), 32,
1429                      ZPixmap, null, &oglDisplay.shminfo, width, height);
1430                   if(oglDisplay.image)
1431                   {
1432                      oglDisplay.shminfo.shmid = shmget(IPC_PRIVATE,
1433                         oglDisplay.image->bytes_per_line * oglDisplay.image->height, IPC_CREAT|0777);
1434                      if(oglDisplay.shminfo.shmid != -1)
1435                      {
1436                         oglDisplay.shminfo.shmaddr = shmat(oglDisplay.shminfo.shmid, 0, 0);
1437                         if(oglDisplay.shminfo.shmaddr != (void *)-1)
1438                         {
1439                            oglDisplay.shminfo.readOnly = False;
1440                            if(XShmAttach(xGlobalDisplay, &oglDisplay.shminfo))
1441                            {
1442                               oglDisplay.pixmap = XShmCreatePixmap(xGlobalDisplay, (X11Window)display.window, oglDisplay.shminfo.shmaddr,
1443                                  &oglDisplay.shminfo, width, height, 32);
1444
1445                               // Initialize Shared Memory Shape Pixmap
1446                               oglDisplay.shapeImage = XShmCreateImage(xGlobalDisplay, DefaultVisual(xGlobalDisplay, DefaultScreen(xGlobalDisplay)), 1,
1447                                  ZPixmap, null, &oglDisplay.shminfoShape, width, height);
1448                               if(oglDisplay.shapeImage)
1449                               {
1450                                  oglDisplay.shminfoShape.shmid = shmget(IPC_PRIVATE,
1451                                     oglDisplay.shapeImage->bytes_per_line * oglDisplay.shapeImage->height, IPC_CREAT|0777);
1452                                  if(oglDisplay.shminfoShape.shmid != -1)
1453                                  {
1454                                     oglDisplay.shminfoShape.shmaddr = shmat(oglDisplay.shminfoShape.shmid, 0, 0);
1455                                     if(oglDisplay.shminfoShape.shmaddr != (void *)-1)
1456                                     {
1457                                        oglDisplay.shminfoShape.readOnly = False;
1458                                        if(XShmAttach(xGlobalDisplay, &oglDisplay.shminfoShape))
1459                                        {
1460                                           oglDisplay.shapePixmap = XShmCreatePixmap(xGlobalDisplay, (X11Window)display.window, oglDisplay.shminfoShape.shmaddr,
1461                                              &oglDisplay.shminfoShape, width, height, 1);
1462                                           //oglDisplay.shapePixmap = XCreatePixmap(xGlobalDisplay, (X11Window)display.window, width, height, 1);
1463
1464                                           {
1465                                              XRenderPictureAttributes attributes = { 0 };
1466                                              XRenderPictFormat * format = XRenderFindStandardFormat(xGlobalDisplay, /*PictStandardRGB24*/ PictStandardARGB32);
1467                                              #if !defined(__APPLE__)
1468                                              attributes.repeat = RepeatNormal;
1469                                              #else
1470                                              attributes.repeat = 1;
1471                                              #endif
1472                                              oglDisplay.pixmapPicture = XRenderCreatePicture(xGlobalDisplay, oglDisplay.pixmap, format, CPRepeat, &attributes);
1473                                              oglDisplay.windowPicture = XRenderCreatePicture(xGlobalDisplay, (X11Window)display.window, format, 0, &attributes);
1474                                              oglDisplay.shapePicture = XRenderCreatePicture(xGlobalDisplay, oglDisplay.shapePixmap,
1475                                                 XRenderFindStandardFormat(xGlobalDisplay, PictStandardA1), 0, &attributes);
1476                                           }
1477
1478                                           oglDisplay.picture = oglDisplay.shminfo.shmaddr;
1479                                           oglDisplay.stride = oglDisplay.image->bytes_per_line / 4;
1480
1481                                           result = true;
1482                                        }
1483                                     }
1484                                  }
1485                               }
1486                            }
1487                         }
1488                      }
1489                   }
1490                }
1491             }
1492             XFree(config);
1493          }
1494      #endif
1495 #endif
1496          CreateDisplay(display);
1497 #if defined(__WIN32__)
1498          wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc);
1499 #elif defined(__unix__) || defined(__APPLE__)
1500       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
1501          width = eglWidth;
1502          height = eglHeight;
1503       #else
1504          glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext);
1505       #endif
1506 #endif
1507       }
1508       else
1509 #endif
1510          result = true;
1511
1512       if(display.alphaBlend && result)
1513          initialDisplaySetup(display);
1514
1515       if(!result && display.alphaBlend)
1516       {
1517          printf("Alpha blending windows not supported on this display\n");
1518       }
1519       if(!result)
1520          return false;
1521
1522       result = false;
1523
1524       glViewport(0,0,width,height);
1525       glMatrixMode(MatrixMode::projection);
1526       glLoadIdentity();
1527       glOrtho(0,width,height,0,0.0,1.0);
1528       displayWidth = display.width = width;
1529       displayHeight = display.height = height;
1530
1531       if(!oglDisplay.flippingBuffer || oglDisplay.flipBufW < width || oglDisplay.flipBufH < height)
1532       {
1533          oglDisplay.flipBufW = width;
1534          oglDisplay.flipBufH = height;
1535 #ifdef ES1_1
1536          result = true;
1537 #else
1538          oglDisplay.flippingBuffer = renew oglDisplay.flippingBuffer ColorAlpha [width * height];
1539 #endif
1540       }
1541       if(oglDisplay.flippingBuffer || !width || !height)
1542          result = true;
1543
1544       return result;
1545    }
1546
1547    void DisplayPosition(Display display, int x, int y)
1548    {
1549       OGLDisplay oglDisplay = display.driverData;
1550
1551       oglDisplay.x = x;
1552       oglDisplay.y = y;
1553    }
1554
1555    void SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
1556    {
1557    }
1558
1559    void RestorePalette(Display display)
1560    {
1561    }
1562
1563    void StartUpdate(Display display)
1564    {
1565    }
1566
1567    void EndUpdate(Display display)
1568    {
1569    }
1570
1571    void Scroll(Display display, Box scroll, int x, int y, Extent dirty)
1572    {
1573    }
1574
1575    void Update(Display display, Box updateBox)
1576    {
1577 #if defined(__WIN32__) || defined(USEPBUFFER)
1578       OGLDisplay oglDisplay = display.driverData;
1579 #endif
1580       //Logf("DisplayScreen\n");
1581
1582 #if !defined(__ANDROID__)
1583       /*glFlush();
1584       glFinish();*/
1585 #endif
1586
1587 #if defined(__WIN32__) || defined(USEPBUFFER)
1588       if(display.alphaBlend)
1589       {
1590          glPixelStorei(GL_PACK_ALIGNMENT, 4);
1591          glPixelStorei(GL_PACK_ROW_LENGTH, oglDisplay.stride);
1592          glPixelStorei(GL_PACK_SKIP_ROWS, 0);
1593          glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
1594          glReadPixels(0,0,display.width,display.height,GL_BGRA_EXT,GL_UNSIGNED_BYTE, oglDisplay.picture);
1595
1596          {
1597 #if defined(__WIN32__)
1598             HDC hdc = GetDC(0);
1599             POINT point = { oglDisplay.x, oglDisplay.y};
1600             POINT srcPoint = { 0, 0 };
1601             BLENDFUNCTION blend = { 0 };
1602             SIZE size;
1603             size.cx = display.width;
1604             size.cy = display.height;
1605             blend.BlendOp = AC_SRC_OVER;
1606             blend.BlendFlags = 0;
1607             blend.SourceConstantAlpha = 255;
1608             blend.AlphaFormat = AC_SRC_ALPHA;
1609
1610             /*
1611             // Process partial images.  Mapping the buffer waits for
1612             // outstanding DMA transfers into the buffer to finish.
1613             glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[0]);
1614             oglDisplay.pboMemory1 = (byte *)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
1615
1616             // glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[1]);
1617             // oglDisplay.pboMemory2 = (byte *)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB,GL_READ_ONLY);
1618
1619
1620             memcpy(oglDisplay.picture, oglDisplay.pboMemory1, display.width * display.height * 4);
1621             //memcpy(oglDisplay.picture + display.width * display.height * 4 / 2, oglDisplay.pboMemory2, display.width * display.height * 4/ 2);
1622             */
1623
1624             UpdateLayeredWindow(display.window, hdc, &point, &size, oglDisplay.memDC, &srcPoint, 0, &blend, ULW_ALPHA);
1625             /*
1626
1627             // Unmap the image buffers
1628             glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[0]);
1629             glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
1630
1631             // glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[1]);
1632             // glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
1633
1634             // Bind two different buffer objects and start the glReadPixels
1635             // asynchronously. Each call will return directly after
1636             // starting the DMA transfer.
1637             glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[0]);
1638             glReadPixels(0, 0, display.width, display.height, GL_BGRA, GL_UNSIGNED_BYTE, 0);
1639
1640             // glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, oglDisplay.imageBuffers[1]);
1641             // glReadPixels(0, display.height/2, display.width, display.height/2, GL_BGRA, GL_UNSIGNED_BYTE, 0);
1642             */
1643
1644             ReleaseDC(0, hdc);
1645 #elif defined(__unix__) || defined(__APPLE__)
1646       #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__)
1647       #else
1648             XTransform transform =
1649             {
1650                {
1651                   { (int)(1.0f * (1<<16)), (int)(0.0f * (1<<16)),  (int)(0 * (1 << 16)) },
1652                   { (int)(0.0f),           (int)(-1.0f * (1<<16)), (int)(0 * (1<<16)) },
1653                   { (int)(0.0f * (1<<16)), (int)(0.0f * (1<<16)),  (int)(1.0f * (1<<16)) }
1654                }
1655             };
1656             XRenderSetPictureTransform(xGlobalDisplay, oglDisplay.pixmapPicture, &transform);
1657             XRenderComposite(xGlobalDisplay, PictOpSrc, oglDisplay.pixmapPicture, None, oglDisplay.shapePicture, 0, 0, 0, 0, 0, 0, display.width, display.height);
1658             XRenderComposite(xGlobalDisplay, PictOpSrc, oglDisplay.pixmapPicture, None, oglDisplay.windowPicture, 0, 0, 0, 0, 0, 0, display.width, display.height);
1659             #if !defined(__APPLE__)
1660             XShapeCombineMask(xGlobalDisplay, (X11Window)display.window, ShapeInput, 0, 0, oglDisplay.shapePixmap, ShapeSet);
1661             #else
1662             XShapeCombineMask(xGlobalDisplay, display.window, 2, 0, 0, oglDisplay.shapePixmap, ShapeSet);
1663             #endif
1664             XFlush(xGlobalDisplay);
1665      #endif
1666 #endif
1667          }
1668       }
1669       else
1670 #endif
1671       {
1672 #if defined(__WIN32__)
1673          //wglSwapLayerBuffers(oglDisplay.hdc,WGL_SWAP_MAIN_PLANE);
1674          SwapBuffers(oglDisplay.hdc);
1675 #elif defined(__unix__) || defined(__APPLE__)
1676       #if defined(__ANDROID__) || defined(__ODROID__)
1677          eglSwapBuffers(eglDisplay, eglSurface);
1678       #elif defined(__EMSCRIPTEN__)
1679          glfwSwapBuffers();
1680       #else
1681          glXSwapBuffers(xGlobalDisplay, (GLXDrawable)display.window);
1682       #endif
1683 #endif
1684       }
1685       //Logf("Out of DisplayScreen\n");
1686    }
1687
1688    void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
1689    {
1690       if(bitmap.driverData)
1691       {
1692          GLuint tex = (GLuint)(uintptr)bitmap.driverData;
1693          glDeleteTextures(1, &tex);
1694          bitmap.driverData = 0;
1695       }
1696       bitmap.driver = ((subclass(DisplayDriver))class(LFBDisplayDriver));
1697    }
1698
1699    bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
1700    {
1701       OGLSystem oglSystem = displaySystem.driverData;
1702       bool result = false;
1703       Bitmap mipMap { };
1704       GLuint glBitmap = 0;
1705
1706       uint w = width, h = height;
1707       if(oglSystem.pow2textures)
1708       {
1709          w = pow2i(w);
1710          h = pow2i(h);
1711       }
1712       w = Min(w, oglSystem.maxTextureSize);
1713       h = Min(h, oglSystem.maxTextureSize);
1714
1715       glGenTextures(1, &glBitmap);
1716       glBindTexture(GL_TEXTURE_2D, glBitmap);
1717
1718       glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
1719
1720       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1721       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1722
1723       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1724       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1725
1726 #if !defined(SHADERS)
1727       glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1728 #endif
1729
1730       mipMap.Allocate(null, w, h, w, pixelFormatRGBA, false);
1731
1732       // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture);
1733       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture);
1734
1735       delete mipMap;
1736
1737       bitmap.driverData = (void *)(uintptr)glBitmap;
1738       bitmap.driver = displaySystem.driver;
1739       bitmap.width = w;
1740       bitmap.height = h;
1741
1742       result = true;
1743       return result;
1744    }
1745
1746    bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
1747    {
1748       bool result = false;
1749       OGLSystem oglSystem = displaySystem.driverData;
1750       Bitmap convBitmap = bitmap;
1751       if(bitmap.keepData)
1752       {
1753          convBitmap = { };
1754          convBitmap.Copy(bitmap);
1755       }
1756
1757       // Pre process the bitmap... First make it 32 bit
1758       if(/*bitmap.pixelFormat == pixelFormatRGBA || */convBitmap.Convert(null, pixelFormat888, null))
1759       {
1760          int c, level;
1761          uint w = bitmap.width, h = bitmap.height;
1762          GLuint glBitmap = 0;
1763          if(oglSystem.pow2textures)
1764          {
1765             w = pow2i(w);
1766             h = pow2i(h);
1767          }
1768          w = Min(w, oglSystem.maxTextureSize);
1769          h = Min(h, oglSystem.maxTextureSize);
1770
1771          if(mipMaps)
1772          {
1773             while(w * 2 < h) w *= 2;
1774             while(h * 2 < w) h *= 2;
1775          }
1776
1777          // Switch ARGB to RGBA
1778          //if(bitmap.format != pixelFormatRGBA)
1779          {
1780             for(c=0; c<bitmap.size; c++)
1781             {
1782                // ((ColorRGBA *)bitmap.picture)[c] = ((ColorAlpha *)bitmap.picture)[c];
1783                // TODO:
1784                ColorAlpha color = ((ColorAlpha *)convBitmap.picture)[c];
1785                ((ColorRGBA *)convBitmap.picture)[c] = ColorRGBA { color.color.r, color.color.g, color.color.b, color.a };
1786             }
1787          }
1788          // convBitmap.pixelFormat = pixelFormat888;
1789
1790          glGetError();
1791          glGenTextures(1, &glBitmap);
1792          if(glBitmap == 0)
1793          {
1794             //int error = glGetError();
1795             return false;
1796          }
1797
1798          glBindTexture(GL_TEXTURE_2D, glBitmap);
1799          glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
1800
1801          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mipMaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
1802          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1803
1804          //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1805
1806          //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1807          //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1808
1809          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1810          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1811 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
1812          glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0 );
1813 #endif
1814
1815 #if !defined(SHADERS)
1816          glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1817 #endif
1818
1819          result = true;
1820
1821          for(level = 0; result && (w >= 1 || h >= 1); level++, w >>= 1, h >>= 1)
1822          {
1823             Bitmap mipMap;
1824             if(!w) w = 1;
1825             if(!h) h = 1;
1826             if(bitmap.width != w || bitmap.height != h)
1827             {
1828                mipMap = Bitmap { };
1829                if(mipMap.Allocate(null, w, h, w, convBitmap.pixelFormat, false))
1830                {
1831                   Surface mipSurface = mipMap.GetSurface(0,0,null);
1832                   mipSurface.Filter(convBitmap, 0,0,0,0, w, h, convBitmap.width, convBitmap.height);
1833                   delete mipSurface;
1834                }
1835                else
1836                {
1837                   result = false;
1838                   delete mipMap;
1839                }
1840             }
1841             else
1842                mipMap = convBitmap;
1843
1844             if(result)
1845             {
1846                int error;
1847                //int width = 0;
1848                glGetError();
1849                // glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture);
1850                glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture);
1851                //printf("Calling glTexImage2D\n");
1852                //glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, &width);
1853                //printf("width = %d (Should be %d, %d)\n", width, w, h);
1854                if((error = glGetError()))
1855                {
1856                   //Logf("OpenGL Bitmap MakeDD error: %d...\n", error);
1857                   //printf("OpenGL Bitmap MakeDD error: %d...\n", error);
1858                   result = false;
1859                }
1860             }
1861             if(mipMap != convBitmap)
1862                delete mipMap;
1863             if(!mipMaps) break;
1864          }
1865
1866          convBitmap.driver.FreeBitmap(convBitmap.displaySystem, convBitmap);
1867          bitmap.driverData = (void *)(uintptr)glBitmap;
1868          bitmap.driver = displaySystem.driver;
1869          if(bitmap.keepData)
1870             delete convBitmap;
1871
1872          if(!result)
1873             FreeBitmap(displaySystem, bitmap);
1874          else if(oglSystem.loadingFont)
1875          {
1876             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1877             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1878             oglSystem.loadingFont = false;
1879          }
1880       }
1881       return result;
1882    }
1883
1884    void ReleaseSurface(Display display, Surface surface)
1885    {
1886       glDisable(GL_SCISSOR_TEST);
1887       delete surface.driverData;
1888       surface.driverData = null;
1889    }
1890
1891    bool GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x, int y, Box clip)
1892    {
1893       return false;
1894    }
1895
1896    bool GetSurface(Display display, Surface surface, int x,int y, Box clip)
1897    {
1898       bool result = false;
1899       OGLSurface oglSurface = surface.driverData = OGLSurface { };
1900
1901       //Logf("GetSurface\n");
1902
1903       if(oglSurface)
1904       {
1905          if(displayWidth != display.width || displayHeight != display.height)
1906          {
1907             displayWidth = display.width;
1908             displayHeight = display.height;
1909
1910             glViewport(0,0,display.width,display.height);
1911             glLoadIdentity();
1912             glOrtho(0,display.width,display.height,0,0.0,1.0);
1913          }
1914
1915          surface.offset.x = x;
1916          surface.offset.y = y;
1917          surface.unclippedBox = surface.box = clip;
1918          oglSurface.bitmapMult[0] = 1;
1919          oglSurface.bitmapMult[1] = 1;
1920          oglSurface.bitmapMult[2] = 1;
1921          oglSurface.bitmapMult[3] = 1;
1922
1923          glEnable(GL_SCISSOR_TEST);
1924          glScissor(
1925             x+clip.left,
1926             (display.height) -(y+clip.bottom)-1,
1927             clip.right-clip.left+1,
1928             clip.bottom-clip.top+1);
1929          result = true;
1930       }
1931       return result;
1932    }
1933
1934    void Clip(Display display, Surface surface, Box clip)
1935    {
1936       Box box;
1937
1938       //Logf("Clip\n");
1939
1940       if(clip != null)
1941       {
1942          box = clip;
1943          box.Clip(surface.unclippedBox);
1944          surface.box = box;
1945       }
1946       else
1947          box = surface.box = surface.unclippedBox;
1948       box.left += surface.offset.x;
1949       box.top  += surface.offset.y;
1950       box.right+= surface.offset.x;
1951       box.bottom += surface.offset.y;
1952
1953       glScissor(
1954          box.left,display.height - box.bottom - 1,
1955          box.right-box.left+1, box.bottom-box.top+1);
1956    }
1957
1958    bool GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
1959    {
1960       bool result = false;
1961       OGLDisplay oglDisplay = display.driverData;
1962       ColorAlpha * flippingBuffer = oglDisplay.flippingBuffer;
1963
1964       if(oglDisplay.flippingBuffer)
1965       {
1966          if(bitmap.pixelFormat != pixelFormat888 || bitmap.width < w || bitmap.height < h)
1967          {
1968             bitmap.Free();
1969             bitmap.Allocate(null, w,h,w, pixelFormat888, false);
1970          }
1971          if(bitmap)
1972          {
1973             uint row;
1974
1975             glPixelStorei(GL_PACK_ALIGNMENT, 4);
1976             glPixelStorei(GL_PACK_ROW_LENGTH, bitmap.stride);
1977             glPixelStorei(GL_PACK_SKIP_ROWS, 0);
1978             glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
1979             glReadPixels(x,display.height-h-y,w,h,GL_BGRA_EXT,GL_UNSIGNED_BYTE, flippingBuffer);
1980
1981             // Need a flip...
1982             for(row = 0; row<h; row++)
1983                CopyBytesBy4(((ColorAlpha *)bitmap.picture) + row * w, ((ColorAlpha *)flippingBuffer) + (h-row-1) * w, w);
1984             result = true;
1985          }
1986       }
1987       return result;
1988    }
1989
1990    void SetForeground(Display display, Surface surface, ColorAlpha color)
1991    {
1992       OGLSurface oglSurface = surface.driverData;
1993
1994       //Logf("SetForeground\n");
1995
1996       oglSurface.foreground[0] = color.color.r/255.0f;
1997       oglSurface.foreground[1] = color.color.g/255.0f;
1998       oglSurface.foreground[2] = color.color.b/255.0f;
1999       //oglSurface.foreground[3] = 1.0f;
2000       oglSurface.foreground[3] = color.a/255.0f;
2001
2002       //if(!oglSurface.foreground[3])printf("bug");
2003    }
2004
2005    void SetBackground(Display display, Surface surface, ColorAlpha color)
2006    {
2007       OGLSurface oglSurface = surface.driverData;
2008
2009       //Logf("SetBackground\n");
2010
2011       oglSurface.background[0] = color.color.r/255.0f;
2012       oglSurface.background[1] = color.color.g/255.0f;
2013       oglSurface.background[2] = color.color.b/255.0f;
2014       //oglSurface.background[3] = 1.0;
2015       oglSurface.background[3] = color.a/255.0f;
2016    }
2017
2018    void SetBlitTint(Display display, Surface surface, ColorAlpha color)
2019    {
2020       OGLSurface oglSurface = surface.driverData;
2021
2022       oglSurface.bitmapMult[0] = color.color.r/255.0f;
2023       oglSurface.bitmapMult[1] = color.color.g/255.0f;
2024       oglSurface.bitmapMult[2] = color.color.b/255.0f;
2025       oglSurface.bitmapMult[3] = color.a/255.0f;
2026    }
2027
2028    ColorAlpha GetPixel(Display display, Surface surface,int x,int y)
2029    {
2030       return 0;
2031    }
2032
2033    void PutPixel(Display display, Surface surface,int x,int y)
2034    {
2035       OGLSurface oglSurface = surface.driverData;
2036
2037       //Logf("PutPixel\n");
2038
2039       glColor4fv(oglSurface.foreground);
2040       glBegin(GL_POINTS);
2041       // glVertex2i(x+surface.offset.x, y+surface.offset.y);
2042       glVertex2f(x+surface.offset.x + 0.5f, y+surface.offset.y + 0.5f);
2043
2044       glEnd();
2045    }
2046
2047    void DrawLine(Display display, Surface surface, int _x1, int _y1, int _x2, int _y2)
2048    {
2049       OGLSurface oglSurface = surface.driverData;
2050       float x1 = _x1, x2 = _x2, y1 = _y1, y2 = _y2;
2051       if(_x1 == _x2)
2052       {
2053          if(_y2 >= _y1)
2054             y2 += 1;
2055          else
2056             y1 += 1;
2057       }
2058       else if(_y1 == _y2)
2059       {
2060          if(_x2 >= _x1)
2061             x2 += 1;
2062          else
2063             x1 += 1;
2064       }
2065       x1 += surface.offset.x;
2066       y1 += surface.offset.y;
2067       x2 += surface.offset.x;
2068       y2 += surface.offset.y;
2069
2070       //Logf("Line\n");
2071
2072       glColor4fv(oglSurface.foreground);
2073       glBegin(GL_LINES);
2074 #if defined(ES1_1) || defined(EM_MODE) || defined(SHADERS)
2075       if(stippleEnabled)
2076       {
2077          glTexCoord2f(0.5f, 0);
2078          glVertex2f(x1 + 0.5f, y1 + 0.5f);
2079          glTexCoord2f(Max(x2-x1, y2-y1) + 0.5f, 0);
2080          glVertex2f(x2 + 0.5f, y2 + 0.5f);
2081       }
2082       else
2083 #endif
2084       {
2085          /*
2086          glVertex2i(x1, y1);
2087          glVertex2i(x2, y2);
2088          */
2089          glVertex2f(x1 + 0.5f, y1 + 0.5f);
2090          glVertex2f(x2 + 0.5f, y2 + 0.5f);
2091       }
2092
2093       glEnd();
2094    }
2095
2096    void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2)
2097    {
2098       OGLSurface oglSurface = surface.driverData;
2099       x1 += surface.offset.x;
2100       y1 += surface.offset.y;
2101       x2 += surface.offset.x;
2102       y2 += surface.offset.y;
2103
2104       //Logf("Rectangle\n");
2105
2106       glColor4fv(oglSurface.foreground);
2107 #if defined(ES1_1) || defined(EM_MODE) || defined(SHADERS)
2108       if(stippleEnabled)
2109       {
2110          glBegin(GL_LINES);
2111
2112          glTexCoord2f(0.5f, 0);
2113          glVertex2f(x1 + 0.5f, y1 + 0.5f);
2114          glTexCoord2f(y2-y1 + 0.5f, 0);
2115          glVertex2f(x1 + 0.5f, y2 + 0.5f);
2116
2117          glTexCoord2f(0.5f, 0);
2118          glVertex2f(x1 + 0.5f, y2 + 0.5f);
2119          glTexCoord2f(x2 - x1 + 0.5f, 0);
2120          glVertex2f(x2 + 0.5f, y2 + 0.5f);
2121
2122          glTexCoord2f(0.5f, 0);
2123          glVertex2f(x2 + 0.5f, y2 + 0.5f);
2124          glTexCoord2f(y1 - y2 + 0.5f, 0);
2125          glVertex2f(x2 + 0.5f, y1 + 0.5f);
2126
2127          glTexCoord2f(0.5f, 0);
2128          glVertex2f(x2 + 0.5f, y1 + 0.5f);
2129          glTexCoord2f(x1 - x2 + 0.5f, 0);
2130          glVertex2f(x1 + 0.5f, y1 + 0.5f);
2131       }
2132       else
2133 #endif
2134       {
2135          glBegin(GL_LINE_LOOP);
2136          /*
2137          glVertex2i(x1, y1);
2138          glVertex2i(x1, y2);
2139          glVertex2i(x2, y2);
2140          glVertex2i(x2, y1);
2141          */
2142          glVertex2f(x1 + 0.5f, y1 + 0.5f);
2143          glVertex2f(x1 + 0.5f, y2 + 0.5f);
2144          glVertex2f(x2 + 0.5f, y2 + 0.5f);
2145          glVertex2f(x2 + 0.5f, y1 + 0.5f);
2146       }
2147       glEnd();
2148    }
2149
2150    void Area(Display display, Surface surface,int x1,int y1,int x2,int y2)
2151    {
2152       OGLSurface oglSurface = surface.driverData;
2153       //Logf("Area\n");
2154
2155       glColor4fv(oglSurface.background);
2156
2157 #ifdef EM_MODE
2158       glBegin(GL_QUADS);
2159       glVertex2f(x1+surface.offset.x, y1+surface.offset.y);
2160       glVertex2f(x1+surface.offset.x, y2+surface.offset.y+1);
2161       glVertex2f(x2+surface.offset.x+1, y2+surface.offset.y+1);
2162       glVertex2f(x2+surface.offset.x+1, y1+surface.offset.y);
2163       glEnd();
2164 #else
2165       glRecti(x1+surface.offset.x, y1+surface.offset.y,
2166               x2+surface.offset.x + 1, y2+surface.offset.y + 1);
2167 #endif
2168       /*
2169       glRectf(x1+surface.offset.x, y1+surface.offset.y,
2170               x2+surface.offset.x + 1, y2+surface.offset.y + 1);
2171       */
2172    }
2173
2174    void Clear(Display display, Surface surface, ClearType type)
2175    {
2176       OGLDisplay oglDisplay = display.driverData;
2177       OGLSurface oglSurface = surface.driverData;
2178
2179       //Logf("Clear\n");
2180       if(type != depthBuffer)
2181          glClearColor(oglSurface.background[0], oglSurface.background[1], oglSurface.background[2], oglSurface.background[3]);
2182       if(type != colorBuffer && !oglDisplay.depthWrite)
2183       {
2184          glDepthMask((byte)bool::true);
2185       }
2186       glClear(((type != depthBuffer) ? GL_COLOR_BUFFER_BIT : 0) |
2187               ((type != colorBuffer) ? GL_DEPTH_BUFFER_BIT : 0));
2188       if(type != colorBuffer && !oglDisplay.depthWrite)
2189       {
2190          glDepthMask((byte)bool::false);
2191       }
2192    }
2193
2194    bool ConvertBitmap(DisplaySystem displaySystem, Bitmap bitmap, PixelFormat format, ColorAlpha * palette)
2195    {
2196       return true;
2197    }
2198
2199    void Blit(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h)
2200    {
2201       OGLSurface oglSurface = surface.driverData;
2202
2203       if(!oglSurface.writingText)
2204       {
2205          // glTranslatef(-0.375f, -0.375f, 0.0f);
2206          GLSetupTexturing(true);
2207          glColor4fv(oglSurface.bitmapMult);
2208       }
2209       else if(oglSurface.xOffset)
2210          glTranslated(oglSurface.xOffset / 64.0/*-0.375*/, 0.0, 0.0);
2211
2212       glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)bitmap.driverData);
2213       glBegin(GLIMTKMode::quads);
2214
2215       if(h < 0)
2216       {
2217          glTexCoord2f((float)sx/ bitmap.width, (float)(sy-h)/ bitmap.height);
2218          glVertex2i(dx+surface.offset.x, dy+surface.offset.y);
2219          glTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy-h)/ bitmap.height);
2220          glVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
2221          glTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height);
2222          glVertex2i(dx+w+surface.offset.x, dy-h+surface.offset.y);
2223          glTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height);
2224          glVertex2i(dx+surface.offset.x, dy-h+surface.offset.y);
2225       }
2226       else
2227       {
2228          /*
2229          glTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height);
2230          glVertex2i(dx+surface.offset.x, dy+surface.offset.y);
2231          glTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height);
2232          glVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
2233          glTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy+h)/ bitmap.height);
2234          glVertex2i(dx+w+surface.offset.x, dy+h+surface.offset.y);
2235          glTexCoord2f((float)sx/ bitmap.width, (float)(sy+h)/ bitmap.height);
2236          glVertex2i(dx+surface.offset.x, dy+h+surface.offset.y);
2237          */
2238
2239          glTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height);
2240          glVertex2f((float)dx+surface.offset.x, (float)dy+surface.offset.y);
2241          glTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height);
2242          glVertex2f((float)dx+w+surface.offset.x, (float)dy+surface.offset.y);
2243          glTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy+h)/ bitmap.height);
2244          glVertex2f((float)dx+w+surface.offset.x, (float)dy+h+surface.offset.y);
2245          glTexCoord2f((float)sx/ bitmap.width, (float)(sy+h)/ bitmap.height);
2246          glVertex2f((float)dx+surface.offset.x, (float)dy+h+surface.offset.y);
2247       }
2248       glEnd();
2249
2250       if(!oglSurface.writingText)
2251       {
2252          GLSetupTexturing(false);
2253
2254          //glTranslate(0.375, 0.375, 0.0);
2255       }
2256       else if(oglSurface.xOffset)
2257          glTranslated(-oglSurface.xOffset / 64.0/*+0.375*/, 0.0, 0.0);
2258    }
2259
2260    void Stretch(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2261    {
2262       OGLSurface oglSurface = surface.driverData;
2263
2264       //glTranslate(-0.375, -0.375, 0.0);
2265
2266       GLSetupTexturing(true);
2267       glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)bitmap.driverData);
2268
2269       glColor4fv(oglSurface.bitmapMult);
2270
2271       glBegin(GLIMTKMode::quads);
2272
2273       if(h < 0)
2274       {
2275          glTexCoord2f((float)(sx)/ bitmap.width, (float)(sy+sh)/ bitmap.height);
2276          glVertex2i(dx+surface.offset.x, dy+surface.offset.y);
2277
2278          glTexCoord2f((float)(sx+sw) / bitmap.width, (float)(sy+sh)/ bitmap.height);
2279          glVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
2280
2281          glTexCoord2f((float)(sx+sw)/ bitmap.width, (float)(sy)/ bitmap.height);
2282          glVertex2i(dx+w+surface.offset.x, dy-h+surface.offset.y);
2283
2284          glTexCoord2f((float)(sx) / bitmap.width, (float)(sy)/ bitmap.height);
2285          glVertex2i(dx+surface.offset.x, dy-h+surface.offset.y);
2286       }
2287       else
2288       {
2289          glTexCoord2f((float)(sx) / bitmap.width, (float)(sy)/ bitmap.height);
2290          glVertex2i(dx+surface.offset.x, dy+surface.offset.y);
2291
2292          glTexCoord2f((float)(sx+sw)/ bitmap.width, (float)(sy)/ bitmap.height);
2293          glVertex2i(dx+w+surface.offset.x, dy+surface.offset.y);
2294
2295          glTexCoord2f((float)(sx+sw) / bitmap.width, (float)(sy+sh)/ bitmap.height);
2296          glVertex2i(dx+w+surface.offset.x, dy+h+surface.offset.y);
2297
2298          glTexCoord2f((float)(sx)/ bitmap.width, (float)(sy+sh)/ bitmap.height);
2299          glVertex2i(dx+surface.offset.x, dy+h+surface.offset.y);
2300       }
2301
2302       glEnd();
2303
2304       GLSetupTexturing(false);
2305
2306       //glTranslate(0.375, 0.375, 0.0);
2307    }
2308
2309    void Filter(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2310    {
2311       Stretch(display, surface, bitmap, dx, dy, sx, sy, w, h, sw, sh);
2312    }
2313
2314    void StretchDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2315    {
2316 #if !defined(EM_MODE)
2317       float s2dw,s2dh,d2sw,d2sh;
2318       //bool flipX = false, flipY = false;
2319
2320       //Logf("StretchDI\n");
2321
2322       if(Sgn(w) != Sgn(sw))
2323       {
2324          w = Abs(w);
2325          sw = Abs(sw);
2326          //flipX = true;
2327       }
2328       if(Sgn(h) != Sgn(sh))
2329       {
2330          h = Abs(h);
2331          sh = Abs(sh);
2332          //flipY = true;
2333       }
2334
2335       s2dw=(float)w / sw;
2336       s2dh=(float)h / sh;
2337       d2sw=(float)sw / w;
2338       d2sh=(float)sh / h;
2339
2340       //Clip against the edges of the source
2341       if(sx<0)
2342       {
2343          dx+=(int)((0-sx) * s2dw);
2344          w-=(int)((0-sx) * s2dw);
2345          sw-=0-sx;
2346          sx=0;
2347       }
2348       if(sy<0)
2349       {
2350          dy+=(int)((0-sy) * s2dh);
2351          h-=(int)((0-sy) * s2dh);
2352
2353          sh-=0-sy;
2354          sy=0;
2355       }
2356       if(sx+sw>bitmap.width-1)
2357       {
2358          w-=(int)((sx+sw-(bitmap.width-1)-1)*s2dw);
2359          sw-=sx+sw-(bitmap.width-1)-1;
2360       }
2361       if(sy+sh>(bitmap.height-1))
2362       {
2363          h-=(int)((sy+sh-(bitmap.height-1)-1)*s2dh);
2364          sh-=sy+sh-(bitmap.height-1)-1;
2365       }
2366       //Clip against the edges of the surfaceination
2367       if(dx<surface.box.left)
2368       {
2369          //if(!flip)
2370          sx+=(int)((surface.box.left-dx)*d2sw);
2371          sw-=(int)((surface.box.left-dx)*d2sw);
2372          w-=surface.box.left-dx;
2373          dx=surface.box.left;
2374       }
2375       if(dy<surface.box.top)
2376       {
2377          sy+=(int)((surface.box.top-dy)*d2sh);
2378          sh-=(int)((surface.box.top-dy)*d2sh);
2379          h-=surface.box.top-dy;
2380          dy=surface.box.top;
2381       }
2382       if(dx+w>surface.box.right)
2383       {
2384          //if(flip) sx+=(int)((dx+w-surface.box.right-1)*d2sw);
2385          sw-=(int)((dx+w-surface.box.right-1)*d2sw);
2386          w-=dx+w-surface.box.right-1;
2387       }
2388       if(dy+h>surface.box.bottom)
2389       {
2390          sh-=(int)((dy+h-surface.box.bottom-1)*d2sh);
2391          h-=dy+h-surface.box.bottom-1;
2392       }
2393       if((w<=0)||(h<=0)||(sw<=0)||(sh<=0)) return;
2394
2395       dx += surface.offset.x;
2396       dy += surface.offset.y;
2397
2398       if(bitmap.pixelFormat == pixelFormat888 && !bitmap.paletteShades)
2399       {
2400          glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
2401          glPixelStorei(GL_UNPACK_ROW_LENGTH, bitmap.stride);
2402          glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx);
2403          glPixelStorei(GL_UNPACK_SKIP_ROWS, sy);
2404 #if !defined(SHADERS)
2405          glRasterPos2d(dx,dy);
2406          //glPixelZoom(flipX ? -s2dw : s2dw, flipY ? s2dh : -s2dh);
2407          glPixelZoom(s2dw, -s2dh);
2408          glDrawPixels(sw,sh,GL_BGRA_EXT,GL_UNSIGNED_BYTE, bitmap.picture);
2409 #endif
2410          glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2411          glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
2412          glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
2413          glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
2414       }
2415 #endif
2416    }
2417
2418    void BlitDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h)
2419    {
2420 #if !defined(EM_MODE)
2421       //Logf("BlitDI\n");
2422
2423       //Clip against the edges of the source
2424       if(sx<0)
2425       {
2426          dx+=-sx;
2427          w-=-sx;
2428          sx=0;
2429       }
2430       if(sy<0)
2431       {
2432          dy+=0-sy;
2433          h-=0-sy;
2434          sy=0;
2435       }
2436       if(sx+w>bitmap.width-1)
2437          w-=sx+w-(bitmap.width-1)-1;
2438       if(sy+h>bitmap.height-1)
2439          h-=sy+h-(bitmap.height-1)-1;
2440       //Clip against the edges of the surfaceination
2441       if(dx<surface.box.left)
2442       {
2443          //if(!flip)
2444          sx+=surface.box.left-dx;
2445          w-=surface.box.left-dx;
2446          dx=surface.box.left;
2447       }
2448       if(dy<surface.box.top)
2449       {
2450          sy+=surface.box.top-dy;
2451          h-=surface.box.top-dy;
2452          dy=surface.box.top;
2453       }
2454       if(dx+w>surface.box.right)
2455       {
2456          //if(flip) sx+=dx+w-surface.box.right-1;
2457          w-=dx+w-surface.box.right-1;
2458       }
2459       if(dy+h>surface.box.bottom)
2460          h-=dy+h-surface.box.bottom-1;
2461       if((w<=0)||(h<=0))
2462          return;
2463
2464       dx += surface.offset.x;
2465       dy += surface.offset.y;
2466
2467       if(bitmap.pixelFormat == pixelFormat888 && !bitmap.paletteShades)
2468       {
2469          glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
2470          glPixelStorei(GL_UNPACK_ROW_LENGTH, bitmap.stride);
2471          glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx);
2472          glPixelStorei(GL_UNPACK_SKIP_ROWS, sy);
2473 #if !defined(SHADERS)
2474          glRasterPos2d(dx,dy);
2475          glPixelZoom(1,-1);
2476          glDrawPixels(w,h,GL_BGRA_EXT,GL_UNSIGNED_BYTE, bitmap.picture);
2477 #endif
2478          glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2479          glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
2480          glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
2481          glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
2482       }
2483 #endif
2484    }
2485
2486    void FilterDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
2487    {
2488       StretchDI(display, surface, bitmap, dx, dy, sx, sy, w, h, sw, sh);
2489    }
2490
2491    void UnloadFont(DisplaySystem displaySystem, Font font)
2492    {
2493       ((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, font);
2494    }
2495
2496    Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade)
2497    {
2498       Font font;
2499       OGLSystem oglSystem = displaySystem.driverData;
2500       oglSystem.loadingFont = true;
2501       font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags, outlineSize, outlineFade);
2502       return font;
2503    }
2504
2505    void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * adv)
2506    {
2507       ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(displaySystem, font, text, len, width, height, prevGlyph, rPrevGlyph, adv);
2508    }
2509
2510    void WriteText(Display display, Surface surface, int x, int y, const char * text, int len, int prevGlyph, int * rPrevGlyph)
2511    {
2512       OGLSurface oglSurface = surface.driverData;
2513       OGLSystem oglSystem = display.displaySystem.driverData;
2514       oglSystem.loadingFont = true;
2515
2516       //glTranslated(-0.375, -0.375, 0.0);
2517
2518       //Logf("Blit\n");
2519
2520       if(surface.textOpacity)
2521       {
2522          int w, h, adv;
2523          FontExtent(display.displaySystem, surface.font, text, len, &w, &h, 0, null, &adv);
2524          w += adv;
2525          display.displaySystem.driver.Area(display, surface,x,y,x+w-1,y+h-1);
2526       }
2527
2528       oglSurface.writingText = true;
2529
2530       GLSetupTexturing(true);
2531
2532       if(surface.font.outlineSize)
2533       {
2534          ColorAlpha outlineColor = surface.outlineColor;
2535          glColor4ub(outlineColor.color.r, outlineColor.color.g, outlineColor.color.b, outlineColor.a);
2536          oglSurface.writingOutline = true;
2537          ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len, prevGlyph, rPrevGlyph);
2538          oglSurface.writingOutline = false;
2539       }
2540       glColor4fv(oglSurface.foreground);
2541
2542       ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len, prevGlyph, rPrevGlyph);
2543       oglSurface.writingText = false;
2544       oglSystem.loadingFont = false;
2545
2546       GLSetupTexturing(false);
2547
2548       //glTranslated(0.375, 0.375, 0.0);
2549    }
2550
2551    void TextFont(Display display, Surface surface, Font font)
2552    {
2553       ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextFont(display, surface, font);
2554    }
2555
2556    void TextOpacity(Display display, Surface surface, bool opaque)
2557    {
2558       OGLSurface oglSurface = surface.driverData;
2559       oglSurface.opaqueText = opaque;
2560    }
2561
2562    void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * adv)
2563    {
2564       OGLSurface oglSurface = surface.driverData;
2565       OGLSystem oglSystem = display.displaySystem.driverData;
2566       oglSystem.loadingFont = true;
2567       FontExtent(display.displaySystem, oglSurface.font, text, len, width, height, prevGlyph, rPrevGlyph, adv);
2568       oglSystem.loadingFont = false;
2569    }
2570
2571    void DrawingChar(Display display, Surface surface, char character)
2572    {
2573
2574    }
2575
2576    void LineStipple(Display display, Surface surface, uint32 stipple)
2577    {
2578       //Logf("Stipple\n");
2579
2580       if(stipple)
2581       {
2582 #if defined(ES1_1) || defined(EM_MODE) || defined(SHADERS)
2583          stippleEnabled = true;
2584          glesLineStipple(1, (uint16)stipple);
2585 #else
2586          glLineStipple(1, (uint16)stipple);
2587          glEnable(GL_LINE_STIPPLE);
2588 #endif
2589       }
2590       else
2591       {
2592 #if defined(ES1_1) || defined(EM_MODE) || defined(SHADERS)
2593          stippleEnabled = false;
2594          glMatrixMode(GL_TEXTURE);
2595          glLoadIdentity();
2596          glMatrixMode(MatrixMode::projection);
2597          GLSetupTexturing(false);   // TODO: Special shading code for stipple?
2598 #else
2599          glDisable(GL_LINE_STIPPLE);
2600 #endif
2601       }
2602    }
2603 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
2604    void SetRenderState(Display display, RenderState state, uint value)
2605    {
2606       OGLDisplay oglDisplay = display.driverData;
2607       //Logf("RenderState\n");
2608
2609       switch(state)
2610       {
2611          case antiAlias:
2612             if(value)
2613                glEnable(GL_MULTISAMPLE_ARB);
2614             else
2615                glDisable(GL_MULTISAMPLE_ARB);
2616             break;
2617          case fillMode:
2618 #if !defined(ES1_1)
2619             glPolygonMode(GL_FRONT_AND_BACK, ((FillModeValue)value == solid) ? GL_FILL : GL_LINE);
2620 #endif
2621             break;
2622          case depthTest:
2623             if(value) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
2624             break;
2625          case depthWrite:
2626             if(value) glDepthMask((byte)bool::true); else glDepthMask((byte)bool::false);
2627             oglDisplay.depthWrite = (bool)value;
2628             break;
2629          case fogColor:
2630          {
2631 #if !defined(SHADERS)
2632             float color[4] = { ((Color)value).r/255.0f, ((Color)value).g/255.0f, ((Color)value).b/255.0f, 1.0f };
2633             glFogfv(GL_FOG_COLOR, (float *)&color);
2634 #endif
2635             break;
2636          }
2637          case fogDensity:
2638 #if !defined(SHADERS)
2639             glFogf(GL_FOG_DENSITY, (float)(RenderStateFloat { ui = value }.f * nearPlane));
2640 #endif
2641             break;
2642          case blend:
2643             if(value) glEnable(GL_BLEND); else glDisable(GL_BLEND);
2644             break;
2645          case ambient:
2646          {
2647 #if defined(SHADERS)
2648             shader_setGlobalAmbient(((Color)value).r / 255.0f, ((Color)value).g / 255.0f, ((Color)value).b / 255.0f, 1.0f);
2649 #elif !defined(EM_MODE)
2650             float ambient[4] = { ((Color)value).r/255.0f, ((Color)value).g/255.0f, ((Color)value).b/255.0f, 1.0f };
2651             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
2652 #endif
2653             break;
2654          }
2655          case alphaWrite:
2656          {
2657             if(value) glColorMask(1,1,1,1); else glColorMask(1,1,1,0);
2658             break;
2659          }
2660          case vSync:
2661          {
2662 #if defined(__WIN32__)
2663             wglSwapIntervalEXT(value ? 1 : 0);
2664 #endif
2665             break;
2666          }
2667       }
2668    }
2669
2670    void SetLight(Display display, int id, Light light)
2671    {
2672 #if defined(SHADERS)
2673       shader_setLight(display, id, light);
2674 #elif !defined(EM_MODE)
2675       //Logf("SetLight\n");
2676
2677       if(light != null)
2678       {
2679          Object lightObject = light.lightObject;
2680          float position[4] = { 0, 0, 0, 0 };
2681          float color[4] = { 0, 0, 0, 1 };
2682
2683          glEnable(GL_LIGHT0 + id);
2684          /*
2685          glLightfv(GL_LIGHT0 + id, GL_DIFFUSE, (float *)&light.diffuse);
2686          glLightfv(GL_LIGHT0 + id, GL_AMBIENT, (float *)&light.ambient);
2687          glLightfv(GL_LIGHT0 + id, GL_SPECULAR,(float *)&light.specular);
2688          */
2689
2690          if(!light.multiplier) light.multiplier = 1.0f;
2691
2692          color[0] = light.diffuse.r * light.multiplier;
2693          color[1] = light.diffuse.g * light.multiplier;
2694          color[2] = light.diffuse.b * light.multiplier;
2695          glLightfv(GL_LIGHT0 + id, GL_DIFFUSE, color);
2696
2697          color[0] = light.ambient.r * light.multiplier;
2698          color[1] = light.ambient.g * light.multiplier;
2699          color[2] = light.ambient.b * light.multiplier;
2700          glLightfv(GL_LIGHT0 + id, GL_AMBIENT, color);
2701          color[0] = light.specular.r * light.multiplier;
2702          color[1] = light.specular.g * light.multiplier;
2703          color[2] = light.specular.b * light.multiplier;
2704          glLightfv(GL_LIGHT0 + id, GL_SPECULAR,color);
2705
2706          if(lightObject)
2707          {
2708             Vector3D positionVector;
2709             if(light.flags.spot)
2710             {
2711                if(lightObject.flags.root || !lightObject.parent)
2712                {
2713                   positionVector = lightObject.transform.position;
2714                   positionVector.Subtract(positionVector, display.display3D.camera.cPosition);
2715                }
2716                else
2717                {
2718                   positionVector.MultMatrix(lightObject.transform.position, lightObject.parent.matrix);
2719                   if(display.display3D.camera)
2720                      positionVector.Subtract(positionVector, display.display3D.camera.cPosition);
2721                }
2722                position[3] = 1;
2723             }
2724             else
2725             {
2726                if(!light.direction.x && !light.direction.y && !light.direction.z)
2727                {
2728                   Vector3Df vector { 0,0,-1 };
2729                   Matrix mat;
2730                   mat.RotationQuaternion(light.orientation);
2731                   positionVector.MultMatrixf(vector, mat);
2732                }
2733                else
2734                {
2735                   positionVector = light.direction;
2736                   position[3] = 1;
2737                }
2738             }
2739
2740             position[0] = (float)positionVector.x;
2741             position[1] = (float)positionVector.y;
2742             position[2] = (float)positionVector.z;
2743
2744             glLightfv(GL_LIGHT0 + id, GL_POSITION, position);
2745
2746             /*
2747             // Display Light Position
2748             glDisable(GL_LIGHTING);
2749             glDisable(GL_DEPTH_TEST);
2750             glColor3f(1,1,1);
2751             glPointSize(10);
2752             glBegin(GL_POINTS);
2753             glVertex3fv(position);
2754             glEnd();
2755             glEnable(GL_DEPTH_TEST);
2756             glEnable(GL_LIGHTING);
2757
2758
2759             // Display Target
2760             if(lightObject.flags.root || !lightObject.parent)
2761             {
2762                positionVector = light.target.transform.position;
2763                positionVector.Subtract(positionVector, display.camera.cPosition);
2764             }
2765             else
2766             {
2767                positionVector.MultMatrix(light.target.transform.position,
2768                   lightObject.light.target.parent.matrix);
2769                positionVector.Subtract(positionVector, display.camera.cPosition);
2770             }
2771
2772             position[0] = positionVector.x;
2773             position[1] = positionVector.y;
2774             position[2] = positionVector.z;
2775
2776             glDisable(GL_LIGHTING);
2777             glDisable(GL_DEPTH_TEST);
2778             glColor3f(1,1,0);
2779             glPointSize(10);
2780             glBegin(GL_POINTS);
2781             glVertex3fv(position);
2782             glEnd();
2783             glEnable(GL_DEPTH_TEST);
2784             glEnable(GL_LIGHTING);
2785             */
2786
2787             if(light.flags.attenuation)
2788             {
2789                glLightf(GL_LIGHT0 + id, GL_CONSTANT_ATTENUATION, light.Kc);
2790                glLightf(GL_LIGHT0 + id, GL_LINEAR_ATTENUATION, light.Kl);
2791                glLightf(GL_LIGHT0 + id, GL_QUADRATIC_ATTENUATION, light.Kq);
2792             }
2793
2794             if(light.flags.spot)
2795             {
2796                float exponent = 0;
2797                #define MAXLIGHT  0.9
2798                float direction[4] = { (float)light.direction.x, (float)light.direction.y, (float)light.direction.z, 1 };
2799                // Figure out exponent out of the hot spot
2800                exponent = (float)(log(MAXLIGHT) / log(cos((light.hotSpot / 2))));
2801
2802                glLightfv(GL_LIGHT0 + id, GL_SPOT_DIRECTION, direction);
2803                glLightf(GL_LIGHT0 + id, GL_SPOT_CUTOFF, (float)(light.fallOff / 2));
2804                glLightf(GL_LIGHT0 + id, GL_SPOT_EXPONENT, exponent);
2805             }
2806          }
2807          else
2808          {
2809             Vector3Df vector { 0,0,-1 };
2810             Vector3Df direction;
2811             Matrix mat;
2812
2813             mat.RotationQuaternion(light.orientation);
2814             direction.MultMatrix(vector, mat);
2815
2816             position[0] = direction.x;
2817             position[1] = direction.y;
2818             position[2] = direction.z;
2819
2820             glLightfv(GL_LIGHT0 + id, GL_POSITION, position);
2821          }
2822       }
2823       else
2824          glDisable(GL_LIGHT0 + id);
2825 #endif
2826    }
2827
2828    void SetCamera(Display display, Surface surface, Camera camera)
2829    {
2830       OGLDisplay oglDisplay = display.driverData;
2831       //Logf("SetCamera\n");
2832
2833       if(surface && camera)
2834       {
2835          int left = surface.box.left + surface.offset.x;
2836          int top = surface.box.top  + surface.offset.y;
2837          int right = surface.box.right + surface.offset.x;
2838          int bottom = surface.box.bottom + surface.offset.y;
2839          float origX = surface.offset.x + camera.origin.x;
2840          float origY = surface.offset.y + camera.origin.y;
2841          int x = left;
2842          int y = display.height - bottom - 1;
2843          int w = right - left + 1;
2844          int h = bottom - top + 1;
2845
2846          // *** ViewPort ***
2847          glViewport(x, y, w, h);
2848
2849          // *** Projection Matrix ***
2850          glMatrixMode(MatrixMode::projection);
2851          if(!display.display3D.camera)
2852             glPushMatrix();
2853
2854          if(display.display3D.collectingHits)
2855          {
2856             float pickX = display.display3D.pickX + surface.offset.x;
2857             float pickY = display.height - (display.display3D.pickY + surface.offset.y) - 1;
2858             Matrix pickMatrix
2859             {
2860                {
2861                   w / display.display3D.pickWidth, 0, 0, 0,
2862                   0, h / display.display3D.pickHeight, 0, 0,
2863                   0, 0, 1, 0,
2864                   (w + 2.0f * (x - pickX)) / display.display3D.pickWidth,
2865                   (h + 2.0f * (y - pickY)) / display.display3D.pickHeight, 0, 1
2866                }
2867             };
2868             glLoadMatrixd(pickMatrix.array);
2869          }
2870          else
2871             glLoadIdentity();
2872          glFrustum(
2873             (left   - origX) * camera.zMin / camera.focalX,
2874             (right  - origX) * camera.zMin / camera.focalX,
2875             (bottom - origY) * camera.zMin / camera.focalY,
2876             (top    - origY) * camera.zMin / camera.focalY,
2877             camera.zMin, camera.zMax);
2878
2879          glDisable(GL_BLEND);
2880
2881          // *** Z Inverted Identity Matrix ***
2882          glMatrixMode(MatrixMode::modelView);
2883          if(!display.display3D.camera)
2884             glPushMatrix();
2885
2886          glLoadIdentity();
2887
2888          glScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane);
2889
2890          // *** View Matrix ***
2891          glMultMatrixd(camera.viewMatrix.array);
2892
2893          // *** Lights ***
2894          // ...
2895
2896          glEnable(GL_DEPTH_TEST);
2897
2898          GLSetupLighting(true);
2899 #if !defined(EM_MODE) && !defined(SHADERS)
2900          glShadeModel(GL_SMOOTH);
2901 #endif
2902          glDepthMask((byte)bool::true);
2903          oglDisplay.depthWrite = true;
2904
2905          glEnable(GL_MULTISAMPLE_ARB);
2906       }
2907       else if(surface && display.display3D.camera)
2908       {
2909          oglDisplay.depthWrite = false;
2910          glViewport(0,0,display.width,display.height);
2911
2912          glDisable(GL_CULL_FACE);
2913          glDisable(GL_DEPTH_TEST);
2914
2915          GLSetupTexturing(false);
2916          GLSetupLighting(false);
2917 #if !defined(SHADERS) && !defined(EM_MODE)
2918          glDisable(GL_FOG);
2919          glShadeModel(GL_FLAT);
2920 #endif
2921          glEnable(GL_BLEND);
2922          glDisable(GL_MULTISAMPLE_ARB);
2923
2924          // *** Restore 2D MODELVIEW Matrix ***
2925          glPopMatrix();
2926
2927          // *** Restore 2D PROJECTION Matrix ***
2928          glMatrixMode(MatrixMode::projection);
2929          glPopMatrix();
2930       }
2931
2932    }
2933
2934    void ApplyMaterial(Display display, Material material, Mesh mesh)
2935    {
2936       //Logf("ApplyMaterial\n");
2937
2938       // Basic Properties
2939       if(material.flags.doubleSided)
2940       {
2941 #if !defined(EM_MODE) && !defined(SHADERS)
2942          glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, !material.flags.singleSideLight);
2943 #endif
2944          glDisable(GL_CULL_FACE);
2945       }
2946       else
2947       {
2948 #if !defined(EM_MODE) && !defined(SHADERS)
2949          glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, bool::false);
2950 #endif
2951          glEnable(GL_CULL_FACE);
2952       }
2953
2954 #if !defined(SHADERS)
2955       // Fog
2956       if(material.flags.noFog)
2957          glDisable(GL_FOG);
2958       else
2959          glEnable(GL_FOG);
2960 #endif
2961
2962       // Maps
2963       if(material.baseMap && (mesh.texCoords || mesh.flags.texCoords1))
2964       {
2965          Bitmap map = material.baseMap;
2966          GLSetupTexturing(true);
2967          glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)map.driverData);
2968
2969          glMatrixMode(GL_TEXTURE);
2970          glLoadIdentity();
2971          if(material.uScale && material.vScale)
2972             glScalef(material.uScale, material.vScale, 1);
2973          glMatrixMode(MatrixMode::modelView);
2974
2975          if(material.flags.tile)
2976          {
2977             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
2978             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
2979          }
2980          else
2981          {
2982             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2983             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2984          }
2985       }
2986       else
2987          GLSetupTexturing(false);
2988
2989 #if defined(SHADERS)
2990       shader_setMaterial(material, mesh.flags.colors);
2991 #elif defined(EM_MODE)
2992       glimtkColor4f(material.diffuse.r, material.diffuse.g, material.diffuse.b, material.opacity);
2993 #else
2994       if(mesh.flags.colors)
2995       {
2996          glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
2997          glEnable(GL_COLOR_MATERIAL);
2998       }
2999       else
3000       {
3001          glDisable(GL_COLOR_MATERIAL);
3002          {
3003             float color[4] = { material.diffuse.r, material.diffuse.g, material.diffuse.b, material.opacity };
3004             glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);
3005          }
3006          {
3007             float color[4] = { material.ambient.r, material.ambient.g, material.ambient.b, 0 };
3008             glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color);
3009          }
3010       }
3011       {
3012          float color[4] = { material.specular.r, material.specular.g, material.specular.b, 0 };
3013          glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color);
3014       }
3015       {
3016          float color[4] = { material.emissive.r, material.emissive.g, material.emissive.b, 0 };
3017          glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color);
3018       }
3019
3020       glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &material.power);
3021 #endif
3022    }
3023
3024    void FreeMesh(DisplaySystem displaySystem, Mesh mesh)
3025    {
3026       OGLMesh oglMesh = mesh.data;
3027       if(oglMesh)
3028       {
3029          if(!mesh.flags.vertices)
3030          {
3031             oglMesh.vertices.free();
3032             delete mesh.vertices;
3033          }
3034          if(!mesh.flags.normals)
3035          {
3036             oglMesh.normals.free();
3037             delete mesh.normals;
3038          }
3039          if(!mesh.flags.texCoords1)
3040          {
3041             oglMesh.texCoords.free();
3042             delete mesh.texCoords;
3043          }
3044          if(!mesh.flags.texCoords2)
3045          {
3046             oglMesh.texCoords2.free();
3047             // delete mesh.texCoords2;
3048          }
3049          if(!mesh.flags.colors)
3050          {
3051             oglMesh.colors.free();
3052             delete mesh.colors;
3053          }
3054          if(!mesh.flags)
3055          {
3056             delete oglMesh;
3057             mesh.data = null;
3058          }
3059       }
3060    }
3061
3062    bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags, int nVertices)
3063    {
3064       bool result = false;
3065
3066       if(!mesh.data)
3067          mesh.data = OGLMesh { };
3068       if(mesh.data)
3069       {
3070          if(mesh.nVertices == nVertices)
3071          {
3072             // Same number of vertices, adding features (Leaves the other features pointers alone)
3073             if(mesh.flags != flags)
3074             {
3075                if(!mesh.flags.vertices && flags.vertices)
3076                {
3077                   if(flags.doubleVertices)
3078                   {
3079                      mesh.vertices = (Vector3Df *)new Vector3D[nVertices];
3080                   }
3081                   else
3082                      mesh.vertices = new Vector3Df[nVertices];
3083                }
3084                if(!mesh.flags.normals && flags.normals)
3085                {
3086                   if(flags.doubleNormals)
3087                   {
3088                      mesh.normals = (Vector3Df *)new Vector3D[nVertices];
3089                   }
3090                   else
3091                      mesh.normals = new Vector3Df[nVertices];
3092                }
3093                if(!mesh.flags.texCoords1 && flags.texCoords1)
3094                {
3095                   mesh.texCoords = new Pointf[nVertices];
3096                }
3097                if(!mesh.flags.colors && flags.colors)
3098                {
3099                   mesh.colors = new ColorRGBAf[nVertices];
3100                }
3101             }
3102          }
3103          else
3104          {
3105             // New number of vertices, reallocate all current and new features
3106             flags |= mesh.flags;
3107             if(flags.vertices)
3108             {
3109                if(flags.doubleVertices)
3110                {
3111                   mesh.vertices = (Vector3Df *)renew mesh.vertices Vector3D[nVertices];
3112                }
3113                else
3114                   mesh.vertices = renew mesh.vertices Vector3Df[nVertices];
3115             }
3116             if(flags.normals)
3117             {
3118                if(flags.doubleNormals)
3119                {
3120                   mesh.normals = (Vector3Df *)renew mesh.normals Vector3D[nVertices];
3121                }
3122                else
3123                   mesh.normals = renew mesh.normals Vector3Df[nVertices];
3124             }
3125             if(flags.texCoords1)
3126             {
3127                mesh.texCoords = renew mesh.texCoords Pointf[nVertices];
3128             }
3129             if(flags.colors)
3130             {
3131                mesh.colors = renew mesh.colors ColorRGBAf[nVertices];
3132             }
3133          }
3134          result = true;
3135       }
3136       return result;
3137    }
3138
3139    void UnlockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags)
3140    {
3141       OGLMesh oglMesh = mesh.data;
3142       if(!flags) flags = mesh.flags;
3143
3144       if(vboAvailable)
3145       {
3146          if(flags.vertices)
3147             oglMesh.vertices.upload(
3148                mesh.nVertices * (mesh.flags.doubleVertices ? sizeof(Vector3D) : sizeof(Vector3Df)), mesh.vertices); //, GL_STATIC_DRAW_ARB );
3149
3150          if(flags.normals)
3151             oglMesh.normals.upload(
3152                mesh.nVertices * (mesh.flags.doubleNormals ? sizeof(Vector3D) : sizeof(Vector3Df)), mesh.normals); //, GL_STATIC_DRAW_ARB );
3153
3154          if(flags.texCoords1)
3155             oglMesh.texCoords.upload(
3156                mesh.nVertices * sizeof(Pointf), mesh.texCoords); //, GL_STATIC_DRAW_ARB );
3157
3158          if(flags.colors)
3159             oglMesh.colors.upload(
3160                mesh.nVertices * sizeof(ColorRGBAf), mesh.colors); //, GL_STATIC_DRAW_ARB );
3161       }
3162    }
3163
3164    bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags)
3165    {
3166       bool result = true;
3167
3168       return result;
3169    }
3170
3171    void FreeIndices(DisplaySystem displaySystem, OGLIndices oglIndices)
3172    {
3173       if(oglIndices)
3174       {
3175          oglIndices.buffer.free();
3176          delete oglIndices.indices;
3177          delete oglIndices;
3178       }
3179    }
3180
3181    void * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
3182    {
3183       OGLIndices oglIndices = OGLIndices { };
3184       if(oglIndices)
3185       {
3186          oglIndices.indices = (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]);
3187          oglIndices.nIndices = nIndices;
3188       }
3189       return oglIndices;
3190    }
3191
3192    void UnlockIndices(DisplaySystem displaySystem, OGLIndices oglIndices, bool indices32bit, int nIndices)
3193    {
3194       if(vboAvailable)
3195       {
3196 #ifdef ES1_1
3197          if(indices32bit)
3198          {
3199             if(!oglIndices.buffer.buffer)
3200                glGenBuffers(1, &oglIndices.buffer.buffer);
3201             if(glabCurElementBuffer != oglIndices.buffer.buffer)
3202                GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, oglIndices.buffer.buffer);
3203             glimtkBufferDatai(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32) * nIndices, oglIndices.indices, GL_STATIC_DRAW_ARB);
3204          }
3205          else
3206 #endif
3207          oglIndices.buffer.upload(
3208             nIndices * (indices32bit ? sizeof(uint32) : sizeof(uint16)),
3209             oglIndices.indices); //GL_STATIC_DRAW_ARB);
3210       }
3211    }
3212
3213    uint16 * LockIndices(DisplaySystem displaySystem, OGLIndices oglIndices)
3214    {
3215
3216       return oglIndices.indices;
3217    }
3218
3219    void SelectMesh(Display display, Mesh mesh)
3220    {
3221       //Logf("SelectMesh\n");
3222
3223 #if !defined( __ANDROID__) && !defined(__APPLE__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
3224
3225 #if defined(__WIN32__)
3226       if(glUnlockArraysEXT)
3227 #endif
3228          if(!vboAvailable && display.display3D.mesh)
3229             glUnlockArraysEXT();
3230
3231 #endif
3232       if(mesh)
3233       {
3234          OGLMesh oglMesh = mesh.data;
3235
3236          // *** Vertex Stream ***
3237          glEnableClientState(GL_VERTEX_ARRAY);
3238          if(!display.display3D.collectingHits && oglMesh)
3239          {
3240             oglMesh.vertices.use(vertex, 3, (mesh.flags.doubleVertices ? GL_DOUBLE : GL_FLOAT), 0, oglMesh.vertices.buffer ? null : (double *)mesh.vertices);
3241
3242             // *** Normals Stream ***
3243             if(mesh.normals || mesh.flags.normals)
3244             {
3245                glEnableClientState(GL_NORMAL_ARRAY);
3246                oglMesh.normals.use(normal, 3, GL_FLOAT, 0, oglMesh.normals.buffer ? null : mesh.normals);
3247             }
3248             else
3249                glDisableClientState(GL_NORMAL_ARRAY);
3250
3251             // *** Texture Coordinates Stream ***
3252             if(mesh.texCoords || mesh.flags.texCoords1)
3253             {
3254                glEnableClientState(GL_TEXTURE_COORD_ARRAY);
3255                oglMesh.texCoords.use(texCoord, 2, GL_FLOAT, 0, oglMesh.texCoords.buffer ? null : mesh.texCoords);
3256             }
3257             else
3258                glDisableClientState(GL_TEXTURE_COORD_ARRAY);
3259
3260             // *** Color Stream ***
3261             if(mesh.colors || mesh.flags.colors)
3262             {
3263                glEnableClientState(GL_COLOR_ARRAY);
3264                oglMesh.colors.use(color, 4, GL_FLOAT, 0, oglMesh.colors.buffer ? null : mesh.colors);
3265             }
3266             else
3267                glDisableClientState(GL_COLOR_ARRAY);
3268          }
3269          else
3270          {
3271             noAB.use(vertex, 3, (mesh.flags.doubleVertices ? GL_DOUBLE : GL_FLOAT), 0, (double *)mesh.vertices);
3272             if((mesh.normals || mesh.flags.normals) && !display.display3D.collectingHits)
3273             {
3274                glEnableClientState(GL_NORMAL_ARRAY);
3275                noAB.use(normal, 3, GL_FLOAT, 0, mesh.normals);
3276             }
3277             else
3278                glDisableClientState(GL_NORMAL_ARRAY);
3279             if((mesh.texCoords || mesh.flags.texCoords1) && !display.display3D.collectingHits)
3280             {
3281                glEnableClientState(GL_TEXTURE_COORD_ARRAY);
3282                noAB.use(texCoord, 2, GL_FLOAT, 0, mesh.texCoords);
3283             }
3284             else
3285                glDisableClientState(GL_TEXTURE_COORD_ARRAY);
3286             if((mesh.colors || mesh.flags.colors) && !display.display3D.collectingHits)
3287             {
3288                glEnableClientState(GL_COLOR_ARRAY);
3289                noAB.use(color, 4, GL_FLOAT, 0, mesh.colors);
3290             }
3291             else
3292                glDisableClientState(GL_COLOR_ARRAY);
3293          }
3294
3295 #if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__)
3296
3297 #if defined(__WIN32__)
3298          if(glLockArraysEXT)
3299 #endif
3300             if(!vboAvailable)
3301                glLockArraysEXT(0, mesh.nVertices);
3302
3303 #endif
3304       }
3305    }
3306
3307    void DrawPrimitives(Display display, PrimitiveSingle * primitive, Mesh mesh)
3308    {
3309       //Logf("DrawPrimitives\n");
3310
3311       if(primitive->type.vertexRange)
3312          glDrawArrays(primitiveTypes[primitive->type.primitiveType], primitive->first, primitive->nVertices);
3313       else
3314       {
3315          //    *** Hoping the data won't be uploaded at all (Won't really work if another group of the mesh is using the mesh ) ***
3316          // HACK TO SPEED THINGS UP...
3317 #ifndef __ANDROID__
3318          /*GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
3319          if(primitive->nIndices < (mesh.nVertices >> 2) && !primitive->type.indices32bit)
3320          {
3321             int c;
3322             glBegin((GLIMTKMode)primitiveTypes[primitive->type.primitiveType]);
3323             if(primitive->data)
3324             {
3325                OGLIndices oglIndices = primitive->data;
3326                MeshFeatures flags = mesh.flags;
3327                for(c = 0; c<primitive->nIndices; c++)
3328                {
3329                   uint16 index = ((uint16 *) oglIndices.indices)[c];
3330                   if(flags.normals) glNormal3fv((float *)&mesh.normals[index]);
3331                   if(flags.texCoords1) glTexCoord2fv((float *)&mesh.texCoords[index]);
3332                   if(flags.colors) glColor4fv((float *)&mesh.colors[index]);
3333                   glVertex3fv((float *)&mesh.vertices[index]);
3334                }
3335             }
3336             glEnd();
3337          }
3338          else*/
3339 #endif
3340
3341          {
3342             OGLIndices oglIndices = primitive->data;
3343             GLEAB eab = ((!display.display3D.collectingHits && oglIndices) ? oglIndices.buffer : noEAB);
3344
3345             eab.draw(primitiveTypes[primitive->type.primitiveType], primitive->nIndices,
3346                primitive->type.indices32bit ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT,
3347                eab.buffer ? 0 : (oglIndices ? oglIndices.indices : primitive->indices));
3348             GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
3349          }
3350       }
3351    }
3352
3353    void PushMatrix(Display display)
3354    {
3355       glPushMatrix();
3356    }
3357
3358    void PopMatrix(Display display, bool setMatrix)
3359    {
3360       glPopMatrix();
3361    }
3362
3363    void SetTransform(Display display, Matrix transMatrix, bool viewSpace, bool useCamera)
3364    {
3365       Matrix matrix = transMatrix;
3366       Camera camera = useCamera ? display.display3D.camera : null;
3367
3368       if(viewSpace)
3369       {
3370          glLoadIdentity();
3371          glScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane);
3372       }
3373       else if(camera)
3374       {
3375          glTranslated(
3376             matrix.m[3][0] - camera.cPosition.x,
3377             matrix.m[3][1] - camera.cPosition.y,
3378             matrix.m[3][2] - camera.cPosition.z);
3379       }
3380       else
3381          glTranslated(
3382             matrix.m[3][0],
3383             matrix.m[3][1],
3384             matrix.m[3][2]);
3385
3386       matrix.m[3][0] = 0;
3387       matrix.m[3][1] = 0;
3388       matrix.m[3][2] = 0;
3389
3390       glMultMatrixd(matrix.array);
3391    }
3392 #endif
3393 }
3394
3395 public void UseSingleGLContext(bool useSingle)
3396 {
3397    useSingleGLContext = useSingle;
3398 }
3399
3400 default dllexport void *
3401 #if defined(__WIN32__)
3402 __attribute__((stdcall))
3403 #endif
3404 IS_GLGetContext(DisplaySystem displaySystem)
3405 {
3406    if(displaySystem)
3407    {
3408 #if defined(__WIN32__)
3409       OGLSystem system = displaySystem.driverData;
3410       return system.glrc;
3411 #elif defined(__ANDROID__) || defined(__ODROID__)
3412       return eglContext;
3413 #elif defined(__EMSCRIPTEN__)
3414 #else
3415       OGLSystem system = displaySystem.driverData;
3416       return system.glContext;
3417 #endif
3418    }
3419    return null;
3420 }
3421
3422 #endif