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