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