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