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