X-Git-Url: https://ecere.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ecere%2Fsrc%2Fgfx%2Fdrivers%2FOpenGLDisplayDriver.ec;h=289d9817f3f0510d0dba905199251f5dc22b47dd;hb=8d4a267a681da78408bf758106ca32be3a021dd7;hp=510618b9cc803f3636a53dd7725a2436003bb1bc;hpb=8cbb554ea793d054b76d8e83564c59550b3f12d3;p=sdk diff --git a/ecere/src/gfx/drivers/OpenGLDisplayDriver.ec b/ecere/src/gfx/drivers/OpenGLDisplayDriver.ec index 510618b..289d981 100644 --- a/ecere/src/gfx/drivers/OpenGLDisplayDriver.ec +++ b/ecere/src/gfx/drivers/OpenGLDisplayDriver.ec @@ -1,1050 +1,248 @@ -// We were using PBUFFER for alpha compositing on Linux before, but it does not seem to work, nor be required anymore. -// #define USEPBUFFER - -namespace gfx::drivers; - -// OpenGL Extensions -#if defined(__unix__) || defined(__APPLE__) - -#if !defined(__MINGW32__) -#define GL_GLEXT_PROTOTYPES -#endif - -#ifdef ECERE_MINIGLX - -//#include - -#else - -#if defined(__ANDROID__) - -#else - -#define property _property -#define new _new -#define class _class - -#define Window X11Window -#define Cursor X11Cursor -#define Font X11Font -#define Display X11Display -#define Time X11Time -#define KeyCode X11KeyCode -#define Picture X11Picture -#define uint _uint - -#include -#include -#include -#include -#include -#include -#include -#include - -#undef Window -#undef Cursor -#undef Font -#undef Display -#undef Time -#undef KeyCode -#undef Picture -#undef uint -#undef new -#undef property -#undef class - -#endif - -#endif - -#endif - -#if defined(__APPLE__) -#include -#endif - #if defined(__WIN32__) || defined(__unix__) || defined(__APPLE__) -#if defined(__WIN32__) -#define WIN32_LEAN_AND_MEAN -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0500 -#define String Sting_ -#include -#undef String +// #define DIAGNOSTICS +#if defined(_DEBUG) && !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__) + #define GL_DEBUGGING #endif -#if defined(__ANDROID__) - -#include -#include - -#else +import "Display" -#include -#include +import "glab" +import "immediate" +import "matrixStack" +import "defaultShader" -#endif +namespace gfx::drivers; -import "Display" +#include "gl123es.h" +// ********** GL PLATFORMS INCLUDES ********** +// UNIX #if defined(__unix__) || defined(__APPLE__) -#ifndef __ANDROID__ -import "XInterface" -#endif - -#endif + // EGL + #if defined(__ANDROID__) || defined(__ODROID__) + import "egl" -static double nearPlane = 1; + #if defined(__ANDROID__) + #include + #include + #define printf(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "ecere-app", __VA_ARGS__)) + #endif -#define glLoadMatrix glLoadMatrixd -#define glMultMatrix glMultMatrixd -#define glGetMatrix glGetDoublev -#define glTranslate glTranslated -#define glScale glScaled + // Emscripten + #elif defined(__EMSCRIPTEN__) + #define property _property + #define uint _uint + + #include + #include + + #undef property + #undef uint + + // GLX + #elif !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__) + #define pointer _pointer + #define GL_GLEXT_PROTOTYPES + + #define property _property + #define new _new + #define class _class + + #define Window X11Window + #define Cursor X11Cursor + #define Font X11Font + #define Display X11Display + #define Time X11Time + #define KeyCode X11KeyCode + #define Picture X11Picture + #define Glyph X11Glyph + #define uint _uint + + #include + #include + #include + #include + #include + #include + #include + #include + + #undef Window + #undef Cursor + #undef Font + #undef Display + #undef Time + #undef KeyCode + #undef Picture + #undef Glyph + #undef uint + #undef new + #undef property + #undef class + #undef pointer + + #if !defined(__APPLE__) + default GLAPI void APIENTRY glLockArraysEXT (GLint first, GLsizei count); + default GLAPI void APIENTRY glUnlockArraysEXT (void); + #endif -/* -#define glVertex3v glVertex3dv -#define glNormal3v glNormal3dv -*/ + import "XInterface" -/* -//#ifdef VERTEX_FORMAT_DOUBLE + // We were using PBUFFER for alpha compositing on Linux before, but it does not seem to work, nor be required anymore. + // #define USEPBUFFER -#define glLoadMatrix glLoadMatrixd -#define glMultMatrix glMultMatrixd -#define glGetMatrix glGetDoublev -#define glVertex3v glVertex3dv -#define glNormal3v glNormal3dv -#define glTranslate glTranslated -#define glScale glScaled -//#define GL_VERTEX_FORMAT GL_DOUBLE + #endif -#else +// Apple +#elif defined(__APPLE__) + #include -#define glLoadMatrix glLoadMatrixf -#define glMultMatrix glMultMatrixf -#define glGetMatrix glGetFloatv -#define glVertex3v glVertex3fv -#define glNormal3v glNormal3fv -#define glTranslate glTranslatef -#define glScale glScalef -//#define GL_VERTEX_FORMAT GL_FLOAT +// WGL +#elif defined(__WIN32__) + //#define WIN32_LEAN_AND_MEAN + #undef _WIN32_WINNT + #define _WIN32_WINNT 0x0502 + #define String Sting_ + #include + #undef String + #include "wglDefs.h" #endif -*/ - -#define GL_ARRAY_BUFFER_ARB 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 -#define GL_STATIC_DRAW_ARB 0x88E4 -#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 -#define GL_SEPARATE_SPECULAR_COLOR 0x81FA - -#define GL_MULTISAMPLE_ARB 0x809D #if defined(__WIN32__) +#elif !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__) +default: +private: +#endif -#define WGL_SAMPLE_BUFFERS_ARB 0x2041 -#define WGL_SAMPLES_ARB 0x2042 - -#define WGL_WGLEXT_VERSION 1 -#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 -#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 -#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 -#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 -#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 -#define WGL_DRAW_TO_WINDOW_ARB 0x2001 -#define WGL_DRAW_TO_BITMAP_ARB 0x2002 -#define WGL_ACCELERATION_ARB 0x2003 -#define WGL_NEED_PALETTE_ARB 0x2004 -#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 -#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 -#define WGL_SWAP_METHOD_ARB 0x2007 -#define WGL_NUMBER_OVERLAYS_ARB 0x2008 -#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 -#define WGL_TRANSPARENT_ARB 0x200A -#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 -#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 -#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 -#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A -#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B -#define WGL_SHARE_DEPTH_ARB 0x200C -#define WGL_SHARE_STENCIL_ARB 0x200D -#define WGL_SHARE_ACCUM_ARB 0x200E -#define WGL_SUPPORT_GDI_ARB 0x200F -#define WGL_SUPPORT_OPENGL_ARB 0x2010 -#define WGL_DOUBLE_BUFFER_ARB 0x2011 -#define WGL_STEREO_ARB 0x2012 -#define WGL_PIXEL_TYPE_ARB 0x2013 -#define WGL_COLOR_BITS_ARB 0x2014 -#define WGL_RED_BITS_ARB 0x2015 -#define WGL_RED_SHIFT_ARB 0x2016 -#define WGL_GREEN_BITS_ARB 0x2017 -#define WGL_GREEN_SHIFT_ARB 0x2018 -#define WGL_BLUE_BITS_ARB 0x2019 -#define WGL_BLUE_SHIFT_ARB 0x201A -#define WGL_ALPHA_BITS_ARB 0x201B -#define WGL_ALPHA_SHIFT_ARB 0x201C -#define WGL_ACCUM_BITS_ARB 0x201D -#define WGL_ACCUM_RED_BITS_ARB 0x201E -#define WGL_ACCUM_GREEN_BITS_ARB 0x201F -#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 -#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 -#define WGL_DEPTH_BITS_ARB 0x2022 -#define WGL_STENCIL_BITS_ARB 0x2023 -#define WGL_AUX_BUFFERS_ARB 0x2024 -#define WGL_NO_ACCELERATION_ARB 0x2025 -#define WGL_GENERIC_ACCELERATION_ARB 0x2026 -#define WGL_FULL_ACCELERATION_ARB 0x2027 -#define WGL_SWAP_EXCHANGE_ARB 0x2028 -#define WGL_SWAP_COPY_ARB 0x2029 -#define WGL_SWAP_UNDEFINED_ARB 0x202A -#define WGL_TYPE_RGBA_ARB 0x202B -#define WGL_TYPE_COLORINDEX_ARB 0x202C -#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 -#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 -#define WGL_DRAW_TO_PBUFFER_ARB 0x202D -#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E -#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F -#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 -#define WGL_PBUFFER_LARGEST_ARB 0x2033 -#define WGL_PBUFFER_WIDTH_ARB 0x2034 -#define WGL_PBUFFER_HEIGHT_ARB 0x2035 -#define WGL_PBUFFER_LOST_ARB 0x2036 -#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 -#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 -#define WGL_DRAW_TO_WINDOW_EXT 0x2001 -#define WGL_DRAW_TO_BITMAP_EXT 0x2002 -#define WGL_ACCELERATION_EXT 0x2003 -#define WGL_NEED_PALETTE_EXT 0x2004 -#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 -#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 -#define WGL_SWAP_METHOD_EXT 0x2007 -#define WGL_NUMBER_OVERLAYS_EXT 0x2008 -#define WGL_NUMBER_UNDERLAYS_EXT 0x2009 -#define WGL_TRANSPARENT_EXT 0x200A -#define WGL_TRANSPARENT_VALUE_EXT 0x200B -#define WGL_SHARE_DEPTH_EXT 0x200C -#define WGL_SHARE_STENCIL_EXT 0x200D -#define WGL_SHARE_ACCUM_EXT 0x200E -#define WGL_SUPPORT_GDI_EXT 0x200F -#define WGL_SUPPORT_OPENGL_EXT 0x2010 -#define WGL_DOUBLE_BUFFER_EXT 0x2011 -#define WGL_STEREO_EXT 0x2012 -#define WGL_PIXEL_TYPE_EXT 0x2013 -#define WGL_COLOR_BITS_EXT 0x2014 -#define WGL_RED_BITS_EXT 0x2015 -#define WGL_RED_SHIFT_EXT 0x2016 -#define WGL_GREEN_BITS_EXT 0x2017 -#define WGL_GREEN_SHIFT_EXT 0x2018 -#define WGL_BLUE_BITS_EXT 0x2019 -#define WGL_BLUE_SHIFT_EXT 0x201A -#define WGL_ALPHA_BITS_EXT 0x201B -#define WGL_ALPHA_SHIFT_EXT 0x201C -#define WGL_ACCUM_BITS_EXT 0x201D -#define WGL_ACCUM_RED_BITS_EXT 0x201E -#define WGL_ACCUM_GREEN_BITS_EXT 0x201F -#define WGL_ACCUM_BLUE_BITS_EXT 0x2020 -#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 -#define WGL_DEPTH_BITS_EXT 0x2022 -#define WGL_STENCIL_BITS_EXT 0x2023 -#define WGL_AUX_BUFFERS_EXT 0x2024 -#define WGL_NO_ACCELERATION_EXT 0x2025 -#define WGL_GENERIC_ACCELERATION_EXT 0x2026 -#define WGL_FULL_ACCELERATION_EXT 0x2027 -#define WGL_SWAP_EXCHANGE_EXT 0x2028 -#define WGL_SWAP_COPY_EXT 0x2029 -#define WGL_SWAP_UNDEFINED_EXT 0x202A -#define WGL_TYPE_RGBA_EXT 0x202B -#define WGL_TYPE_COLORINDEX_EXT 0x202C -#define WGL_DRAW_TO_PBUFFER_EXT 0x202D -#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E -#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F -#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 -#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 -#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 -#define WGL_PBUFFER_LARGEST_EXT 0x2033 -#define WGL_PBUFFER_WIDTH_EXT 0x2034 -#define WGL_PBUFFER_HEIGHT_EXT 0x2035 -#define WGL_DEPTH_FLOAT_EXT 0x2040 -#define WGL_SAMPLE_BUFFERS_3DFX 0x2060 -#define WGL_SAMPLES_3DFX 0x2061 -#define WGL_SAMPLE_BUFFERS_EXT 0x2041 -#define WGL_SAMPLES_EXT 0x2042 -#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 -#define WGL_GENLOCK_SOURCE_EXTENAL_SYNC_I3D 0x2045 -#define WGL_GENLOCK_SOURCE_EXTENAL_FIELD_I3D 0x2046 -#define WGL_GENLOCK_SOURCE_EXTENAL_TTL_I3D 0x2047 -#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 -#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 -#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A -#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B -#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C -#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E -#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F -#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 -#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 -#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 -#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 -#define WGL_ARB_buffer_region 1 -#define WGL_ARB_extensions_string 1 -#define WGL_ARB_pixel_format 1 -#define WGL_ARB_make_current_read 1 -#define WGL_ARB_pbuffer 1 -#define WGL_EXT_display_color_table 1 -#define WGL_EXT_extensions_string 1 -#define WGL_EXT_make_current_read 1 -#define WGL_EXT_pbuffer 1 -#define WGL_EXT_pixel_format 1 -#define WGL_EXT_swap_control 1 -#define WGL_WGL_EXT_depth_float 1 -#define WGL_WGL_3DFX_multisample 1 -#define WGL_WGL_EXT_multisample 1 -#define WGL_NV_allocate_memory 1 - -/* -typedef void (APIENTRY * PFNGLACTIVETEXTUREARBPROC) (GLenum target); -typedef void (APIENTRY * PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t); -typedef void (APIENTRY * PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum target); -typedef void (APIENTRY * PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count); -typedef void (APIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void); -*/ - -/* -typedef int (APIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer); -typedef int (APIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers); -typedef int (APIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers); -typedef int (APIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, int size, const GLvoid *data, GLenum usage); +/* OpenGL Versions Features Quick Reference + + | OpenGL 1.1 | OpenGL 1.5 | GL ES 1.1 | OpenGL 2 | GL 3 (Compat) | GL 3 (Core) | GL ES 2 | WebGL 1 | GL ES 3 | WebGL 2 + ======================================================================================================================================================================= + glBegin() | X | X | - | X | X | - | - | - | - | - + glLoadMatrix() | X | X | - | X | X | - | - | - | - | - + glLineWidth() | X | X | - | X | X | - | - | - | - | - + glPointSize() | X | X | - | X | X | - | - | - | - | - + glLineStipple() | X | X | - | X | X | - | - | - | - | - + glPolygonStipple() | X | X | - | X | X | - | - | - | - | - + glColorMaterial() | X | X | - | X | X | - | - | - | - | - + GL_QUADS | X | X | - | X | X | - | - | - | - | - + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + GL_INT / GL_DOUBLE | X | X | - | X | X | X | - | - | - | - + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + GL_SELECT | X | X | - | (Slow) | (Slow) | (Slow) | - | - | - | - + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Non ² Textures | - | - | - | X | X | X | - | - | - | - + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + glVertexPointer() (PTR) | X | X | X | X | X | - | - | - | - | - + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + glVertexPointer() (VBO) | - | X | X | X | X | - | - | - | - | - + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + glBufferData() | - | X | X | X | X | X | X | X | X | X + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + glMapBuffer() | - | X | OES x | X | X | X | OES x | - | OES x | - + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + glBindFramebuffer() | - | - | OES x | - | X | X | X | X | X | X + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + glVertexAttribPointer() (PTR) | - | - | - | X | X | X | X | - | X | - + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + glVertexAttribPointer() (VBO) | - | - | - | X | X | X | X | X | X | X + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + GLSL Version | - | - | - | 1.10 | 1.30 | 1.30 | 1.00 | 1.00 | 3.00 | 3.00 + ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- + bool legacy :1; // | X | X | - | X | X | - | - | - | - | - + bool shaders :1; // | - | - | - | X | X | X | X | X | X | X + bool nonPow2Textures :1; // | - | - | - | X | X | X | - | - | - | - + bool vertexBuffer :1; // | - | X | X | X | X | X | X | X | X | X + bool frameBuffer :1; // | - | - | ~ | - | X | X | X | X | X | X +// bool mapBuffer :1; // | - | X | ~ | X | X | X | ~ | - | ~ | - */ -typedef int (APIENTRY * PFNWGLCHOOSEPIXELFORMATARBPROC) (); -typedef void * (APIENTRY * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); -typedef HDC (APIENTRY * PFNWGLGETPBUFFERDCARBPROC) (void * hPbuffer); -typedef int (APIENTRY * PFNWGLRELEASEPBUFFERDCARBPROC) (void * hPbuffer, HDC hDC); -typedef BOOL (APIENTRY * PFNWGLDESTROYPBUFFERARBPROC) (void * hPbuffer); -typedef BOOL (APIENTRY * PFNWGLQUERYPBUFFERARBPROC) (void * hPbuffer, int iAttribute, int *piValue); -typedef const char * (APIENTRY * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); -typedef BOOL (APIENTRY * PFNWGLBINDTEXIMAGEARBPROC) (void * hPbuffer, int iBuffer); -typedef BOOL (APIENTRY * PFNWGLRELEASETEXIMAGEARBPROC) (void * hPbuffer, int iBuffer); - -static PFNGLMAPBUFFERARBPROC glMapBufferARB = null; -static PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = null; -static PFNGLACTIVETEXTUREARBPROC glActiveTextureARB = null; -static PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB = null; -static PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB = null; -static PFNGLLOCKARRAYSEXTPROC glLockArraysEXT = null; -static PFNGLUNLOCKARRAYSEXTPROC glUnlockArraysEXT = null; -static PFNGLBLENDFUNCSEPARATEPROC glBlendFuncSeparate = null; - -static PFNGLGENBUFFERSARBPROC glGenBuffersARB = null; -static PFNGLBINDBUFFERARBPROC glBindBufferARB = null; -static PFNGLBUFFERDATAARBPROC glBufferDataARB = null; -static PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = null; -static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = null; -static PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = null; -static PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB = null; -static PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB = null; -static PFNWGLQUERYPBUFFERARBPROC wglQueryPbufferARB = null; -static PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB = null; -static PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB = null; -static PFNWGLBINDTEXIMAGEARBPROC wglBindTexImageARB = null; -static PFNWGLRELEASETEXIMAGEARBPROC wglReleaseTexImageARB = null; - -#ifdef WGL_WGLEXT_PROTOTYPES -extern BOOL WINAPI wglSwapIntervalEXT (int); -extern int WINAPI wglGetSwapIntervalEXT (void); -#endif /* WGL_WGLEXT_PROTOTYPES */ -typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); -typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); - -static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; - -#else - -#if defined(__ANDROID__) - -// Our own matrix stack -static Matrix matrixStack[3][32]; -static int matrixIndex[3]; -static int curStack = 0; - -// OpenGL ES Porting Kit - -#define glBindFramebuffer glBindFramebufferOES -#define glBindRenderbuffer glBindRenderbufferOES -#define GL_FRAMEBUFFER GL_FRAMEBUFFER_OES -#define GL_RENDERBUFFER GL_RENDERBUFFER_OES -#define glFramebufferTexture2D glFramebufferTexture2DOES -#define GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_OES -#define glGenFramebuffers glGenFramebuffersOES -#define glGenRenderbuffers glGenRenderbuffersOES -#define glDeleteFramebuffers glDeleteFramebuffersOES -#define glDeleteRenderbuffers glDeleteRenderbuffersOES - -#define GL_POLYGON_STIPPLE 0xFFFF -#define GL_LINE_STIPPLE 0xFFFF -#define GL_LINE 0xFFFF -#define GL_FILL 0xFFFF -#define GL_ALL_ATTRIB_BITS 0xFFFF -#define GL_LIGHT_MODEL_LOCAL_VIEWER 0xFFFF -#define glDrawElementsi(type, count, start) glDrawElements(type, count, GL_UNSIGNED_SHORT, start) - -#define GL_UNSIGNED_INT 0x1405 -#define GL_DOUBLE 0x140A - -#define GL_POLYGON 9 -#define GL_QUADS 7 - -#define glBufferDatai glesBufferDatai -#define glBufferDatad glesBufferDatad -#define glVertexPointeri glesVertexPointeri -#define glVertexPointerd glesVertexPointerd - -#define glRecti glesRecti -#define glBegin glesBegin -#define glTexCoord2i glesTexCoord2i -#define glVertex2i glesVertex2i -#define glTexCoord2d glesTexCoord2d -#define glVertex2d glesVertex2d -#define glTexCoord2f glesTexCoord2f -#define glVertex2f glesVertex2f -#define glEnd glesEnd -#define glColor3f glesColor3f -#define glColor4ub glesColor4ub -#define glColor4fv glesColor4fv -#define glLineStipple glesLineStipple -#define glNormal3fv glesNormal3fv -#define glTexCoord2fv glesTexCoord2fv -#define glColorMaterial glesColorMaterial - -#define glLoadMatrixd glesLoadMatrixd -#define glMultMatrixd glesMultMatrixd -#define glFrustum glesFrustum -#define glOrtho glesOrtho -#define glScaled glesScaled -#define glTranslated glesTranslated -#define glRotated glesRotated -#define glVertex3d glesVertex3d -#define glVertex3f glesVertex3f -#define glVertex3fv glesVertex3fv -#define glLightModeli glesLightModeli - -#define APIENTRY -//#define GL_QUADS 0 -#define GL_QUAD_STRIP 0 -//#define GL_DOUBLE 0 -//#define GL_UNSIGNED_INT 0 -//#define GL_FILL 0 -//#define GL_LINE 0 -//#define GL_LINE_STIPPLE 0 -#define GL_BGRA_EXT 0 -#define GL_UNPACK_ROW_LENGTH 0 -#define GL_UNPACK_SKIP_PIXELS 0 -#define GL_UNPACK_SKIP_ROWS 0 -#define GL_RGBA8 0 -#define GL_PACK_ROW_LENGTH 0 -#define GL_PACK_SKIP_ROWS 0 -#define GL_PACK_SKIP_PIXELS 0 - -static EGLDisplay eglDisplay; -static EGLSurface eglSurface; -static EGLContext eglContext; -static int eglWidth, eglHeight; - -static bool egl_init_display(ANativeWindow* window) -{ - const EGLint attribs[] = - { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_BLUE_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_RED_SIZE, 8, - EGL_DEPTH_SIZE, 24, - /*EGL_SAMPLE_BUFFERS, 1, - EGL_SAMPLES, 0, //2,*/ - EGL_NONE - }; - EGLint w, h, format; - EGLint numConfigs; - EGLConfig config; - EGLSurface surface; - EGLContext context; - - EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - eglInitialize(display, 0, 0); - eglChooseConfig(display, attribs, &config, 1, &numConfigs); - eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format); - - surface = eglCreateWindowSurface(display, config, window, null); - context = eglCreateContext(display, config, null, null); - - if(!eglMakeCurrent(display, surface, surface, context)) - return false; - - eglQuerySurface(display, surface, EGL_WIDTH, &w); - eglQuerySurface(display, surface, EGL_HEIGHT, &h); - - eglDisplay = display; - eglContext = context; - eglSurface = surface; - eglWidth = w; - eglHeight = h; - - glEnableClientState(GL_VERTEX_ARRAY); - /* - // Initialize GL state. - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); - glEnable(GL_CULL_FACE); - glShadeModel(GL_SMOOTH); - glDisable(GL_DEPTH_TEST); - */ - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - - matrixStack[0][0].Identity(); - matrixStack[1][0].Identity(); - matrixStack[2][0].Identity(); - - glesMatrixMode(GL_MODELVIEW); - glScaled(1.0, 1.0, -1.0); - glesMatrixMode(GL_PROJECTION); - glShadeModel(GL_FLAT); - - glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); - glFogi(GL_FOG_MODE, GL_EXP); - glFogf(GL_FOG_DENSITY, 0); - glEnable(GL_NORMALIZE); - glDepthFunc(GL_LESS); - glClearDepth(1.0); - glDisable(GL_MULTISAMPLE_ARB); - - glViewport(0,0,w,h); - glesLoadIdentity(); - glOrtho(0,w,h,0,0.0,1.0); - - currentVertexBuffer = 0; - return true; -} - -static void egl_term_display() -{ - if(stippleTexture) - { - glDeleteTextures(1, &stippleTexture); - stippleTexture = 0; - } - if(eglDisplay != EGL_NO_DISPLAY) - { - eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if(eglContext != EGL_NO_CONTEXT) - eglDestroyContext(eglDisplay, eglContext); - if(eglSurface != EGL_NO_SURFACE) - eglDestroySurface(eglDisplay, eglSurface); - eglTerminate(eglDisplay); - } - eglDisplay = EGL_NO_DISPLAY; - eglContext = EGL_NO_CONTEXT; - eglSurface = EGL_NO_SURFACE; -} - -// OpenGL Immediate Mode Porting Kit -static int beginCount; -static int vertexCount; -static int normalCount; -static float *vertexPointer; -static float *normalPointer; -static GLenum beginMode; -static unsigned int beginBufferSize, normalBufferSize; -static int numVertexCoords = 2; - -void glesRecti(int a, int b, int c, int d) -{ - glBegin(GL_QUADS); - glVertex2i(a, b); - glVertex2i(a, d); - glVertex2i(c, d); - glVertex2i(c, b); - glEnd(); -} - -void glesBegin(GLenum mode) -{ - beginMode = mode; - beginCount = 0; - vertexCount = 0; - if(!vertexPointer) - { - normalBufferSize = beginBufferSize = 1024; // default number of vertices - vertexPointer = new float[beginBufferSize * 5]; - normalPointer = new float[normalBufferSize * 3]; - } -} - -void glesTexCoord2f(float x, float y) -{ - int count = vertexCount; - - if(vertexCount + numVertexCoords > beginBufferSize) - { - beginBufferSize = beginBufferSize + beginBufferSize/2; - vertexPointer = renew vertexPointer float[beginBufferSize * 5]; - } - - vertexPointer[count*(2+numVertexCoords) ] = x; - vertexPointer[count*(2+numVertexCoords)+1] = y; - count++; - - if(beginMode == GL_QUADS && ((beginCount % 4) == 3)) - { - vertexPointer[count*(2+numVertexCoords) ] = vertexPointer[(count-4)*(2+numVertexCoords)]; - vertexPointer[count*(2+numVertexCoords)+1] = vertexPointer[(count-4)*(2+numVertexCoords)+1]; - count++; - vertexPointer[count*(2+numVertexCoords) ] = vertexPointer[(count-3)*(2+numVertexCoords)]; - vertexPointer[count*(2+numVertexCoords)+1] = vertexPointer[(count-3)*(2+numVertexCoords)+1]; - count++; - } -} -void glesTexCoord2i(int x, int y) { glesTexCoord2f((float)x, (float)y); } -void glesTexCoord2d(double x, double y) { glesTexCoord2f((float)x, (float)y); } -void glesTexCoord2fv(float * a) { glesTexCoord2f(a[0], a[1]); } - -void glesVertex2f(float x, float y) -{ - numVertexCoords = 2; - if(vertexCount + 4 > beginBufferSize) - { - beginBufferSize = beginBufferSize + beginBufferSize/2; - vertexPointer = renew vertexPointer float[beginBufferSize * 5]; - } - - vertexPointer[vertexCount*4+2] = x; - vertexPointer[vertexCount*4+3] = y; - vertexCount++; - - if(beginMode == GL_QUADS && ((beginCount % 4) == 3)) - { - vertexPointer[vertexCount*4+2] = vertexPointer[(vertexCount-4)*4+2]; - vertexPointer[vertexCount*4+3] = vertexPointer[(vertexCount-4)*4+3]; - vertexCount++; - vertexPointer[vertexCount*4+2] = vertexPointer[(vertexCount-3)*4+2]; - vertexPointer[vertexCount*4+3] = vertexPointer[(vertexCount-3)*4+3]; - vertexCount++; - } - beginCount++; -} -void glesVertex2i(int x, int y) { glesVertex2f((float)x, (float)y); } -void glesVertex2d(double x, double y) { glesVertex2f((float)x, (float)y); } - -void glesEnd(void) -{ - int mode = beginMode; - if(mode == GL_QUADS) mode = GL_TRIANGLES; - else if(mode == GL_POLYGON) mode = GL_TRIANGLE_FAN; - GLSelectVBO(0); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(numVertexCoords, GL_FLOAT, (numVertexCoords+2)*sizeof(float),vertexPointer); - glVertexPointer (numVertexCoords, GL_FLOAT, (numVertexCoords+2)*sizeof(float),vertexPointer+2); - if(normalCount && normalCount == vertexCount) - { - glEnableClientState(GL_NORMAL_ARRAY); - glNormalPointer (GL_FLOAT, 3*sizeof(float),normalPointer); - } - - glDrawArrays(mode, 0, vertexCount); - if(normalCount) - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - normalCount = 0; -} - -// Vertex Pointer -static float *floatVPBuffer = null; -static short *shortVPBuffer = null; -static unsigned int shortVPSize = 0, floatVPSize = 0; - -// Buffer Data -//static float *floatVPBuffer = null; // For floats we reuse floatVPBuffer -static unsigned short *shortBDBuffer = null; -static unsigned int shortBDSize = 0/*, floatVPSize = 0*/; - -void glesVertexPointeri(int numCoords, int stride, int *pointer, int numVertices) -{ - if(pointer) - { - int i; - if(numVertices*numCoords > shortVPSize) - { - shortVPSize = numVertices*numCoords; - shortVPBuffer = renew shortVPBuffer short[shortVPSize]; - } - for(i = 0; i < numVertices*numCoords; i++) - shortVPBuffer[i] = (short)pointer[i]; - glVertexPointer(numCoords, GL_SHORT, stride, shortVPBuffer); - } - else - glVertexPointer(numCoords, GL_SHORT, stride, 0); -} - -void glesVertexPointerd(int numCoords, int stride, double *pointer, int numVertices) -{ - if(pointer) - { - int i; - if(numVertices*numCoords > floatVPSize) - { - floatVPSize = numVertices*numCoords; - floatVPBuffer = renew floatVPBuffer float[floatVPSize]; - } - for(i = 0; i < numVertices*numCoords; i++) - floatVPBuffer[i] = (float)pointer[i]; - glVertexPointer(numCoords, GL_FLOAT, stride, floatVPBuffer); - } - else - glVertexPointer(numCoords, GL_FLOAT, stride, 0); -} - -void glesTexReuseIntVP(int numCoords) -{ - glTexCoordPointer(numCoords, GL_SHORT, 0, floatVPBuffer); -} - -void glesTexReuseDoubleVP(int numCoords) -{ - glTexCoordPointer(numCoords, GL_FLOAT, 0, floatVPBuffer); -} - -void glesColor3f( float r, float g, float b ) -{ - glColor4f(r, g, b, 1.0f); -} - -void glesColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a) -{ - glColor4f(r/255.0f, g/255.0f, b/255.0f, a/255.0f); -} - -void glesColor4fv(float * a) -{ - glColor4f(a[0], a[1], a[2], a[3]); -} - -void glesBufferDatad(int target, int size, void * data, int usage) -{ - int numElems = size/sizeof(double); - double * dblPtr = (double *)data; - int i; - if (numElems > floatVPSize) - { - floatVPSize = numElems; - floatVPBuffer = renew floatVPBuffer float[floatVPSize]; - } - for (i=0; i< numElems; i++) - floatVPBuffer[i] = (float)dblPtr[i]; - - glBufferData(target, numElems*sizeof(float), floatVPBuffer, usage); -} - -void glesBufferDatai(int target, int size, void * data, int usage) -{ - int numElems = size/sizeof(unsigned int); - unsigned int * pointer = (unsigned int *)data; - int i; - if (numElems > shortBDSize) - { - shortBDSize = numElems; - shortBDBuffer = renew shortBDBuffer uint16[shortBDSize]; - } - for (i=0; i< numElems; i++) - shortBDBuffer[i] = (unsigned short)pointer[i]; - - glBufferData(target, numElems*sizeof(unsigned short), shortBDBuffer, usage); -} - -// *** Our Custom Matrix Stack *** - -static void LoadCurMatrix() -{ - double * i = matrixStack[curStack][matrixIndex[curStack]].array; - float m[16] = - { - (float)i[0],(float)i[1],(float)i[2],(float)i[3], - (float)i[4],(float)i[5],(float)i[6],(float)i[7], - (float)i[8],(float)i[9],(float)i[10],(float)i[11], - (float)i[12],(float)i[13],(float)i[14],(float)i[15] - }; - glLoadMatrixf(m); -} - -void glesLoadIdentity() -{ - matrixStack[curStack][matrixIndex[curStack]].Identity(); - LoadCurMatrix(); -} - -void glesPushMatrix() -{ - if(matrixIndex[curStack] + 1 < sizeof(matrixStack[0]) / sizeof(Matrix)) - { - matrixIndex[curStack]++; - memcpy(matrixStack[curStack][matrixIndex[curStack]].array, matrixStack[curStack][matrixIndex[curStack]-1].array, sizeof(Matrix)); - } -} - -void glesPopMatrix() -{ - if(matrixIndex[curStack] > 0) - { - matrixIndex[curStack]--; - LoadCurMatrix(); - } -} - -void glesLoadMatrixd(double * i) -{ - memcpy(matrixStack[curStack][matrixIndex[curStack]].array, i, sizeof(Matrix)); - LoadCurMatrix(); -} - -void glesOrtho( double l, double r, double b, double t, double n, double f ) -{ - Matrix m - { { - (2 / (r - l)), 0, 0, 0, - 0, (2 / (t - b)), 0, 0, - 0, 0, (-2 / (f - n)), 0, - (-(r + l) / (r - l)), (-(t + b) / (t - b)), (-(f + n) / (f - n)), 1 - } }; - Matrix res; - res.Multiply(m, matrixStack[curStack][matrixIndex[curStack]]); - matrixStack[curStack][matrixIndex[curStack]] = res; - LoadCurMatrix(); -} - -void glesFrustum( double l, double r, double b, double t, double n, double f ) -{ - nearPlane = n; - n = 1; - l /= nearPlane; - r /= nearPlane; - b /= nearPlane; - t /= nearPlane; - f /= nearPlane; - { - double A = ((r + l) / (r - l)); - double B = ((t + b) / (t - b)); - double C = (-(f + n) / (f - n)); - double D = (-2*f*n/(f-n)); - Matrix m - { { - (2.0*n / (r - l)), 0, 0, 0, - 0, (2.0*n / (t - b)), 0, 0, - A, B, C,-1, - 0, 0, D, 0 - } }; - Matrix res; - res.Multiply(m, matrixStack[curStack][matrixIndex[curStack]]); - matrixStack[curStack][matrixIndex[curStack]] = res; - LoadCurMatrix(); - } -} - -void glesRotated( double a, double b, double c, double d ) -{ - Matrix m; - Quaternion q; - q.RotationAxis({(float)b,(float)-c,(float)d}, a ); - m.RotationQuaternion(q); - matrixStack[curStack][matrixIndex[curStack]].Rotate(q); - LoadCurMatrix(); -} -void glesScaled( double a, double b, double c ) -{ - Matrix m, r; - - m.Identity(); - m.Scale(a,b,c); - r.Multiply(m, matrixStack[curStack][matrixIndex[curStack]]); - matrixStack[curStack][matrixIndex[curStack]] = r; - LoadCurMatrix(); -} - -void glesTranslated( double a, double b, double c ) -{ - Matrix m, r; - - m.Identity(); - m.Translate(a,b,c); - r.Multiply(m, matrixStack[curStack][matrixIndex[curStack]]); - matrixStack[curStack][matrixIndex[curStack]] = r; - LoadCurMatrix(); -} - -void glesMultMatrixd( double * i ) -{ - Matrix r; - r.Multiply((Matrix *)i, matrixStack[curStack][matrixIndex[curStack]]); - matrixStack[curStack][matrixIndex[curStack]] = r; - LoadCurMatrix(); -} - -void glesMatrixMode(int mode) -{ - curStack = mode == GL_MODELVIEW ? 0 : mode == GL_PROJECTION ? 1 : 2; - glMatrixMode(mode); -} -#define glPushMatrix glesPushMatrix -#define glPopMatrix glesPopMatrix -#define glLoadIdentity glesLoadIdentity -#define glMatrixMode glesMatrixMode +default: +// Capabilities Global set to capabilities of Display being rendered to +GLCapabilities glCaps; +// Requiring Graphics Reload: +bool glCaps_nonPow2Textures, glCaps_vertexBuffer, glCaps_quads, glCaps_intAndDouble, glCaps_legacyFormats, glCaps_compatible, glCaps_vertexPointer; +// Might toggle without Reload: +bool glCaps_core, glCaps_shaders, glCaps_fixedFunction, glCaps_immediate, glCaps_legacy, glCaps_pointSize, glCaps_frameBuffer, glCaps_vao, glCaps_select; +// bool mapBuffer; +private: -/* Using the built-in matrix stack -void glesLoadMatrixd( double * i ) -{ - float m[16] = - { - (float)i[0],(float)i[1],(float)i[2],(float)i[3], - (float)i[4],(float)i[5],(float)i[6],(float)i[7], - (float)i[8],(float)i[9],(float)i[10],(float)i[11], - (float)i[12],(float)i[13],(float)i[14],(float)i[15] - }; - glLoadMatrixf(m); -} -void glesOrtho( double l, double r, double b, double t, double n, double f ) -{ - float matrix[4][4] = - { - { (float)(2 / (r - l)), 0, 0, 0 }, - { 0, (float)(2 / (t - b)), 0, 0 }, - { 0, 0, (float)(-2 / (f - n)), 0 }, - { (float)(-(r + l) / (r - l)), (float)(-(t + b) / (t - b)), (float)(-(f + n) / (f - n)), 1 } - }; - glMultMatrixf((float *)matrix); -} - -void glesFrustum( double l, double r, double b, double t, double n, double f ) -{ - float A = (float)((r + l) / (r - l)); - float B = (float)((t + b) / (t - b)); - float C = (float)(-(f + n) / (f - n)); - float D = (float)(-2*f*n/(f-n)); - float matrix[4][4] = - { - { (float)(2*n / (r - l)), 0, 0, 0 }, - { 0, (float)(2*n / (t - b)), 0, 0 }, - { A, B, C,-1 }, - { 0, 0, D, 0 } - }; - glMultMatrixf((float *)matrix); -} - -void glesRotated( double a, double b, double c, double d ) { glRotatef((float)a, (float)b, (float)c, (float)d); } -void glesScaled( double a, double b, double c ) { glScalef((float)a, (float)b, (float)c); } -void glesTranslated( double a, double b, double c ) { glTranslatef((float)a, (float)b, (float)c); } - -void glesMultMatrixd( double * i ) +// ********** Errors and Debugging ********** +/* +void CheckGLErrors() { - float m[16] = - { - (float)i[0], (float)i[1], (float)i[2], (float)i[3], - (float)i[4], (float)i[5], (float)i[6], (float)i[7], - (float)i[8], (float)i[9], (float)i[10], (float)i[11], - (float)i[12], (float)i[13], (float)i[14], (float)i[15] - }; - glMultMatrixf(m); + int e, nCount = 0; + while((e = glGetError()) && nCount++ < 10) + printf("GL error %d!\n", e); } */ - -// Need to do these... -void glesVertex3f( float x, float y, float z ) +#ifdef GL_DEBUGGING +#ifndef APIENTRY + #define APIENTRY +#endif +static void APIENTRY openglCallbackFunction(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam) { - numVertexCoords = 3; - if(vertexCount + 4 > beginBufferSize) + if(severity == GL_DEBUG_SEVERITY_NOTIFICATION) + return; + PrintLn("---------------------opengl-callback-start------------"); + PrintLn("message: ", message); + PrintLn("type: "); + switch (type) { - beginBufferSize = beginBufferSize + beginBufferSize/2; - vertexPointer = renew vertexPointer float[beginBufferSize * 5]; + case GL_DEBUG_TYPE_ERROR: PrintLn("ERROR"); break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: PrintLn("DEPRECATED_BEHAVIOR"); break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: PrintLn("UNDEFINED_BEHAVIOR"); break; + case GL_DEBUG_TYPE_PORTABILITY: PrintLn("PORTABILITY"); break; + case GL_DEBUG_TYPE_PERFORMANCE: PrintLn("PERFORMANCE"); break; + case GL_DEBUG_TYPE_OTHER: PrintLn("OTHER"); break; } - vertexPointer[vertexCount*5+2] = x; - vertexPointer[vertexCount*5+3] = y; - vertexPointer[vertexCount*5+4] = z; - vertexCount++; - - if(beginMode == GL_QUADS && ((beginCount % 4) == 3)) + PrintLn("id: ", id); + Print("severity: "); + switch (severity) { - vertexPointer[vertexCount*5+2] = vertexPointer[(vertexCount-4)*5+2]; - vertexPointer[vertexCount*5+3] = vertexPointer[(vertexCount-4)*5+3]; - vertexPointer[vertexCount*5+4] = vertexPointer[(vertexCount-4)*5+4]; - vertexCount++; - vertexPointer[vertexCount*5+2] = vertexPointer[(vertexCount-3)*5+2]; - vertexPointer[vertexCount*5+3] = vertexPointer[(vertexCount-3)*5+3]; - vertexPointer[vertexCount*5+4] = vertexPointer[(vertexCount-3)*5+4]; - vertexCount++; + case GL_DEBUG_SEVERITY_LOW: PrintLn("LOW"); break; + case GL_DEBUG_SEVERITY_MEDIUM: PrintLn("MEDIUM"); break; + case GL_DEBUG_SEVERITY_HIGH: PrintLn("HIGH"); break; + default: PrintLn("(other)"); } - beginCount++; + PrintLn("---------------------opengl-callback-end--------------"); } -void glesVertex3d( double x, double y, double z ) { glesVertex3f((float)x, (float)y, (float)z); } -void glesVertex3fv( float* coords ) { glesVertex3f(coords[0], coords[1], coords[2]); } - -void glesNormal3f(float x, float y, float z) +static void setupDebugging() { - normalCount = vertexCount; - if(vertexCount + 4 > normalBufferSize) + if(glDebugMessageCallback) { - normalBufferSize = normalBufferSize + normalBufferSize/2; - normalPointer = renew normalPointer float[normalBufferSize * 2]; - } + GLuint unusedIds = 0; - normalPointer[normalCount*3+0] = x; - normalPointer[normalCount*3+1] = y; - normalPointer[normalCount*3+2] = z; - normalCount++; + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); - if(beginMode == GL_QUADS && ((beginCount % 4) == 3)) - { - normalPointer[normalCount*3+0] = normalPointer[(normalCount-4)*3+0]; - normalPointer[normalCount*3+1] = normalPointer[(normalCount-4)*3+1]; - normalPointer[normalCount*3+2] = normalPointer[(normalCount-4)*3+2]; - normalCount++; - normalPointer[normalCount*3+0] = normalPointer[(normalCount-3)*3+0]; - normalPointer[normalCount*3+1] = normalPointer[(normalCount-3)*3+1]; - normalPointer[normalCount*3+2] = normalPointer[(normalCount-3)*3+2]; - normalCount++; + glDebugMessageCallback(openglCallbackFunction, null); + glDebugMessageControl(GL_DONT_CARE, + GL_DONT_CARE, + GL_DONT_CARE, + 0, + &unusedIds, + GL_TRUE); } } -void glesNormal3fd(double x, double y, double z) { glesNormal3f((float)x, (float)y, (float)z); } -void glesNormal3fv(float * coords) { glesNormal3f(coords[0], coords[1], coords[2]); } - -void glesColorMaterial(int a, int b) -{ - PrintLn("glColorMaterial stub"); -} - -void glesTerminate() -{ - delete vertexPointer; - beginBufferSize = 0; - - delete floatVPBuffer; - shortVPSize = 0; - - delete shortVPBuffer; - floatVPSize = 0; +#endif - delete shortBDBuffer; - shortBDSize = 0; -} static GLuint stippleTexture; static bool stippleEnabled; -void glesLineStipple( int i, unsigned short j ) +public void glsupLineStipple( int i, uint16 j ) { uint texture[1*16]; int x; @@ -1057,151 +255,132 @@ void glesLineStipple( int i, unsigned short j ) glGenTextures(1, &stippleTexture); glBindTexture(GL_TEXTURE_2D, stippleTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture); - glEnable(GL_TEXTURE_2D); + + // TOOD: Special shading code for stippling? + GLSetupTexturing(true); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); + GLMatrixMode(GL_TEXTURE); + GLLoadIdentity(); //glTranslated(1.0/backAttrib->texW/2.0f, 1.0/backAttrib->texH/2.0f, 0.0f); - glScaled(i/16.0, 1, 1.0f); - glTranslated(0.5, 0.5, 0); - glMatrixMode(GL_PROJECTION); + GLScaled(i/16.0, 1, 1.0f); + GLTranslated(0.5, 0.5, 0); + GLMatrixMode(MatrixMode::projection); } -void glesLightModeli( unsigned int pname, int param ) -{ - if(pname == GL_LIGHT_MODEL_TWO_SIDE) - glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, param); -} + // Exported to build _GLES version... + public void glsupLightModeli( unsigned int pname, int param ) + { +#if ENABLE_GL_FFP + if(pname == GL_LIGHT_MODEL_TWO_SIDE) + glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, param); +#endif + } + +#ifdef _GLES + void glFogi( unsigned int pname, int param ) { } + void glPolygonMode( unsigned int i, unsigned int j ) { } + void glBlendFuncSeparate(int a, int b, int c, int d) + { + glBlendFunc(a, b); + } +#endif + +#if defined(_GLES) || defined(_GLES2) void glClearDepth( double depth ) { glClearDepthf((float)depth); } -void glFogi( unsigned int pname, int param ) { } -void glPolygonMode( unsigned int i, unsigned int j ) { } +#endif +#if !ENABLE_GL_SELECT // *** Picking won't be supported for now *** void glPushName( unsigned int i ) { } void glLoadName( unsigned int i ) { } void glPopName() { } -// Probably replace by regular glBlendFunc ... -void glBlendFuncSeparate(int a, int b, int c, int d) -{ - glBlendFunc(a, b); -} - -// For direct pixel blitting... -void glRasterPos2d(double a, double b) { } -void glPixelZoom(float a, float b) { } -void glDrawPixels(int a, int b, int c, int d, void * e) { } - -#else - -/* Non OpenGL ES friendly stuff -#undef GL_UNSIGNED_INT -#undef GL_DOUBLE -#undef GL_INT -//#undef GL_POLYGON -//#undef GL_QUADS -#undef GL_QUAD_STRIP -#undef GL_POLYGON_STIPPLE -#undef GL_LINE_STIPPLE -#undef GL_LINE -#undef GL_FILL -#undef GL_ALL_ATTRIB_BITS -#undef GL_LIGHT_MODEL_LOCAL_VIEWER -*/ - -#endif - -#if !defined(__APPLE__) -void (APIENTRY * glBindBufferARB) (GLenum target, GLuint buffer); -void (APIENTRY * glGenBuffersARB) (GLsizei n, GLuint *buffers); -void (APIENTRY * glDeleteBuffersARB) (GLsizei n, const GLuint *buffers); -void (APIENTRY * glBufferDataARB) (GLenum target, int size, const GLvoid *data, GLenum usage); -#endif - #endif -static int currentVertexBuffer; - -bool GLSelectVBO(uint vbo) +#if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA) +static inline uint getPrimitiveType(RenderPrimitiveType type) { - if(currentVertexBuffer != vbo) + static int primitiveTypes[RenderPrimitiveType] = { - GLBindBuffer(GL_ARRAY_BUFFER, vbo); - currentVertexBuffer = vbo; - return true; - } - return false; + GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, + GLIMTKMode::quads, + GLIMTKMode::quadStrip, + GL_LINE_STRIP + }; + // NOTE: This will only work for single quads + return (type == quads && !glCaps_quads) ? GL_TRIANGLE_FAN : primitiveTypes[type]; } -void GLGenBuffers(int count, uint * buffer) +public void GLSetupTexturing(bool enable) { -#ifdef __ANDROID__ - glGenBuffers(count, buffer); -#else -#if defined(__WIN32__) - if(glGenBuffersARB) -#endif - glGenBuffersARB(count, buffer); +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + defaultShader.texturing(enable); #endif -} -void GLDeleteBuffers(int count, GLuint * buffer) -{ -#ifdef __ANDROID__ - glDeleteBuffers(count, buffer); -#else -#if defined(__WIN32__) - if(glDeleteBuffersARB) -#endif - glDeleteBuffersARB(count, buffer); +#if ENABLE_GL_FFP + if(!glCaps_shaders) + (enable ? glEnable : glDisable)(GL_TEXTURE_2D); #endif } -void GLBindBuffer(int target, uint buffer) +public void GLSetupFog(bool enable) { -#ifdef __ANDROID__ - glBindBuffer(target, buffer); -#else -#if defined(__WIN32__) - if(glBindBufferARB) +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + defaultShader.fog(enable); #endif - glBindBufferARB(target, buffer); + +#if ENABLE_GL_FFP + if(!glCaps_shaders) + (enable ? glEnable : glDisable)(GL_FOG); #endif } -void GLBufferData(int type, GLenum target, int size, const GLvoid *data, GLenum usage) -{ -#ifdef __ANDROID__ - if(type == GL_DOUBLE) - glesBufferDatad(target, size, (void *)data, usage); - else if(type == GL_UNSIGNED_INT) - glesBufferDatai(target, size, (void *)data, usage); - else - glBufferData(target, size, data, usage); -#else +bool lightingEnabled; -#if defined(__WIN32__) - if(glBufferDataARB) +public void GLSetupLighting(bool enable) +{ + lightingEnabled = enable; +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + defaultShader.lighting(enable); #endif - glBufferDataARB(target, size, data, usage); +#if ENABLE_GL_FFP + if(!glCaps_shaders) + (enable ? glEnable : glDisable)(GL_LIGHTING); #endif } +#endif + +/*static */GLuint lastBlitTex; + +Shader activeShader; static int displayWidth, displayHeight; #define GL_CLAMP_TO_EDGE 0x812F -static bool vboAvailable; - static bool useSingleGLContext = false; class OGLDisplay : struct { + GLCapabilities capabilities, originalCapabilities; + bool compat; + int version; + + ColorAlpha * flippingBuffer; + int flipBufH, flipBufW; + bool depthWrite; + int x, y; + uint vao; + int maxTMU; + #if defined(__WIN32__) HDC hdc; HGLRC glrc; @@ -1215,7 +394,7 @@ class OGLDisplay : struct int imageBuffers[2]; byte * pboMemory1, * pboMemory2; */ -#elif !defined(__ANDROID__) +#elif !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__) GLXContext glContext; Pixmap pixmap; @@ -1231,29 +410,32 @@ class OGLDisplay : struct Pixmap shapePixmap; X11Picture shapePicture; #endif - - ColorAlpha * flippingBuffer; - int flipBufH, flipBufW; - bool depthWrite; - int x, y; }; class OGLSystem : struct { int maxTextureSize; bool loadingFont; - bool pow2textures; #if defined(__WIN32__) PIXELFORMATDESCRIPTOR pfd; int format; HDC hdc; HGLRC glrc; HWND hwnd; -#elif !defined(__ANDROID__) +#elif defined(__EMSCRIPTEN__) + EMSCRIPTEN_WEBGL_CONTEXT_HANDLE glc; +#elif !defined(__ANDROID__) && !defined(__ODROID__) XVisualInfo * visualInfo; GLXContext glContext; GLXDrawable glxDrawable; #endif + GLCapabilities capabilities; + bool compat; + int version; + + // Buffer Data + uint16 *shortBDBuffer; + uint shortBDSize; }; class OGLSurface : struct @@ -1262,43 +444,98 @@ class OGLSurface : struct bool opaqueText; int xOffset; bool writingText; + bool writingOutline; float foreground[4], background[4], bitmapMult[4]; } OGLSurface; class OGLMesh : struct { - uint vertices; - uint normals; - uint texCoords; - uint texCoords2; - uint colors; + GLAB vertices; + GLAB normals; + GLAB tangents; + GLAB lightVectors; + GLAB texCoords; + GLAB texCoords2; + GLAB colors; }; class OGLIndices : struct { uint16 * indices; - uint buffer; + GLEAB buffer; uint nIndices; }; -#if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA) -static int primitiveTypes[RenderPrimitiveType] = -{ - GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS, GL_QUAD_STRIP, GL_LINE_STRIP -}; -#endif - int current; void * previous; +#if defined(__WIN32__) +static HGLRC winCreateContext(HDC hdc, int * contextVersion, bool * isCompatible, bool compatible) +{ + HGLRC result = 0; + if(wglCreateContextAttribsARB) + { + int versions[12][2] = + { + { 4, 5 }, { 4, 4 }, { 4, 3 }, { 4, 2 }, { 4, 1 }, { 4, 0 }, + { 3, 3 }, { 3, 2 }, { 3, 1 }, { 3, 0 }, + { 2, 1 }, { 2, 0 } + }; + + bool tryingCompat = compatible; + int v = 0; + while(!result) + { + for(v = 0; !result && v < sizeof(versions) / sizeof(versions[0]); v++) + { + int v0 = versions[v][0], v1 = versions[v][1]; + if(!tryingCompat || v0 >= 3) + { + bool coreNotion = v0 > 3 || (v0 == 3 && v1 >= 3); + int attribs[] = + { + WGL_CONTEXT_MAJOR_VERSION_ARB, v0, WGL_CONTEXT_MINOR_VERSION_ARB, v1, + #ifdef _DEBUG + WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB, + #endif + coreNotion ? WGL_CONTEXT_PROFILE_MASK_ARB : 0, coreNotion ? (tryingCompat ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : WGL_CONTEXT_CORE_PROFILE_BIT_ARB) : 0, + 0,0 + }; + result = wglCreateContextAttribsARB(hdc, null, attribs); + if(result) + { + if(contextVersion) *contextVersion = v0; + if(isCompatible) *isCompatible = tryingCompat || !coreNotion; + } + } + } + if(tryingCompat) + tryingCompat = false; + else + break; + } + } + if(!result) + { + if(contextVersion) *contextVersion = 1; + if(isCompatible) *isCompatible = true; + result = wglCreateContext(hdc); + } + return result; +} +#endif + class OpenGLDisplayDriver : DisplayDriver { class_property(name) = "OpenGL"; bool LockSystem(DisplaySystem displaySystem) { -#if !defined(__ANDROID__) +#if defined(__EMSCRIPTEN__) + OGLSystem oglSystem = displaySystem.driverData; + emscripten_webgl_make_context_current(oglSystem.glc); +#elif !defined(__ANDROID__) && !defined(__ODROID__) OGLSystem oglSystem = displaySystem.driverData; if(useSingleGLContext) return true; #if defined(__WIN32__) @@ -1310,6 +547,8 @@ class OpenGLDisplayDriver : DisplayDriver //previous = oglSystem.glContext; #endif #endif + GLABBindBuffer(GL_ARRAY_BUFFER, 0); + GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); return true; } @@ -1320,7 +559,7 @@ class OpenGLDisplayDriver : DisplayDriver wglMakeCurrent(null, null); #elif defined(__unix__) || defined(__APPLE__) // printf("Making NULL current\n"); - #if defined(__ANDROID__) + #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__) #else glXMakeCurrent(xGlobalDisplay, None, null); #endif @@ -1330,7 +569,7 @@ class OpenGLDisplayDriver : DisplayDriver bool Lock(Display display) { -#if !defined(__ANDROID__) +#if !defined(__ANDROID__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__) OGLDisplay oglDisplay = display.driverData; if(useSingleGLContext) return true; #if defined(__WIN32__) @@ -1341,6 +580,8 @@ class OpenGLDisplayDriver : DisplayDriver glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext); #endif #endif + GLABBindBuffer(GL_ARRAY_BUFFER, 0); + GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); return true; } @@ -1378,7 +619,7 @@ class OpenGLDisplayDriver : DisplayDriver if(oglDisplay.memBitmap) DeleteObject(oglDisplay.memBitmap); #elif defined(__unix__) || defined(__APPLE__) - #if defined(__ANDROID__) + #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__) #else if(oglDisplay.shapePixmap) XFreePixmap(xGlobalDisplay, oglDisplay.shapePixmap); @@ -1419,19 +660,83 @@ class OpenGLDisplayDriver : DisplayDriver } } - void ::CheckExtensions(OGLSystem oglSystem) +#if !defined(__EMSCRIPTEN__) + void ::CheckCapabilities(OGLSystem oglSystem, OGLDisplay oglDisplay, bool canCheckExtensions) { - const char * extensions = (const char *)glGetString(GL_EXTENSIONS); - if(extensions) - oglSystem.pow2textures = strstr(extensions, "GL_ARB_texture_non_power_of_two") ? false : true; + GLCapabilities capabilities; +#if !defined(_GLES2) + const char * extensions = (canCheckExtensions && (!oglDisplay || oglDisplay.compat)) ? (const char *)glGetString(GL_EXTENSIONS) : null; +#endif +#ifdef DIAGNOSTICS + printf("extensions: %s\n", extensions); +#endif + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &oglSystem.maxTextureSize); + +#if defined(_GLES) + capabilities = { fixedFunction = true, vertexPointer = true, vertexBuffer = true, pointSize = true, legacyFormats = true, frameBuffer = extensions && strstr(extensions, "GL_OES_framebuffer_object") }; +#elif defined(_GLES2) + capabilities = { glCaps_shaders = true, vertexBuffer = true, pointSize = true, frameBuffer = true, legacyFormats = true }; +#else + capabilities = + { + nonPow2Textures = glGetStringi || (extensions && (strstr(extensions, "GL_ARB_texture_non_power_of_two"))); + intAndDouble = true; +#ifdef GL_DEBUGGING + debug = true; +#endif + compatible = oglDisplay.compat; + pointSize = oglDisplay.compat; +#if ENABLE_GL_LEGACY + legacy = glBegin != null && oglDisplay.compat; + legacyFormats = glBegin != null && oglDisplay.compat; + immediate = glBegin != null && oglDisplay.compat; + fixedFunction = glBegin != null && oglDisplay.compat; + quads = glBegin != null && oglDisplay.compat; + select = glSelectBuffer != null && oglDisplay.compat; +#endif +#if ENABLE_GL_SHADERS + shaders = glCreateProgram != null; +#endif +#if ENABLE_GL_POINTER + vertexPointer = oglDisplay.compat; +#endif +#if ENABLE_GL_VAO + vao = glBindVertexArray != null && !oglDisplay.compat; +#endif +#if ENABLE_GL_FBO + frameBuffer = glBindFramebuffer != null; +#endif + vertexBuffer = glBindBuffer != null; + // mapBuffer = glMapBuffer != null; + }; +#endif + +#ifdef DIAGNOSTICS + PrintLn("max texture size: ", oglSystem.maxTextureSize); +#endif + if(oglDisplay) oglDisplay.capabilities = capabilities; + if(oglSystem) oglSystem.capabilities = capabilities; } +#endif bool CreateDisplaySystem(DisplaySystem displaySystem) { bool result = false; OGLSystem oglSystem = displaySystem.driverData = OGLSystem { }; +#ifdef _GLES + oglSystem.capabilities = { fixedFunction = true, vertexBuffer = true, frameBuffer = true, pointSize = true }; +#elif defined(_GLES2) + oglSystem.capabilities = { shaders = true, vertexBuffer = true, frameBuffer = true, pointSize = true }; +#else + oglSystem.capabilities = { compatible = glCaps_compatible, shaders = true, fixedFunction = true, immediate = true, legacy = true, pointSize = true, quads = true, intAndDouble = true, vertexBuffer = true, frameBuffer = true, vao = true, nonPow2Textures = true }; +#endif + +#ifdef DIAGNOSTICS + PrintLn("OpenGL driver's CreateDisplaySystem()"); +#endif + #ifdef __WIN32__ oglSystem.hwnd = CreateWindow("static", null, 0,0,0,0,0,null,null,null,null); @@ -1459,20 +764,6 @@ class OpenGLDisplayDriver : DisplayDriver { wglMakeCurrent(oglSystem.hdc, oglSystem.glrc); - // Get Pointers To The GL Functions - glActiveTextureARB = (void *) wglGetProcAddress("glActiveTextureARB"); - glMultiTexCoord2fARB = (void *) wglGetProcAddress("glMultiTexCoord2fARB"); - glClientActiveTextureARB = (void *) wglGetProcAddress("glClientActiveTextureARB"); - glLockArraysEXT = (void *) wglGetProcAddress("glLockArraysEXT" ); - glUnlockArraysEXT = (void *) wglGetProcAddress("glUnlockArraysEXT"); - glGenBuffersARB = (void *) wglGetProcAddress("glGenBuffersARB"); - glBindBufferARB = (void *) wglGetProcAddress("glBindBufferARB"); - glBufferDataARB = (void *) wglGetProcAddress("glBufferDataARB"); - glMapBufferARB = (void *) wglGetProcAddress("glMapBufferARB"); - glUnmapBufferARB = (void *) wglGetProcAddress("glUnmapBufferARB"); - glDeleteBuffersARB = (void *) wglGetProcAddress("glDeleteBuffersARB"); - glBlendFuncSeparate = (void *) wglGetProcAddress("glBlendFuncSeparate"); - wglChoosePixelFormatARB = (void *) wglGetProcAddress("wglChoosePixelFormatARB"); wglGetExtensionsStringARB = (void *)wglGetProcAddress("wglGetExtensionsStringARB"); wglCreatePbufferARB = (void *)wglGetProcAddress("wglCreatePbufferARB"); @@ -1482,42 +773,43 @@ class OpenGLDisplayDriver : DisplayDriver wglReleasePbufferDCARB = (void *)wglGetProcAddress("wglReleasePbufferDCARB"); wglBindTexImageARB = (void *)wglGetProcAddress("wglBindTexImageARB"); wglReleaseTexImageARB = (void *)wglGetProcAddress("wglReleaseTexImageARB"); - wglSwapIntervalEXT = (void *)wglGetProcAddress("wglSwapIntervalEXT"); + wglCreateContextAttribsARB = (void *)wglGetProcAddress("wglCreateContextAttribsARB"); - vboAvailable = glBindBufferARB != null; + glLockArraysEXT = (void *) wglGetProcAddress("glLockArraysEXT" ); + glUnlockArraysEXT = (void *) wglGetProcAddress("glUnlockArraysEXT"); // eSystem_LoggingMode(LOG_MSGBOX, null); if(wglChoosePixelFormatARB) { - int pixelFormat; - int valid; - int numFormats; - float fAttributes[] = {0,0}; - int iAttributes[] = + int pixelFormat; + int valid; + int numFormats; + float fAttributes[] = {0,0}; + int iAttributes[] = { WGL_DRAW_TO_WINDOW_ARB,GL_TRUE, - WGL_SUPPORT_OPENGL_ARB,GL_TRUE, - WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB, - WGL_COLOR_BITS_ARB,24, - WGL_ALPHA_BITS_ARB,8, - WGL_DEPTH_BITS_ARB,16, - WGL_STENCIL_BITS_ARB,0, - WGL_DOUBLE_BUFFER_ARB,GL_TRUE, - WGL_SAMPLE_BUFFERS_ARB,GL_TRUE, - WGL_SAMPLES_ARB, 4, // Check For 4x Multisampling - 0,0 + WGL_SUPPORT_OPENGL_ARB,GL_TRUE, + WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB, + WGL_COLOR_BITS_ARB,24, + WGL_ALPHA_BITS_ARB,8, + WGL_DEPTH_BITS_ARB,16, + WGL_STENCIL_BITS_ARB,0, + WGL_DOUBLE_BUFFER_ARB,GL_TRUE, + WGL_SAMPLE_BUFFERS_ARB,GL_TRUE, + WGL_SAMPLES_ARB, 4, // Check For 4x Multisampling + 0,0 }; //Log("Found wglChoosePixelFormatARB\n"); - valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats); - if(!valid || !numFormats) - { + valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats); + if(!valid || !numFormats) + { //Log("Can't find 4x multi sampling\n"); - iAttributes[19] = 2; - valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats); + iAttributes[19] = 2; + valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats); if(!valid || !numFormats) { // Log("Can't find 2x multi sampling\n"); @@ -1525,41 +817,121 @@ class OpenGLDisplayDriver : DisplayDriver iAttributes[17] = 0; valid = wglChoosePixelFormatARB(oglSystem.hdc,iAttributes,fAttributes,1,&pixelFormat,&numFormats); } - } + } if(valid && numFormats) { oglSystem.format = pixelFormat; wglMakeCurrent(null, null); wglDeleteContext(oglSystem.glrc); - // *** DescribePixelFormat does not support WGL pixel formats! *** - //DescribePixelFormat(oglSystem.hdc, oglSystem.format, sizeof(oglSystem.pfd), &oglSystem.pfd); - SetPixelFormat(oglSystem.hdc, oglSystem.format, &oglSystem.pfd); - //Log("Successfully set pixel format\n"); + // *** DescribePixelFormat does not support WGL pixel formats! *** + //DescribePixelFormat(oglSystem.hdc, oglSystem.format, sizeof(oglSystem.pfd), &oglSystem.pfd); + SetPixelFormat(oglSystem.hdc, oglSystem.format, &oglSystem.pfd); + //Log("Successfully set pixel format\n"); + +#ifdef DIAGNOSTICS + PrintLn("winCreateContext()"); +#endif + oglSystem.glrc = winCreateContext(oglSystem.hdc, &oglSystem.version, &oglSystem.compat, displaySystem.glCapabilities.compatible); +#ifdef DIAGNOSTICS + PrintLn("wglMakeCurrent()"); +#endif + if(oglSystem.glrc) + wglMakeCurrent(oglSystem.hdc, oglSystem.glrc); + } + } + /*else + eSystem_Logf("Can't find wglChoosePixelFormatARB\n");*/ + + result = true; + + wglMakeCurrent(null, null); + + //eSystem_DumpErrors(true); + } + } + } + #elif defined(__unix__) || defined(__APPLE__) + #if defined(__ANDROID__) || defined(__ODROID__) + #if defined(__ANDROID__) + egl_init_display(guiApp.desktop.windowHandle); + #elif defined(__ODROID__) + egl_init_display((uint)displaySystem.window); + #endif + CheckCapabilities(oglSystem, null, true); + + // TODO: Clean this up? Needed here? + GLEnableClientState(VERTICES); + /* + // Initialize GL state. + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + glEnable(GL_CULL_FACE); + glShadeModel(GL_SMOOTH); + glDisable(GL_DEPTH_TEST); + */ + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + matrixStack[0][0].Identity(); + matrixStack[1][0].Identity(); + matrixStack[2][0].Identity(); + + GLMatrixMode(GL_MODELVIEW); + GLScaled(1.0, 1.0, -1.0); + GLMatrixMode(GL_PROJECTION); + glShadeModel(GL_FLAT); - oglSystem.glrc = wglCreateContext(oglSystem.hdc); - wglMakeCurrent(oglSystem.hdc, oglSystem.glrc); - } - } - /*else - eSystem_Logf("Can't find wglChoosePixelFormatARB\n");*/ +#if !defined(_GLES) + if(!glCaps_shaders) + ;//GLLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); +#endif + glFogi(GL_FOG_MODE, GL_EXP); + glFogf(GL_FOG_DENSITY, 0); + glEnable(GL_NORMALIZE); + glDepthFunc(GL_LESS); + glClearDepth(1.0); + glDisable(GL_MULTISAMPLE); - result = true; + glViewport(0,0,eglWidth,eglHeight); + GLLoadIdentity(); + GLOrtho(0,eglWidth,eglHeight,0,0.0,1.0); - CheckExtensions(oglSystem); + glabCurArrayBuffer = 0; + glabCurElementBuffer = 0; - wglMakeCurrent(null, null); + result = true; + #elif defined(__EMSCRIPTEN__) + { + EmscriptenWebGLContextAttributes attribs = { 0 }; + attribs.depth = 1; + attribs.antialias = 1; - //eSystem_DumpErrors(true); - } + /* + EM_BOOL alpha; + EM_BOOL depth; + EM_BOOL stencil; + EM_BOOL antialias; + EM_BOOL premultipliedAlpha; + EM_BOOL preserveDrawingBuffer; + EM_BOOL preferLowPowerToHighPerformance; + EM_BOOL failIfMajorPerformanceCaveat; + int majorVersion; + int minorVersion; + EM_BOOL enableExtensionsByDefault; + */ + + emscripten_webgl_init_context_attributes(&attribs); + oglSystem.maxTextureSize = 16384; + oglSystem.glc = emscripten_webgl_create_context("canvas", &attribs); + if(emscripten_webgl_make_context_current(oglSystem.glc) == EMSCRIPTEN_RESULT_SUCCESS) + result = true; + + /*glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND);*/ } - } - #elif defined(__unix__) || defined(__APPLE__) - vboAvailable = true; - #if defined(__ANDROID__) - egl_init_display(guiApp.desktop.windowHandle); - CheckExtensions(oglSystem); - result = true; #else { X11Window root = RootWindow( xGlobalDisplay, DefaultScreen( xGlobalDisplay ) ); @@ -1592,8 +964,6 @@ class OpenGLDisplayDriver : DisplayDriver if(oglSystem.glContext) { glXMakeCurrent(xGlobalDisplay, oglSystem.glxDrawable, oglSystem.glContext); - // Setup Extensions - CheckExtensions(oglSystem); glXMakeCurrent(xGlobalDisplay, None, null); result = true; } @@ -1610,6 +980,19 @@ class OpenGLDisplayDriver : DisplayDriver void DestroyDisplaySystem(DisplaySystem displaySystem) { OGLSystem oglSystem = displaySystem.driverData; + if(stippleTexture) + { + glDeleteTextures(1, &stippleTexture); + stippleTexture = 0; + } + +#if ENABLE_GL_SHADERS + defaultShader.free(); + activeShader = null; +#endif + + delete oglSystem.shortBDBuffer; + glimtkTerminate(); #if defined(__WIN32__) wglMakeCurrent( null, null ); @@ -1622,8 +1005,10 @@ class OpenGLDisplayDriver : DisplayDriver DestroyWindow(oglSystem.hwnd); #elif defined(__unix__) || defined(__APPLE__) - #if defined(__ANDROID__) + #if defined(__ANDROID__) || defined(__ODROID__) egl_term_display(); + #elif defined(__EMSCRIPTEN__) + emscripten_webgl_destroy_context(oglSystem.glc); #else if(oglSystem.visualInfo) { @@ -1633,6 +1018,8 @@ class OpenGLDisplayDriver : DisplayDriver XFree(oglSystem.visualInfo); #endif } + if(oglSystem.glContext) + glXDestroyContext(xGlobalDisplay, oglSystem.glContext); if(oglSystem.glxDrawable) { @@ -1644,25 +1031,189 @@ class OpenGLDisplayDriver : DisplayDriver delete oglSystem; } + /*static */bool ::initialDisplaySetup(Display display, bool canCheckExtensions, bool loadExtensions) + { + OGLDisplay oglDisplay = display.driverData; + OGLSystem oglSystem = display.displaySystem.driverData; + bool result = true; + +#if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) && !defined(__ODROID__) + if(loadExtensions && ogl_LoadFunctions() == ogl_LOAD_FAILED) + PrintLn("ogl_LoadFunctions() failed!"); + CheckCapabilities(oglSystem, oglDisplay, canCheckExtensions); +#endif + + { + GLCapabilities capabilities = *&display.glCapabilities; + // PrintLn("Available OpenGL Capabilities: ", oglDisplay.capabilities); + // PrintLn("Desired OpenGL Capabilities: ", capabilities); + + oglDisplay.originalCapabilities = oglDisplay.capabilities; + + // Re-enable glCaps_shaders if no fixed function support + if(!oglDisplay.capabilities.fixedFunction) + capabilities.shaders = true; + // Re-enable fixed function if no glCaps_shaders support + if(!oglDisplay.capabilities.shaders) + { + capabilities.fixedFunction = true; + capabilities.shaders = false; + } + + if(!capabilities.shaders && !capabilities.fixedFunction) + { + capabilities.fixedFunction = oglDisplay.capabilities.fixedFunction; + capabilities.shaders = oglDisplay.capabilities.shaders; + } + + // Disable things that don't work with glCaps_shaders + if(capabilities.shaders) + { + capabilities.fixedFunction = false; + capabilities.legacy = false; + capabilities.immediate = false; + } + + #if !ENABLE_GL_POINTER + // Re-enable vertex buffer if no pointer support + capabilities.vertexBuffer = true; + #endif + + oglDisplay.capabilities &= capabilities; + + // PrintLn("Selected OpenGL Capabilities: ", oglDisplay.capabilities); + oglSystem.capabilities = oglDisplay.capabilities; + } + + #ifdef GL_DEBUGGING + if(oglDisplay.capabilities.debug) + setupDebugging(); + #else + oglDisplay.capabilities.debug = false; + #endif + +#if ENABLE_GL_VAO + if(oglDisplay.capabilities.vao) + { + glGenVertexArrays(1, &oglDisplay.vao); + glBindVertexArray(oglDisplay.vao); + } +#endif + + oglSystem.capabilities = oglDisplay.capabilities; + SETCAPS(oglDisplay.capabilities); + +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + { +#if ENABLE_GL_LEGACY + if(oglDisplay.compat) + { + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + } +#endif + defaultShader.select(); + } +#if ENABLE_GL_LEGACY + else + { + glDisableVertexAttribArray(GLBufferContents::color); + glDisableVertexAttribArray(GLBufferContents::normal); + glDisableVertexAttribArray(GLBufferContents::texCoord); + glDisableVertexAttribArray(GLBufferContents::vertex); + glDisableVertexAttribArray(GLBufferContents::tangent1); + glDisableVertexAttribArray(GLBufferContents::tangent2); +#if ENABLE_GL_VAO + glBindVertexArray(0); +#endif + glUseProgram(0); + } +#endif + +#endif + +#if ENABLE_GL_VAO + if(glCaps_vao) + glBindVertexArray(oglDisplay.vao); +#endif + + GLEnableClientState(VERTICES); + + GLABBindBuffer(GL_ARRAY_BUFFER, 0); + GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + +#if defined(__WIN32__) + if(glBlendFuncSeparate) + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + else + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +#else + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); +#endif + glEnable(GL_BLEND); + + GLMatrixMode(MatrixMode::texture); + GLLoadIdentity(); + + GLMatrixMode(MatrixMode::modelView); + GLLoadIdentity(); // For setting up GLES stack + GLScaled(1.0, 1.0, -1.0); + // glTranslatef(0.375f, 0.375f, 0.0f); + // glTranslatef(-0.625f, -0.625f, 0.0f); + GLMatrixMode(MatrixMode::projection); + GLLoadIdentity(); + if(display.width && display.height) + GLOrtho(0,display.width,display.height,0,0.0,1.0); + +#if ENABLE_GL_FFP + if(!glCaps_shaders) + { + glShadeModel(GL_FLAT); + + #define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 + GLLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); + +#if !defined(_GLES) + ;//GLLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); +#endif + glFogi(GL_FOG_MODE, GL_EXP); + glFogf(GL_FOG_DENSITY, 0); + glEnable(GL_NORMALIZE); + } +#endif + glDepthFunc(GL_LESS); + glClearDepth(1.0); +#if !defined(__EMSCRIPTEN__) + glDisable(GL_MULTISAMPLE); +#endif + +#if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA) + display.ambient = Color { 50,50,50 }; +#endif + return result; + } + bool CreateDisplay(Display display) { bool result = false; OGLDisplay oglDisplay = display.driverData; -#if !defined(__ANDROID__) OGLSystem oglSystem = display.displaySystem.driverData; -#endif + if(!oglDisplay) oglDisplay = display.driverData = OGLDisplay { }; - //printf("Inside CreateDisplay\n"); + oglDisplay.capabilities = oglSystem.capabilities; #if defined(__WIN32__) || defined(USEPBUFFER) if(!display.alphaBlend) #endif { - #if defined(__WIN32__) +#if defined(__WIN32__) oglDisplay.hdc = GetDC(display.window); SetPixelFormat(oglDisplay.hdc, oglSystem.format, &oglSystem.pfd); - if((oglDisplay.glrc = wglCreateContext(oglDisplay.hdc))) + if((oglDisplay.glrc = winCreateContext(oglDisplay.hdc, &oglDisplay.version, &oglDisplay.compat, (*&display.glCapabilities).compatible))) { wglShareLists(oglSystem.glrc, oglDisplay.glrc); wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc); @@ -1670,9 +1221,10 @@ class OpenGLDisplayDriver : DisplayDriver } else ReleaseDC(display.window, oglDisplay.hdc); - #elif defined(__unix__) || defined(__APPLE__) - #if defined(__ANDROID__) - #else +#elif defined(__unix__) || defined(__APPLE__) +# if defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__ODROID__) + result = true; +# else XVisualInfo * visualInfo = ((XWindowData)display.windowDriverData).visual; /* #if defined(__APPLE__) @@ -1691,6 +1243,11 @@ class OpenGLDisplayDriver : DisplayDriver // visualInfo = oglSystem.visualInfo; //#endif */ +#if !defined(__APPLE__) + oglDisplay.compat = true; + oglDisplay.version = 4; +#endif + if(visualInfo) { //printf("visualInfo is not null\n"); @@ -1706,72 +1263,56 @@ class OpenGLDisplayDriver : DisplayDriver glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext); result = true; } - #endif - #endif +# endif +#endif } #if defined(__WIN32__) || defined(USEPBUFFER) else + { + oglDisplay.compat = (*&display.glCapabilities).compatible; result = true; + wglMakeCurrent(oglSystem.hdc, oglSystem.glrc); + } #endif if(result) { -#if defined(__WIN32__) - if(glBlendFuncSeparate) - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - else - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -#else -#if !defined(__OLDX__) - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); -#else - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -#endif +#if defined(__EMSCRIPTEN__) + emscripten_webgl_make_context_current(oglSystem.glc); #endif - glEnable(GL_BLEND); - - glMatrixMode(GL_MODELVIEW); - glScaled(1.0, 1.0, -1.0); - // glTranslatef(0.375f, 0.375f, 0.0f); - // glTranslatef(-0.625f, -0.625f, 0.0f); - glMatrixMode(GL_PROJECTION); - glShadeModel(GL_FLAT); - // glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, true); - glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); - glFogi(GL_FOG_MODE, GL_EXP); - glFogf(GL_FOG_DENSITY, 0); - glEnable(GL_NORMALIZE); - glDepthFunc(GL_LESS); - glClearDepth(1.0); - glDisable(GL_MULTISAMPLE_ARB); - } -#if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA) - display.ambient = Color { 50,50,50 }; +#if defined(__WIN32__) || defined(USEPBUFFER) + initialDisplaySetup(display, !display.alphaBlend, true); +#else + initialDisplaySetup(display, true, true); #endif + } if(!useSingleGLContext) { #if defined(__WIN32__) wglMakeCurrent(null, null); #elif defined(__unix__) || defined(__APPLE__) - #if defined(__ANDROID__) + #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__) result = true; #else glXMakeCurrent(xGlobalDisplay, None, null); #endif #endif } - + else + { + #if defined(__ANDROID__) || defined(__EMSCRIPTEN__) || defined(__ODROID__) + result = true; + #endif + } return result; } bool DisplaySize(Display display, int width, int height) { OGLDisplay oglDisplay = display.driverData; - bool result = false; - //printf("Inside DisplaySize\n"); #if defined(__WIN32__) || defined(USEPBUFFER) OGLSystem oglSystem = display.displaySystem.driverData; if(display.alphaBlend) @@ -1792,16 +1333,16 @@ class OpenGLDisplayDriver : DisplayDriver { //WGL_DRAW_TO_BITMAP_ARB, GL_TRUE, WGL_DRAW_TO_PBUFFER_ARB,GL_TRUE, - WGL_SUPPORT_OPENGL_ARB,GL_TRUE, - WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB, - WGL_COLOR_BITS_ARB,24, - WGL_ALPHA_BITS_ARB,8, - WGL_DEPTH_BITS_ARB,16, - WGL_STENCIL_BITS_ARB,0, - WGL_DOUBLE_BUFFER_ARB,GL_FALSE, - WGL_SAMPLE_BUFFERS_ARB,GL_TRUE, - WGL_SAMPLES_ARB, 4, // Check For 4x Multisampling - 0,0 + WGL_SUPPORT_OPENGL_ARB,GL_TRUE, + WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB, + WGL_COLOR_BITS_ARB,24, + WGL_ALPHA_BITS_ARB,8, + WGL_DEPTH_BITS_ARB,16, + WGL_STENCIL_BITS_ARB,0, + WGL_DOUBLE_BUFFER_ARB,GL_FALSE, + WGL_SAMPLE_BUFFERS_ARB,GL_TRUE, + WGL_SAMPLES_ARB, 4, // Check For 4x Multisampling + 0,0 }; //Log("Found wglChoosePixelFormatARB\n"); @@ -1855,7 +1396,7 @@ class OpenGLDisplayDriver : DisplayDriver oglDisplay.pBuffer = wglCreatePbufferARB(oglSystem.hdc, pixelFormat, width, height, attributes); oglDisplay.hdc = wglGetPbufferDCARB(oglDisplay.pBuffer); - if((oglDisplay.glrc = wglCreateContext(oglDisplay.hdc))) + if((oglDisplay.glrc = winCreateContext(oglDisplay.hdc, null, null, oglDisplay.capabilities.compatible))) { BITMAPINFO * info; HDC hdc = GetDC(display.window); @@ -1931,36 +1472,36 @@ class OpenGLDisplayDriver : DisplayDriver ReleaseDC(display.window, hdc); } #elif defined(__unix__) || defined(__APPLE__) - #if defined(__ANDROID__) + #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__) result = true; #else - int attrib[] = - { - GLX_DOUBLEBUFFER, True, + int attrib[] = + { + GLX_DOUBLEBUFFER, True, GLX_DEPTH_SIZE, 1, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_STENCIL_SIZE, 1, - //GLX_DEPTH_SIZE, 24, - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT, - None - }; - - int PBattrib[] = - { - GLX_PBUFFER_WIDTH, width, - GLX_PBUFFER_HEIGHT, height, - GLX_LARGEST_PBUFFER, False, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_STENCIL_SIZE, 1, + //GLX_DEPTH_SIZE, 24, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT, + None + }; + + int PBattrib[] = + { + GLX_PBUFFER_WIDTH, width, + GLX_PBUFFER_HEIGHT, height, + GLX_LARGEST_PBUFFER, False, None - }; + }; - // choose a pixel format that meets our minimum requirements - int count = 0; + // choose a pixel format that meets our minimum requirements + int count = 0; - GLXFBConfig *config = glXChooseFBConfig(xGlobalDisplay, DefaultScreen(xGlobalDisplay), attrib, &count); + GLXFBConfig *config = glXChooseFBConfig(xGlobalDisplay, DefaultScreen(xGlobalDisplay), attrib, &count); if(config) { if(oglDisplay.pixmap) @@ -2009,14 +1550,14 @@ class OpenGLDisplayDriver : DisplayDriver XFreePixmap(xGlobalDisplay, oglDisplay.pixmap); if(oglDisplay.glContext) - glXDestroyContext(xGlobalDisplay, oglDisplay.glContext); + glXDestroyContext(xGlobalDisplay, oglDisplay.glContext); if(oglDisplay.pBuffer) glXDestroyPbuffer(xGlobalDisplay, oglDisplay.pBuffer); - oglDisplay.pBuffer = glXCreatePbuffer(xGlobalDisplay, config[0], PBattrib); + oglDisplay.pBuffer = glXCreatePbuffer(xGlobalDisplay, config[0], PBattrib); if(oglDisplay.pBuffer) { - oglDisplay.glContext = glXCreateNewContext(xGlobalDisplay, config[0], GLX_RGBA_TYPE, oglSystem.glContext, True); + oglDisplay.glContext = glXCreateNewContext(xGlobalDisplay, config[0], GLX_RGBA_TYPE, oglSystem.glContext, True); if(oglDisplay.glContext) { glXMakeCurrent(xGlobalDisplay, None, null); @@ -2062,7 +1603,7 @@ class OpenGLDisplayDriver : DisplayDriver { XRenderPictureAttributes attributes = { 0 }; XRenderPictFormat * format = XRenderFindStandardFormat(xGlobalDisplay, /*PictStandardRGB24*/ PictStandardARGB32); - #if !defined(__APPLE__) && !defined(__OLDX__) + #if !defined(__APPLE__) attributes.repeat = RepeatNormal; #else attributes.repeat = 1; @@ -2095,9 +1636,11 @@ class OpenGLDisplayDriver : DisplayDriver #if defined(__WIN32__) wglMakeCurrent(oglDisplay.hdc, oglDisplay.glrc); #elif defined(__unix__) || defined(__APPLE__) - #if defined(__ANDROID__) + #if defined(__ANDROID__) || defined(__ODROID__) width = eglWidth; height = eglHeight; + #elif defined(__EMSCRIPTEN__) + emscripten_webgl_make_context_current(oglSystem.glc); #else glXMakeCurrent(xGlobalDisplay, (GLXDrawable)display.window, oglDisplay.glContext); #endif @@ -2106,6 +1649,12 @@ class OpenGLDisplayDriver : DisplayDriver else #endif result = true; + + SETCAPS(oglDisplay.capabilities); + + if(display.alphaBlend && result) + initialDisplaySetup(display, true, false); + if(!result && display.alphaBlend) { printf("Alpha blending windows not supported on this display\n"); @@ -2116,8 +1665,9 @@ class OpenGLDisplayDriver : DisplayDriver result = false; glViewport(0,0,width,height); - glLoadIdentity(); - glOrtho(0,width,height,0,0.0,1.0); + GLMatrixMode(MatrixMode::projection); + GLLoadIdentity(); + GLOrtho(0,width,height,0,0.0,1.0); displayWidth = display.width = width; displayHeight = display.height = height; @@ -2125,7 +1675,11 @@ class OpenGLDisplayDriver : DisplayDriver { oglDisplay.flipBufW = width; oglDisplay.flipBufH = height; +#if defined(_GLES) || defined(_GLES2) + result = true; +#else oglDisplay.flippingBuffer = renew oglDisplay.flippingBuffer ColorAlpha [width * height]; +#endif } if(oglDisplay.flippingBuffer || !width || !height) result = true; @@ -2151,6 +1705,18 @@ class OpenGLDisplayDriver : DisplayDriver void StartUpdate(Display display) { +#if ENABLE_GL_VAO + if(glCaps_vao) + { + OGLDisplay oglDisplay = display.driverData; + glBindVertexArray(oglDisplay.vao); + } +#endif + GLABBindBuffer(GL_ARRAY_BUFFER, 0); + GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +#if ENABLE_GL_SHADERS + activeProgram = 0; +#endif } void EndUpdate(Display display) @@ -2166,10 +1732,12 @@ class OpenGLDisplayDriver : DisplayDriver #if defined(__WIN32__) || defined(USEPBUFFER) OGLDisplay oglDisplay = display.driverData; #endif - //Logf("DisplayScreen\n"); - glFlush(); - glFinish(); +#if !defined(__ANDROID__) + /*glFlush(); + glFinish();*/ +#endif + #if defined(__WIN32__) || defined(USEPBUFFER) if(display.alphaBlend) { @@ -2229,7 +1797,7 @@ class OpenGLDisplayDriver : DisplayDriver ReleaseDC(0, hdc); #elif defined(__unix__) || defined(__APPLE__) - #if defined(__ANDROID__) + #if defined(__ANDROID__) || defined(__ODROID__) || defined(__EMSCRIPTEN__) #else XTransform transform = { @@ -2242,7 +1810,7 @@ class OpenGLDisplayDriver : DisplayDriver XRenderSetPictureTransform(xGlobalDisplay, oglDisplay.pixmapPicture, &transform); XRenderComposite(xGlobalDisplay, PictOpSrc, oglDisplay.pixmapPicture, None, oglDisplay.shapePicture, 0, 0, 0, 0, 0, 0, display.width, display.height); XRenderComposite(xGlobalDisplay, PictOpSrc, oglDisplay.pixmapPicture, None, oglDisplay.windowPicture, 0, 0, 0, 0, 0, 0, display.width, display.height); - #if !defined(__APPLE__) && !defined(__OLDX__) + #if !defined(__APPLE__) XShapeCombineMask(xGlobalDisplay, (X11Window)display.window, ShapeInput, 0, 0, oglDisplay.shapePixmap, ShapeSet); #else XShapeCombineMask(xGlobalDisplay, display.window, 2, 0, 0, oglDisplay.shapePixmap, ShapeSet); @@ -2258,15 +1826,16 @@ class OpenGLDisplayDriver : DisplayDriver #if defined(__WIN32__) //wglSwapLayerBuffers(oglDisplay.hdc,WGL_SWAP_MAIN_PLANE); SwapBuffers(oglDisplay.hdc); + //ecere::sys::Sleep(0.1); #elif defined(__unix__) || defined(__APPLE__) - #if defined(__ANDROID__) - eglSwapBuffers(eglDisplay, eglSurface); + #if defined(__ANDROID__) || defined(__ODROID__) + egl_swap_buffers(); + #elif defined(__EMSCRIPTEN__) #else glXSwapBuffers(xGlobalDisplay, (GLXDrawable)display.window); #endif #endif } - //Logf("Out of DisplayScreen\n"); } void FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap) @@ -2283,12 +1852,13 @@ class OpenGLDisplayDriver : DisplayDriver bool AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette) { OGLSystem oglSystem = displaySystem.driverData; + GLCapabilities capabilities = oglSystem.capabilities; bool result = false; Bitmap mipMap { }; GLuint glBitmap = 0; uint w = width, h = height; - if(oglSystem.pow2textures) + if(!capabilities.nonPow2Textures) { w = pow2i(w); h = pow2i(h); @@ -2307,7 +1877,10 @@ class OpenGLDisplayDriver : DisplayDriver glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); +#if ENABLE_GL_FFP + if(!capabilities.shaders) + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); +#endif mipMap.Allocate(null, w, h, w, pixelFormatRGBA, false); @@ -2325,18 +1898,28 @@ class OpenGLDisplayDriver : DisplayDriver return result; } - bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps) + bool MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps, uint cubeMapFace) { bool result = false; OGLSystem oglSystem = displaySystem.driverData; + GLCapabilities capabilities = oglSystem.capabilities; + Bitmap convBitmap = bitmap; + bool oldStyleCubeMap = (cubeMapFace >> 3) != 0; + int face = (cubeMapFace & 7) - 1; + if(bitmap.keepData) + { + convBitmap = { }; + convBitmap.Copy(bitmap); + } // Pre process the bitmap... First make it 32 bit - if(/*bitmap.pixelFormat == pixelFormatRGBA || */bitmap.Convert(null, pixelFormat888, null)) + if(/*bitmap.pixelFormat == pixelFormatRGBA || */convBitmap.Convert(null, pixelFormat888, null)) { int c, level; uint w = bitmap.width, h = bitmap.height; - GLuint glBitmap = 0; - if(oglSystem.pow2textures) + GLuint glBitmap = cubeMapFace && face > 0 ? (GLuint)(uintptr)bitmap.driverData : 0; + int target = cubeMapFace ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; + if(!capabilities.nonPow2Textures) { w = pow2i(w); h = pow2i(h); @@ -2353,51 +1936,105 @@ class OpenGLDisplayDriver : DisplayDriver // Switch ARGB to RGBA //if(bitmap.format != pixelFormatRGBA) { - for(c=0; c 1 || h > 1); level++, w >>= 1, h >>= 1) + for(level = 0; result && (w >= 1 || h >= 1); level++, w >>= 1, h >>= 1) { Bitmap mipMap; + if(!w) w = 1; + if(!h) h = 1; if(bitmap.width != w || bitmap.height != h) { mipMap = Bitmap { }; - if(mipMap.Allocate(null, w, h, w, bitmap.pixelFormat, false)) + if(mipMap.Allocate(null, w, h, w, convBitmap.pixelFormat, false)) { Surface mipSurface = mipMap.GetSurface(0,0,null); - mipSurface.Filter(bitmap, 0,0,0,0, w, h, bitmap.width, bitmap.height); + mipSurface.blend = false; + mipSurface.Filter(convBitmap, 0,0,0,0, w, h, convBitmap.width, convBitmap.height); delete mipSurface; } else @@ -2407,7 +2044,7 @@ class OpenGLDisplayDriver : DisplayDriver } } else - mipMap = bitmap; + mipMap = convBitmap; if(result) { @@ -2415,7 +2052,7 @@ class OpenGLDisplayDriver : DisplayDriver //int width = 0; glGetError(); // glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture); - glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture); + glTexImage2D(cubeMapFace ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + face : GL_TEXTURE_2D, level, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, mipMap.picture); //printf("Calling glTexImage2D\n"); //glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, &width); //printf("width = %d (Should be %d, %d)\n", width, w, h); @@ -2426,22 +2063,23 @@ class OpenGLDisplayDriver : DisplayDriver result = false; } } - if(mipMap != bitmap) + if(mipMap != convBitmap) delete mipMap; if(!mipMaps) break; } - if(!bitmap.keepData) - bitmap.driver.FreeBitmap(bitmap.displaySystem, bitmap); + convBitmap.driver.FreeBitmap(convBitmap.displaySystem, convBitmap); bitmap.driverData = (void *)(uintptr)glBitmap; bitmap.driver = displaySystem.driver; + if(bitmap.keepData) + delete convBitmap; if(!result) FreeBitmap(displaySystem, bitmap); else if(oglSystem.loadingFont) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); oglSystem.loadingFont = false; } } @@ -2463,20 +2101,19 @@ class OpenGLDisplayDriver : DisplayDriver bool GetSurface(Display display, Surface surface, int x,int y, Box clip) { bool result = false; + OGLDisplay oglDisplay = display.driverData; OGLSurface oglSurface = surface.driverData = OGLSurface { }; - - //Logf("GetSurface\n"); - if(oglSurface) { + SETCAPS(oglDisplay.capabilities); if(displayWidth != display.width || displayHeight != display.height) { displayWidth = display.width; displayHeight = display.height; glViewport(0,0,display.width,display.height); - glLoadIdentity(); - glOrtho(0,display.width,display.height,0,0.0,1.0); + GLLoadIdentity(); + GLOrtho(0,display.width,display.height,0,0.0,1.0); } surface.offset.x = x; @@ -2502,8 +2139,6 @@ class OpenGLDisplayDriver : DisplayDriver { Box box; - //Logf("Clip\n"); - if(clip != null) { box = clip; @@ -2540,9 +2175,11 @@ class OpenGLDisplayDriver : DisplayDriver uint row; glPixelStorei(GL_PACK_ALIGNMENT, 4); +#if ENABLE_GL_LEGACY glPixelStorei(GL_PACK_ROW_LENGTH, bitmap.stride); glPixelStorei(GL_PACK_SKIP_ROWS, 0); glPixelStorei(GL_PACK_SKIP_PIXELS, 0); +#endif glReadPixels(x,display.height-h-y,w,h,GL_BGRA_EXT,GL_UNSIGNED_BYTE, flippingBuffer); // Need a flip... @@ -2558,8 +2195,6 @@ class OpenGLDisplayDriver : DisplayDriver { OGLSurface oglSurface = surface.driverData; - //Logf("SetForeground\n"); - oglSurface.foreground[0] = color.color.r/255.0f; oglSurface.foreground[1] = color.color.g/255.0f; oglSurface.foreground[2] = color.color.b/255.0f; @@ -2573,8 +2208,6 @@ class OpenGLDisplayDriver : DisplayDriver { OGLSurface oglSurface = surface.driverData; - //Logf("SetBackground\n"); - oglSurface.background[0] = color.color.r/255.0f; oglSurface.background[1] = color.color.g/255.0f; oglSurface.background[2] = color.color.b/255.0f; @@ -2600,15 +2233,11 @@ class OpenGLDisplayDriver : DisplayDriver void PutPixel(Display display, Surface surface,int x,int y) { OGLSurface oglSurface = surface.driverData; - - //Logf("PutPixel\n"); - - glColor4fv(oglSurface.foreground); - glBegin(GL_POINTS); + GLColor4fv(oglSurface.foreground); + GLBegin(GL_POINTS); // glVertex2i(x+surface.offset.x, y+surface.offset.y); - glVertex2f(x+surface.offset.x + 0.5f, y+surface.offset.y + 0.5f); - - glEnd(); + GLVertex2f(x+surface.offset.x + 0.5f, y+surface.offset.y + 0.5f); + GLEnd(); } void DrawLine(Display display, Surface surface, int _x1, int _y1, int _x2, int _y2) @@ -2634,30 +2263,26 @@ class OpenGLDisplayDriver : DisplayDriver x2 += surface.offset.x; y2 += surface.offset.y; - //Logf("Line\n"); - - glColor4fv(oglSurface.foreground); - glBegin(GL_LINES); -#ifdef __ANDROID__ + GLColor4fv(oglSurface.foreground); + GLBegin(GL_LINES); if(stippleEnabled) { - glTexCoord2f(0.5f, 0); - glVertex2f(x1 + 0.5f, y1 + 0.5f); - glTexCoord2f(Max(x2-x1, y2-y1) + 0.5f, 0); - glVertex2f(x2 + 0.5f, y2 + 0.5f); + GLTexCoord2f(0.5f, 0); + GLVertex2f(x1 + 0.5f, y1 + 0.5f); + GLTexCoord2f(Max(x2-x1, y2-y1) + 0.5f, 0); + GLVertex2f(x2 + 0.5f, y2 + 0.5f); } else -#endif { /* - glVertex2i(x1, y1); - glVertex2i(x2, y2); + GLVertex2i(x1, y1); + GLVertex2i(x2, y2); */ - glVertex2f(x1 + 0.5f, y1 + 0.5f); - glVertex2f(x2 + 0.5f, y2 + 0.5f); + GLVertex2f(x1 + 0.5f, y1 + 0.5f); + GLVertex2f(x2 + 0.5f, y2 + 0.5f); } - glEnd(); + GLEnd(); } void Rectangle(Display display, Surface surface,int x1,int y1,int x2,int y2) @@ -2668,63 +2293,58 @@ class OpenGLDisplayDriver : DisplayDriver x2 += surface.offset.x; y2 += surface.offset.y; - //Logf("Rectangle\n"); - - glColor4fv(oglSurface.foreground); -#ifdef __ANDROID__ + GLColor4fv(oglSurface.foreground); if(stippleEnabled) { - glBegin(GL_LINES); - - glTexCoord2f(0.5f, 0); - glVertex2f(x1 + 0.5f, y1 + 0.5f); - glTexCoord2f(y2-y1 + 0.5f, 0); - glVertex2f(x1 + 0.5f, y2 + 0.5f); - - glTexCoord2f(0.5f, 0); - glVertex2f(x1 + 0.5f, y2 + 0.5f); - glTexCoord2f(x2 - x1 + 0.5f, 0); - glVertex2f(x2 + 0.5f, y2 + 0.5f); - - glTexCoord2f(0.5f, 0); - glVertex2f(x2 + 0.5f, y2 + 0.5f); - glTexCoord2f(y1 - y2 + 0.5f, 0); - glVertex2f(x2 + 0.5f, y1 + 0.5f); - - glTexCoord2f(0.5f, 0); - glVertex2f(x2 + 0.5f, y1 + 0.5f); - glTexCoord2f(x1 - x2 + 0.5f, 0); - glVertex2f(x1 + 0.5f, y1 + 0.5f); + GLBegin(GL_LINES); + + GLTexCoord2f(0.5f, 0); + GLVertex2f(x1 + 0.5f, y1 + 0.5f); + GLTexCoord2f(y2-y1 + 0.5f, 0); + GLVertex2f(x1 + 0.5f, y2 + 0.5f); + + GLTexCoord2f(0.5f, 0); + GLVertex2f(x1 + 0.5f, y2 + 0.5f); + GLTexCoord2f(x2 - x1 + 0.5f, 0); + GLVertex2f(x2 + 0.5f, y2 + 0.5f); + + GLTexCoord2f(0.5f, 0); + GLVertex2f(x2 + 0.5f, y2 + 0.5f); + GLTexCoord2f(y1 - y2 + 0.5f, 0); + GLVertex2f(x2 + 0.5f, y1 + 0.5f); + + GLTexCoord2f(0.5f, 0); + GLVertex2f(x2 + 0.5f, y1 + 0.5f); + GLTexCoord2f(x1 - x2 + 0.5f, 0); + GLVertex2f(x1 + 0.5f, y1 + 0.5f); } else -#endif { - glBegin(GL_LINE_LOOP); + GLBegin(GL_LINE_LOOP); /* glVertex2i(x1, y1); glVertex2i(x1, y2); glVertex2i(x2, y2); glVertex2i(x2, y1); */ - glVertex2f(x1 + 0.5f, y1 + 0.5f); - glVertex2f(x1 + 0.5f, y2 + 0.5f); - glVertex2f(x2 + 0.5f, y2 + 0.5f); - glVertex2f(x2 + 0.5f, y1 + 0.5f); + GLVertex2f(x1 + 0.5f, y1 + 0.5f); + GLVertex2f(x1 + 0.5f, y2 + 0.5f); + GLVertex2f(x2 + 0.5f, y2 + 0.5f); + GLVertex2f(x2 + 0.5f, y1 + 0.5f); } - glEnd(); + GLEnd(); } void Area(Display display, Surface surface,int x1,int y1,int x2,int y2) { OGLSurface oglSurface = surface.driverData; - //Logf("Area\n"); - glColor4fv(oglSurface.background); - glRecti(x1+surface.offset.x, y1+surface.offset.y, - x2+surface.offset.x + 1, y2+surface.offset.y + 1); + GLColor4fv(oglSurface.background); + GLRecti(x1+surface.offset.x, y1+surface.offset.y, + x2+surface.offset.x + 1, y2+surface.offset.y + 1); /* - glRectf(x1+surface.offset.x, y1+surface.offset.y, + GLRectf(x1+surface.offset.x, y1+surface.offset.y, x2+surface.offset.x + 1, y2+surface.offset.y + 1); */ } @@ -2757,73 +2377,65 @@ class OpenGLDisplayDriver : DisplayDriver void Blit(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h) { OGLSurface oglSurface = surface.driverData; - -#if !defined(__OLDX__) - // WHY DO WE HAVE GL_ONE HERE ? - /*if(glBlendFuncSeparate && !oglSurface.writingText) - glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);*/ -#endif + GLuint tex = (GLuint)(uintptr)bitmap.driverData; + if(!tex) return; if(!oglSurface.writingText) { // glTranslatef(-0.375f, -0.375f, 0.0f); - glEnable(GL_TEXTURE_2D); - glColor4fv(oglSurface.bitmapMult); + GLSetupTexturing(true); + GLColor4fv(oglSurface.bitmapMult); + glBindTexture(GL_TEXTURE_2D, tex); + GLBegin(GLIMTKMode::quads); + } + else if(lastBlitTex != tex) + { + if(lastBlitTex) + GLEnd(); + glBindTexture(GL_TEXTURE_2D, tex); + GLBegin(GLIMTKMode::quads); + lastBlitTex = tex; } - else if(oglSurface.xOffset) - glTranslated(oglSurface.xOffset / 64.0/*-0.375*/, 0.0, 0.0); - - glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)bitmap.driverData); - glBegin(GL_QUADS); if(h < 0) { - glTexCoord2f((float)sx/ bitmap.width, (float)(sy-h)/ bitmap.height); - glVertex2i(dx+surface.offset.x, dy+surface.offset.y); - glTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy-h)/ bitmap.height); - glVertex2i(dx+w+surface.offset.x, dy+surface.offset.y); - glTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height); - glVertex2i(dx+w+surface.offset.x, dy-h+surface.offset.y); - glTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height); - glVertex2i(dx+surface.offset.x, dy-h+surface.offset.y); + GLTexCoord2f((float)sx/ bitmap.width, (float)(sy-h)/ bitmap.height); + GLVertex2i(dx+surface.offset.x, dy+surface.offset.y); + GLTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy-h)/ bitmap.height); + GLVertex2i(dx+w+surface.offset.x, dy+surface.offset.y); + GLTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height); + GLVertex2i(dx+w+surface.offset.x, dy-h+surface.offset.y); + GLTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height); + GLVertex2i(dx+surface.offset.x, dy-h+surface.offset.y); } else { /* - glTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height); - glVertex2i(dx+surface.offset.x, dy+surface.offset.y); - glTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height); - glVertex2i(dx+w+surface.offset.x, dy+surface.offset.y); - glTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy+h)/ bitmap.height); - glVertex2i(dx+w+surface.offset.x, dy+h+surface.offset.y); - glTexCoord2f((float)sx/ bitmap.width, (float)(sy+h)/ bitmap.height); - glVertex2i(dx+surface.offset.x, dy+h+surface.offset.y); + GLTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height); + GLVertex2i(dx+surface.offset.x, dy+surface.offset.y); + GLTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height); + GLVertex2i(dx+w+surface.offset.x, dy+surface.offset.y); + GLTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy+h)/ bitmap.height); + GLVertex2i(dx+w+surface.offset.x, dy+h+surface.offset.y); + GLTexCoord2f((float)sx/ bitmap.width, (float)(sy+h)/ bitmap.height); + GLVertex2i(dx+surface.offset.x, dy+h+surface.offset.y); */ - glTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height); - glVertex2f((float)dx+surface.offset.x, (float)dy+surface.offset.y); - glTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height); - glVertex2f((float)dx+w+surface.offset.x, (float)dy+surface.offset.y); - glTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy+h)/ bitmap.height); - glVertex2f((float)dx+w+surface.offset.x, (float)dy+h+surface.offset.y); - glTexCoord2f((float)sx/ bitmap.width, (float)(sy+h)/ bitmap.height); - glVertex2f((float)dx+surface.offset.x, (float)dy+h+surface.offset.y); + GLTexCoord2f((float)sx / bitmap.width, (float)sy/ bitmap.height); + GLVertex2f((float)dx+surface.offset.x, (float)dy+surface.offset.y); + GLTexCoord2f((float)(sx+w)/ bitmap.width, (float)sy/ bitmap.height); + GLVertex2f((float)dx+w+surface.offset.x, (float)dy+surface.offset.y); + GLTexCoord2f((float)(sx+w) / bitmap.width, (float)(sy+h)/ bitmap.height); + GLVertex2f((float)dx+w+surface.offset.x, (float)dy+h+surface.offset.y); + GLTexCoord2f((float)sx/ bitmap.width, (float)(sy+h)/ bitmap.height); + GLVertex2f((float)dx+surface.offset.x, (float)dy+h+surface.offset.y); } - glEnd(); - if(!oglSurface.writingText) { - glDisable(GL_TEXTURE_2D); - + GLEnd(); + GLSetupTexturing(false); //glTranslate(0.375, 0.375, 0.0); } - else if(oglSurface.xOffset) - glTranslated(-oglSurface.xOffset / 64.0/*+0.375*/, 0.0, 0.0); - -#if !defined(__OLDX__) - /*if(glBlendFuncSeparate && !oglSurface.writingText) - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);*/ -#endif } void Stretch(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh) @@ -2832,59 +2444,47 @@ class OpenGLDisplayDriver : DisplayDriver //glTranslate(-0.375, -0.375, 0.0); - //Logf("Stretch\n"); - -#if !defined(__OLDX__) - /*if(glBlendFuncSeparate) - glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);*/ -#endif - - glEnable(GL_TEXTURE_2D); + GLSetupTexturing(true); glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)bitmap.driverData); - glColor4fv(oglSurface.bitmapMult); + GLColor4fv(oglSurface.bitmapMult); - glBegin(GL_QUADS); + GLBegin(GLIMTKMode::quads); if(h < 0) { - glTexCoord2f((float)(sx)/ bitmap.width, (float)(sy+sh)/ bitmap.height); - glVertex2i(dx+surface.offset.x, dy+surface.offset.y); + GLTexCoord2f((float)(sx)/ bitmap.width, (float)(sy+sh)/ bitmap.height); + GLVertex2i(dx+surface.offset.x, dy+surface.offset.y); - glTexCoord2f((float)(sx+sw) / bitmap.width, (float)(sy+sh)/ bitmap.height); - glVertex2i(dx+w+surface.offset.x, dy+surface.offset.y); + GLTexCoord2f((float)(sx+sw) / bitmap.width, (float)(sy+sh)/ bitmap.height); + GLVertex2i(dx+w+surface.offset.x, dy+surface.offset.y); - glTexCoord2f((float)(sx+sw)/ bitmap.width, (float)(sy)/ bitmap.height); - glVertex2i(dx+w+surface.offset.x, dy-h+surface.offset.y); + GLTexCoord2f((float)(sx+sw)/ bitmap.width, (float)(sy)/ bitmap.height); + GLVertex2i(dx+w+surface.offset.x, dy-h+surface.offset.y); - glTexCoord2f((float)(sx) / bitmap.width, (float)(sy)/ bitmap.height); - glVertex2i(dx+surface.offset.x, dy-h+surface.offset.y); + GLTexCoord2f((float)(sx) / bitmap.width, (float)(sy)/ bitmap.height); + GLVertex2i(dx+surface.offset.x, dy-h+surface.offset.y); } else { - glTexCoord2f((float)(sx) / bitmap.width, (float)(sy)/ bitmap.height); - glVertex2i(dx+surface.offset.x, dy+surface.offset.y); + GLTexCoord2f((float)(sx) / bitmap.width, (float)(sy)/ bitmap.height); + GLVertex2i(dx+surface.offset.x, dy+surface.offset.y); - glTexCoord2f((float)(sx+sw)/ bitmap.width, (float)(sy)/ bitmap.height); - glVertex2i(dx+w+surface.offset.x, dy+surface.offset.y); + GLTexCoord2f((float)(sx+sw)/ bitmap.width, (float)(sy)/ bitmap.height); + GLVertex2i(dx+w+surface.offset.x, dy+surface.offset.y); - glTexCoord2f((float)(sx+sw) / bitmap.width, (float)(sy+sh)/ bitmap.height); - glVertex2i(dx+w+surface.offset.x, dy+h+surface.offset.y); + GLTexCoord2f((float)(sx+sw) / bitmap.width, (float)(sy+sh)/ bitmap.height); + GLVertex2i(dx+w+surface.offset.x, dy+h+surface.offset.y); - glTexCoord2f((float)(sx)/ bitmap.width, (float)(sy+sh)/ bitmap.height); - glVertex2i(dx+surface.offset.x, dy+h+surface.offset.y); + GLTexCoord2f((float)(sx)/ bitmap.width, (float)(sy+sh)/ bitmap.height); + GLVertex2i(dx+surface.offset.x, dy+h+surface.offset.y); } - glEnd(); + GLEnd(); - glDisable(GL_TEXTURE_2D); + GLSetupTexturing(false); //glTranslate(0.375, 0.375, 0.0); -#if !defined(__OLDX__) - /*if(glBlendFuncSeparate) - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);*/ -#endif - } void Filter(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh) @@ -2897,8 +2497,6 @@ class OpenGLDisplayDriver : DisplayDriver float s2dw,s2dh,d2sw,d2sh; //bool flipX = false, flipY = false; - //Logf("StretchDI\n"); - if(Sgn(w) != Sgn(sw)) { w = Abs(w); @@ -2978,24 +2576,27 @@ class OpenGLDisplayDriver : DisplayDriver if(bitmap.pixelFormat == pixelFormat888 && !bitmap.paletteShades) { glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glPixelStorei(GL_UNPACK_ROW_LENGTH, bitmap.stride); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx); - glPixelStorei(GL_UNPACK_SKIP_ROWS, sy); - glRasterPos2d(dx,dy); - //glPixelZoom(flipX ? -s2dw : s2dw, flipY ? s2dh : -s2dh); - glPixelZoom(s2dw, -s2dh); - glDrawPixels(sw,sh,GL_BGRA_EXT,GL_UNSIGNED_BYTE, bitmap.picture); +#if ENABLE_GL_LEGACY + if(glCaps_legacy) + { + glPixelStorei(GL_UNPACK_ROW_LENGTH, bitmap.stride); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx); + glPixelStorei(GL_UNPACK_SKIP_ROWS, sy); + glRasterPos2d(dx,dy); + //glPixelZoom(flipX ? -s2dw : s2dw, flipY ? s2dh : -s2dh); + glPixelZoom(s2dw, -s2dh); + glDrawPixels(sw,sh,GL_BGRA_EXT,GL_UNSIGNED_BYTE, bitmap.picture); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + } +#endif glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); } } void BlitDI(Display display, Surface surface, Bitmap bitmap, int dx, int dy, int sx, int sy, int w, int h) { - //Logf("BlitDI\n"); - //Clip against the edges of the source if(sx<0) { @@ -3043,16 +2644,21 @@ class OpenGLDisplayDriver : DisplayDriver if(bitmap.pixelFormat == pixelFormat888 && !bitmap.paletteShades) { glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glPixelStorei(GL_UNPACK_ROW_LENGTH, bitmap.stride); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx); - glPixelStorei(GL_UNPACK_SKIP_ROWS, sy); - glRasterPos2d(dx,dy); - glPixelZoom(1,-1); - glDrawPixels(w,h,GL_BGRA_EXT,GL_UNSIGNED_BYTE, bitmap.picture); +#if ENABLE_GL_LEGACY + if(glCaps_legacy) + { + glPixelStorei(GL_UNPACK_ROW_LENGTH, bitmap.stride); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx); + glPixelStorei(GL_UNPACK_SKIP_ROWS, sy); + glRasterPos2d(dx,dy); + glPixelZoom(1,-1); + glDrawPixels(w,h,GL_BGRA_EXT,GL_UNSIGNED_BYTE, bitmap.picture); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + } +#endif glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); - glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); } } @@ -3066,49 +2672,70 @@ class OpenGLDisplayDriver : DisplayDriver ((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, font); } - Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags) + Font LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags, float outlineSize, float outlineFade) { Font font; OGLSystem oglSystem = displaySystem.driverData; oglSystem.loadingFont = true; - font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags); + font = ((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags, outlineSize, outlineFade); return font; } - void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height) + void FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * adv) { - ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(displaySystem, font, text, len, width, height); + ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(displaySystem, font, text, len, width, height, prevGlyph, rPrevGlyph, adv); } - void WriteText(Display display, Surface surface, int x, int y, const char * text, int len) + void WriteText(Display display, Surface surface, int x, int y, const char * text, int len, int prevGlyph, int * rPrevGlyph) { - OGLSurface oglSurface = surface.driverData; - OGLSystem oglSystem = display.displaySystem.driverData; - oglSystem.loadingFont = true; + if(len && text[0] && surface.font) + { + OGLSurface oglSurface = surface.driverData; + OGLSystem oglSystem = display.displaySystem.driverData; + oglSystem.loadingFont = true; - //glTranslated(-0.375, -0.375, 0.0); + //glTranslated(-0.375, -0.375, 0.0); - //Logf("Blit\n"); + if(surface.textOpacity) + { + int w = 0, h, adv = 0; + FontExtent(display.displaySystem, surface.font, text, len, &w, &h, 0, null, &adv); + w += adv; + display.displaySystem.driver.Area(display, surface,x,y,x+w-1,y+h-1); + } - if(surface.textOpacity) - { - int w, h; - FontExtent(display.displaySystem, surface.font, text, len, &w, &h); - display.displaySystem.driver.Area(display, surface,x,y,x+w-1,y+h-1); - } + oglSurface.writingText = true; + + GLSetupTexturing(true); + + x <<= 6; + if(surface.font.outlineSize) + { + ColorAlpha outlineColor = surface.outlineColor; + int fx = x; + + GLColor4ub(outlineColor.color.r, outlineColor.color.g, outlineColor.color.b, outlineColor.a); + oglSurface.writingOutline = true; + lastBlitTex = 0; + oglSurface.font.ProcessString(surface.displaySystem, (const byte *)text, len, true, surface, display, &fx, y, prevGlyph, rPrevGlyph, null); + if(lastBlitTex) GLEnd(); + oglSurface.writingOutline = false; + } + GLColor4fv(oglSurface.foreground); - oglSurface.writingText = true; + lastBlitTex = 0; + oglSurface.font.ProcessString(surface.displaySystem, (const byte *)text, len, true, surface, display, &x, y, prevGlyph, rPrevGlyph, null); - glEnable(GL_TEXTURE_2D); - glColor4fv(oglSurface.foreground); + if(lastBlitTex) GLEnd(); + lastBlitTex = 0; - ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x, y, text, len); - oglSurface.writingText = false; - oglSystem.loadingFont = false; + oglSurface.writingText = false; + oglSystem.loadingFont = false; - glDisable(GL_TEXTURE_2D); + GLSetupTexturing(false); - //glTranslated(0.375, 0.375, 0.0); + //glTranslated(0.375, 0.375, 0.0); + } } void TextFont(Display display, Surface surface, Font font) @@ -3122,12 +2749,12 @@ class OpenGLDisplayDriver : DisplayDriver oglSurface.opaqueText = opaque; } - void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height) + void TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height, int prevGlyph, int * rPrevGlyph, int * adv) { OGLSurface oglSurface = surface.driverData; OGLSystem oglSystem = display.displaySystem.driverData; oglSystem.loadingFont = true; - FontExtent(display.displaySystem, oglSurface.font, text, len, width, height); + FontExtent(display.displaySystem, oglSurface.font, text, len, width, height, prevGlyph, rPrevGlyph, adv); oglSystem.loadingFont = false; } @@ -3138,47 +2765,75 @@ class OpenGLDisplayDriver : DisplayDriver void LineStipple(Display display, Surface surface, uint32 stipple) { - //Logf("Stipple\n"); - if(stipple) { -#if defined(__ANDROID__) - stippleEnabled = true; - glesLineStipple(1, (uint16)stipple); -#else - glLineStipple(1, (uint16)stipple); - glEnable(GL_LINE_STIPPLE); +#if ENABLE_GL_LEGACY + if(glCaps_legacy) + { + glLineStipple(1, (uint16)stipple); + glEnable(GL_LINE_STIPPLE); + } + else #endif + { + stippleEnabled = true; + glsupLineStipple(1, (uint16)stipple); + } } else { -#if defined(__ANDROID__) - stippleEnabled = false; - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glDisable(GL_TEXTURE_2D); -#else - glDisable(GL_LINE_STIPPLE); +#if ENABLE_GL_LEGACY + if(glCaps_legacy) + glDisable(GL_LINE_STIPPLE); + else #endif + { + stippleEnabled = false; + GLMatrixMode(GL_TEXTURE); + GLLoadIdentity(); + GLMatrixMode(MatrixMode::projection); + GLSetupTexturing(false); // TODO: Special shading code for stipple? + } + } + } +#if ENABLE_GL_FFP + void ::disableRemainingTMUs(Display display, int lastTMU) + { + OGLDisplay oglDisplay = display.driverData; + int t; + for(t = lastTMU; t < oglDisplay.maxTMU; t++) + { + glActiveTexture(GL_TEXTURE0 + t); + glClientActiveTexture(GL_TEXTURE0 + t); + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_CUBE_MAP); + GLDisableClientState(TEXCOORDS); } + glActiveTexture(GL_TEXTURE0); + glClientActiveTexture(GL_TEXTURE0); + oglDisplay.maxTMU = lastTMU; } +#endif + #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA) void SetRenderState(Display display, RenderState state, uint value) { OGLDisplay oglDisplay = display.driverData; - //Logf("RenderState\n"); - switch(state) { case antiAlias: +#ifndef __EMSCRIPTEN__ if(value) - glEnable(GL_MULTISAMPLE_ARB); + glEnable(GL_MULTISAMPLE); else - glDisable(GL_MULTISAMPLE_ARB); + glDisable(GL_MULTISAMPLE); +#endif break; case fillMode: - glPolygonMode(GL_FRONT_AND_BACK, ((FillModeValue)value == solid) ? GL_FILL : GL_LINE); +#if ENABLE_GL_LEGACY + if(glCaps_legacy) + glPolygonMode(GL_FRONT_AND_BACK, ((FillModeValue)value == solid) ? GL_FILL : GL_LINE); +#endif break; case depthTest: if(value) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); @@ -3190,19 +2845,47 @@ class OpenGLDisplayDriver : DisplayDriver case fogColor: { float color[4] = { ((Color)value).r/255.0f, ((Color)value).g/255.0f, ((Color)value).b/255.0f, 1.0f }; - glFogfv(GL_FOG_COLOR, (float *)&color); +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + defaultShader.setFogColor(color[0], color[1], color[2]); +#endif + +#if ENABLE_GL_FFP + if(!glCaps_shaders) + glFogfv(GL_FOG_COLOR, (float *)&color); +#endif break; } case fogDensity: - glFogf(GL_FOG_DENSITY, (float)(RenderStateFloat { value }.f * nearPlane)); +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + defaultShader.setFogDensity((float)(RenderStateFloat { ui = value }.f * nearPlane)); +#endif + +#if ENABLE_GL_FFP + if(!glCaps_shaders) + glFogf(GL_FOG_DENSITY, (float)(RenderStateFloat { ui = value }.f * nearPlane)); +#endif break; case blend: +//#if !defined(__EMSCRIPTEN__) if(value) glEnable(GL_BLEND); else glDisable(GL_BLEND); +//#endif break; case ambient: { - float ambient[4] = { ((Color)value).r/255.0f, ((Color)value).g/255.0f, ((Color)value).b/255.0f, 1.0f }; - glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + defaultShader.setGlobalAmbient(((Color)value).r / 255.0f, ((Color)value).g / 255.0f, ((Color)value).b / 255.0f, 1.0f); +#endif + +#if ENABLE_GL_FFP + if(!glCaps_shaders) + { + float ambient[4] = { ((Color)value).r/255.0f, ((Color)value).g/255.0f, ((Color)value).b/255.0f, 1.0f }; + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); + } +#endif break; } case alphaWrite: @@ -3213,7 +2896,8 @@ class OpenGLDisplayDriver : DisplayDriver case vSync: { #if defined(__WIN32__) - wglSwapIntervalEXT(value ? 1 : 0); + if(wglSwapIntervalEXT) + wglSwapIntervalEXT(value ? 1 : 0); #endif break; } @@ -3222,165 +2906,169 @@ class OpenGLDisplayDriver : DisplayDriver void SetLight(Display display, int id, Light light) { - //Logf("SetLight\n"); +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + defaultShader.setLight(display, id, light); +#endif - if(light != null) +#if ENABLE_GL_FFP + if(!glCaps_shaders) { - Object lightObject = light.lightObject; - float position[4] = { 0, 0, 0, 0 }; - float color[4] = { 0, 0, 0, 1 }; + if(light != null && !light.flags.off) + { + Object lightObject = light.lightObject; + float position[4] = { 0, 0, 0, 0 }; + float color[4] = { 0, 0, 0, 1 }; + Vector3D l; - glEnable(GL_LIGHT0 + id); - /* - glLightfv(GL_LIGHT0 + id, GL_DIFFUSE, (float *)&light.diffuse); - glLightfv(GL_LIGHT0 + id, GL_AMBIENT, (float *)&light.ambient); - glLightfv(GL_LIGHT0 + id, GL_SPECULAR,(float *)&light.specular); - */ + glEnable(GL_LIGHT0 + id); - if(!light.multiplier) light.multiplier = 1.0f; + if(!light.multiplier) light.multiplier = 1.0f; - color[0] = light.diffuse.r * light.multiplier; - color[1] = light.diffuse.g * light.multiplier; - color[2] = light.diffuse.b * light.multiplier; - glLightfv(GL_LIGHT0 + id, GL_DIFFUSE, color); + GLFlushMatrices(); - color[0] = light.ambient.r * light.multiplier; - color[1] = light.ambient.g * light.multiplier; - color[2] = light.ambient.b * light.multiplier; - glLightfv(GL_LIGHT0 + id, GL_AMBIENT, color); - color[0] = light.specular.r * light.multiplier; - color[1] = light.specular.g * light.multiplier; - color[2] = light.specular.b * light.multiplier; - glLightfv(GL_LIGHT0 + id, GL_SPECULAR,color); + color[0] = light.diffuse.r * light.multiplier; + color[1] = light.diffuse.g * light.multiplier; + color[2] = light.diffuse.b * light.multiplier; + glLightfv(GL_LIGHT0 + id, GL_DIFFUSE, color); - if(lightObject) - { - Vector3D positionVector; - if(light.flags.spot) + color[0] = light.ambient.r * light.multiplier; + color[1] = light.ambient.g * light.multiplier; + color[2] = light.ambient.b * light.multiplier; + glLightfv(GL_LIGHT0 + id, GL_AMBIENT, color); + + color[0] = light.specular.r * light.multiplier; + color[1] = light.specular.g * light.multiplier; + color[2] = light.specular.b * light.multiplier; + glLightfv(GL_LIGHT0 + id, GL_SPECULAR,color); + + if(lightObject) { - if(lightObject.flags.root || !lightObject.parent) + // Positional Lights, including Spot Lights (and omni light with flags.spot not set) + Matrix * mat = &lightObject.matrix; + l = { mat->m[3][0], mat->m[3][1], mat->m[3][2] }; + if(display.display3D && display.display3D.camera) + l.Subtract(l, display.display3D.camera.cPosition); + + position[0] = (float)l.x, position[1] = (float)l.y, position[2] = (float)l.z, position[3] = 1; + + if(light.flags.attenuation) { - positionVector = lightObject.transform.position; - positionVector.Subtract(positionVector, display.display3D.camera.cPosition); + glLightf(GL_LIGHT0 + id, GL_CONSTANT_ATTENUATION, light.Kc); + glLightf(GL_LIGHT0 + id, GL_LINEAR_ATTENUATION, light.Kl); + glLightf(GL_LIGHT0 + id, GL_QUADRATIC_ATTENUATION, light.Kq); } else { - positionVector.MultMatrix(lightObject.transform.position, lightObject.parent.matrix); - if(display.display3D.camera) - positionVector.Subtract(positionVector, display.display3D.camera.cPosition); + glLightf(GL_LIGHT0 + id, GL_CONSTANT_ATTENUATION, 1); + glLightf(GL_LIGHT0 + id, GL_LINEAR_ATTENUATION, 0); + glLightf(GL_LIGHT0 + id, GL_QUADRATIC_ATTENUATION, 0); } - position[3] = 1; - } - else - { - if(!light.direction.x && !light.direction.y && !light.direction.z) + + if((light.flags.spot && light.fallOff < 360) || (lightObject && (light.direction.x || light.direction.y || light.direction.z))) { - Vector3Df vector { 0,0,-1 }; - Matrix mat; - mat.RotationQuaternion(light.orientation); - positionVector.MultMatrixf(vector, mat); + // Figure out exponent out of the hot spot + #define MAXLIGHT 0.9 + float exponent = light.flags.spot ? (float)(log(MAXLIGHT) / log(cos(light.hotSpot / 2))) : 1; + Degrees cutOff = light.flags.spot ? light.fallOff/2 : 90; + float direction[4] = { (float)light.direction.x, (float)light.direction.y, (float)light.direction.z, 1 }; + + glLightfv(GL_LIGHT0 + id, GL_SPOT_DIRECTION, direction); + glLightf(GL_LIGHT0 + id, GL_SPOT_CUTOFF, (float)cutOff); + glLightf(GL_LIGHT0 + id, GL_SPOT_EXPONENT, exponent); } else { - positionVector = light.direction; - position[3] = 1; + float d[4] = { 0, 0, 1, 0 }; + glLightfv(GL_LIGHT0 + id, GL_SPOT_DIRECTION, d); + glLightf(GL_LIGHT0 + id, GL_SPOT_CUTOFF, 180); + glLightf(GL_LIGHT0 + id, GL_SPOT_EXPONENT, 1); } - } - - position[0] = (float)positionVector.x; - position[1] = (float)positionVector.y; - position[2] = (float)positionVector.z; - glLightfv(GL_LIGHT0 + id, GL_POSITION, position); + /* + if(lightObject) + { + // Display Light Position + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glColor3f(1,1,1); + glPointSize(10); + glBegin(GL_POINTS); + glVertex3fv(position); + glEnd(); + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); + + + // Display Target + if(lightObject.flags.root || !lightObject.parent) + { + positionVector = light.target.transform.position; + positionVector.Subtract(positionVector, display.camera.cPosition); + } + else + { + positionVector.MultMatrix(light.target.transform.position, + lightObject.light.target.parent.matrix); + positionVector.Subtract(positionVector, display.camera.cPosition); + } - /* - // Display Light Position - glDisable(GL_LIGHTING); - glDisable(GL_DEPTH_TEST); - glColor3f(1,1,1); - glPointSize(10); - glBegin(GL_POINTS); - glVertex3fv(position); - glEnd(); - glEnable(GL_DEPTH_TEST); - glEnable(GL_LIGHTING); - - - // Display Target - if(lightObject.flags.root || !lightObject.parent) - { - positionVector = light.target.transform.position; - positionVector.Subtract(positionVector, display.camera.cPosition); + position[0] = positionVector.x; + position[1] = positionVector.y; + position[2] = positionVector.z; + + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glColor3f(1,1,0); + glPointSize(10); + glBegin(GL_POINTS); + glVertex3fv(position); + glEnd(); + glEnable(GL_DEPTH_TEST); + glEnable(GL_LIGHTING); + } + */ } else { - positionVector.MultMatrix(light.target.transform.position, - lightObject.light.target.parent.matrix); - positionVector.Subtract(positionVector, display.camera.cPosition); - } - - position[0] = positionVector.x; - position[1] = positionVector.y; - position[2] = positionVector.z; - - glDisable(GL_LIGHTING); - glDisable(GL_DEPTH_TEST); - glColor3f(1,1,0); - glPointSize(10); - glBegin(GL_POINTS); - glVertex3fv(position); - glEnd(); - glEnable(GL_DEPTH_TEST); - glEnable(GL_LIGHTING); - */ - - if(light.flags.attenuation) - { - glLightf(GL_LIGHT0 + id, GL_CONSTANT_ATTENUATION, light.Kc); - glLightf(GL_LIGHT0 + id, GL_LINEAR_ATTENUATION, light.Kl); - glLightf(GL_LIGHT0 + id, GL_QUADRATIC_ATTENUATION, light.Kq); + // Directional Light + Vector3D vector { 0,0,-1 }; + Vector3D direction; + Matrix mat; + mat.RotationQuaternion(light.orientation); + direction.MultMatrix(vector, mat); + l.Normalize(direction); + position[0] = (float)l.x, position[1] = (float)l.y, position[2] = (float)l.z, position[3] = 0; } - - if(light.flags.spot) + glLightfv(GL_LIGHT0 + id, GL_POSITION, position); + if(display.display3D) { - float exponent = 0; - #define MAXLIGHT 0.9 - float direction[4] = { (float)light.direction.x, (float)light.direction.y, (float)light.direction.z, 1 }; - // Figure out exponent out of the hot spot - exponent = (float)(log(MAXLIGHT) / log(cos((light.hotSpot / 2)))); - - glLightfv(GL_LIGHT0 + id, GL_SPOT_DIRECTION, direction); - glLightf(GL_LIGHT0 + id, GL_SPOT_CUTOFF, (float)(light.fallOff / 2)); - glLightf(GL_LIGHT0 + id, GL_SPOT_EXPONENT, exponent); + Matrix m; + Vector3Df v { position[0], position[1], position[2] }; + Vector3Df l; + float * lp = display.display3D.light0Pos; + if(display.display3D.camera) + m = display.display3D.camera.viewMatrix; + else + m.Identity(); + l.MultMatrix(v, m); + lp[0] = l.x; + lp[1] =-l.y; + lp[2] =-l.z; + lp[3] = position[3]; } } else - { - - Vector3Df vector { 0,0,-1 }; - Vector3Df direction; - Matrix mat; - - mat.RotationQuaternion(light.orientation); - direction.MultMatrix(vector, mat); - - position[0] = direction.x; - position[1] = direction.y; - position[2] = direction.z; - - glLightfv(GL_LIGHT0 + id, GL_POSITION, position); - } + glDisable(GL_LIGHT0 + id); } - else - glDisable(GL_LIGHT0 + id); +#endif } void SetCamera(Display display, Surface surface, Camera camera) { OGLDisplay oglDisplay = display.driverData; - //Logf("SetCamera\n"); - if(camera) + if(surface && camera) { int left = surface.box.left + surface.offset.x; int top = surface.box.top + surface.offset.y; @@ -3393,165 +3081,641 @@ class OpenGLDisplayDriver : DisplayDriver int w = right - left + 1; int h = bottom - top + 1; - // *** ViewPort *** - glViewport(x, y, w, h); + // *** ViewPort *** + glViewport(x, y, w, h); + + GLMatrixMode(MatrixMode::texture); + if(!display.display3D.camera) + GLPushMatrix(); + GLLoadIdentity(); + + // *** Projection Matrix *** + GLMatrixMode(MatrixMode::projection); + if(!display.display3D.camera) + GLPushMatrix(); + + if(display.display3D.collectingHits) + { + float pickX = display.display3D.pickX + surface.offset.x; + float pickY = display.height - (display.display3D.pickY + surface.offset.y) - 1; + Matrix pickMatrix + { + { + w / display.display3D.pickWidth, 0, 0, 0, + 0, h / display.display3D.pickHeight, 0, 0, + 0, 0, 1, 0, + (w + 2.0f * (x - pickX)) / display.display3D.pickWidth, + (h + 2.0f * (y - pickY)) / display.display3D.pickHeight, 0, 1 + } + }; + GLLoadMatrixd(pickMatrix.array); + } + else + GLLoadIdentity(); + GLFrustum( + (left - origX) * camera.zMin / camera.focalX, + (right - origX) * camera.zMin / camera.focalX, + (bottom - origY) * camera.zMin / camera.focalY, + (top - origY) * camera.zMin / camera.focalY, + camera.zMin, camera.zMax); + + glDisable(GL_BLEND); + + // *** Z Inverted Identity Matrix *** + GLMatrixMode(MatrixMode::modelView); + if(!display.display3D.camera) + GLPushMatrix(); + + GLLoadIdentity(); + + GLScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane); + + // *** View Matrix *** + GLMultMatrixd(camera.viewMatrix.array); + +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + { + defaultShader.select(); + defaultShader.setCamera(camera); + } +#endif + + // *** Lights *** + // ... + + glEnable(GL_DEPTH_TEST); + + GLSetupLighting(true); +#if ENABLE_GL_FFP + if(!glCaps_shaders) + glShadeModel(GL_SMOOTH); +#endif + glDepthMask((byte)bool::true); + oglDisplay.depthWrite = true; + +#ifndef __EMSCRIPTEN__ + glEnable(GL_MULTISAMPLE); +#endif + } + else if(surface && display.display3D.camera) + { + nearPlane = 1; + oglDisplay.depthWrite = false; + glViewport(0,0,display.width,display.height); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + + GLDisableClientState(COLORS); +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + { + GLDisableClientState(TANGENTS1); + GLDisableClientState(TANGENTS2); + } +#endif + GLDisableClientState(NORMALS); +#if ENABLE_GL_FFP + if(!glCaps_shaders) + GLDisableClientState(LIGHTVECTORS); +#endif + + // *** Restore 2D MODELVIEW Matrix *** + GLMatrixMode(MatrixMode::modelView); + GLPopMatrix(); + + // *** Restore 2D TEXTURE Matrix *** + GLMatrixMode(MatrixMode::texture); + GLPopMatrix(); + + // *** Restore 2D PROJECTION Matrix *** + GLMatrixMode(MatrixMode::projection); + GLPopMatrix(); + + // NOTE: We expect the 2D projection matrix to be the active one for GetSurface to call glOrtho() + +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + defaultShader.select(); +#endif + +#if ENABLE_GL_FFP + if(!glCaps_shaders) + { + disableRemainingTMUs(display, 0); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glDisable(GL_TEXTURE_CUBE_MAP); + #if _GLES + glDisable(GL_TEXTURE_GEN_STR); + #else + glDisable(GL_TEXTURE_GEN_R); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + #endif + } +#endif + + GLSetupTexturing(false); + GLSetupLighting(false); + GLSetupFog(false); + +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + { + defaultShader.setPerVertexColor(false); + defaultShader.setMaterial(null, 0); + } +#endif + +#if ENABLE_GL_FFP + if(!glCaps_shaders) + glShadeModel(GL_FLAT); +#endif + glEnable(GL_BLEND); +#if !defined(__EMSCRIPTEN__) + glDisable(GL_MULTISAMPLE); +#endif + } + } + + void ApplyMaterial(Display display, Material material, Mesh mesh) + { + Shader shader = material.shader ? material.shader : defaultShader; + MaterialFlags flags = material.flags; +#if ENABLE_GL_FFP + static int lastSeparate = 0; + int tmu = 0; + bool normalMapped = false; + OGLMesh oglMesh = mesh ? mesh.data : null; +#endif + +#if ENABLE_GL_SHADERS + if(glCaps_shaders && shader) + shader.select(); +#endif + + // Basic Properties + if(flags.doubleSided) + { +#if ENABLE_GL_FFP + if(!glCaps_shaders) + GLLightModeli(GL_LIGHT_MODEL_TWO_SIDE, !flags.singleSideLight); +#endif + glDisable(GL_CULL_FACE); + } + else + { +#if ENABLE_GL_FFP + if(!glCaps_shaders) + GLLightModeli(GL_LIGHT_MODEL_TWO_SIDE, bool::false); +#endif + glEnable(GL_CULL_FACE); + } + + // Fog + GLSetupFog(!flags.noFog); + +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + activeShader.setMaterial(material, mesh.flags); +#endif + +#if ENABLE_GL_FFP + if(!glCaps_shaders) + { + if(material.bumpMap && mesh.lightVectors) + { + float color[4] = { 1,1,1,1 }; + glActiveTexture(GL_TEXTURE0 + tmu); + glClientActiveTexture(GL_TEXTURE0 + tmu++); + glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)material.bumpMap.driverData); + glDisable(GL_TEXTURE_CUBE_MAP); + glEnable(GL_TEXTURE_2D); + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_DOT3_RGB); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PRIMARY_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + + if(0) //((DefaultShaderBits)defaultShader.state).debugging) + { + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PRIMARY_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color ); + } + + #if _GLES + glDisable(GL_TEXTURE_GEN_STR); + #else + glDisable(GL_TEXTURE_GEN_R); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + #endif + glDisable(GL_LIGHTING); + lightingEnabled = false; + + GLMatrixMode(GL_TEXTURE); + GLLoadIdentity(); + if(material.uScale && material.vScale) + GLScalef(material.uScale, material.vScale, 1); + GLMatrixMode(MatrixMode::modelView); + + if(flags.tile) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } + else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + + glActiveTexture(GL_TEXTURE0 + tmu); + glClientActiveTexture(GL_TEXTURE0 + tmu); + + normalMapped = true; + + // Modulate base color + if(material.diffuse.r < 1 || material.diffuse.g < 1 || material.diffuse.b < 1) + { + tmu++; + glDisable(GL_TEXTURE_CUBE_MAP); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)material.bumpMap.driverData); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); + + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); + + color[0] = material.diffuse.r, color[1] = material.diffuse.g, color[2] = material.diffuse.b, color[3] = 1.0; + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color ); + glActiveTexture(GL_TEXTURE0 + tmu); + glClientActiveTexture(GL_TEXTURE0 + tmu); + } + + // Add ambient light + { + ColorRGB ambient { material.ambient.r * 0.2f, material.ambient.g * 0.2f, material.ambient.g * 0.2f }; + if(ambient.r > 0 || ambient.g > 0 || ambient.b > 0) + { + tmu++; + glDisable(GL_TEXTURE_CUBE_MAP); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)material.bumpMap.driverData); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); + + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); + + color[0] = ambient.r, color[1] = ambient.g, color[2] = ambient.b, color[3] = 1.0; + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color ); + glActiveTexture(GL_TEXTURE0 + tmu); + glClientActiveTexture(GL_TEXTURE0 + tmu); + } + } + } + else + { + GLDisableClientState(LIGHTVECTORS); + if(!lightingEnabled) + { + glEnable(GL_LIGHTING); + lightingEnabled = true; + } + } + } +#endif + // Maps + if(flags.cubeMap || (material.baseMap && (mesh.texCoords || mesh.flags.texCoords1))) + { + Bitmap map = material.baseMap; + int diffuseTarget = flags.cubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; + +#if ENABLE_GL_FFP + if(!glCaps_shaders) + { + glActiveTexture(GL_TEXTURE0 + tmu); + glClientActiveTexture(GL_TEXTURE0 + tmu++); + glEnable(diffuseTarget); + glDisable(flags.cubeMap ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP); + } +#endif + +#if ENABLE_GL_SHADERS + if(glCaps_shaders && !flags.cubeMap) + GLSetupTexturing(true); +#endif + + glBindTexture(diffuseTarget, (GLuint)(uintptr)map.driverData); + +#if ENABLE_GL_FFP + if(!glCaps_shaders) + { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + /* // This did not have the desired effect with a GL_ALPHA texture + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); + */ + + if(flags.cubeMap) + { + #if _GLES + glEnable(GL_TEXTURE_GEN_STR); + // GL_OBJECT_LINEAR: No extension support? + // glTexGeni(GL_TEXTURE_GEN_STR_OES, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + #else + GLfloat xPlane[] = { 1.0f, 0.0f, 0.0f, 0 }; + GLfloat yPlane[] = { 0.0f,-1.0f, 0.0f, 0 }; + GLfloat zPlane[] = { 0.0f, 0.0f,-1.0f, 0 }; + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGenfv(GL_R, GL_OBJECT_PLANE, zPlane); + glTexGenfv(GL_S, GL_OBJECT_PLANE, xPlane); + glTexGenfv(GL_T, GL_OBJECT_PLANE, yPlane); + + glEnable(GL_TEXTURE_GEN_R); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + #endif + + GLDisableClientState(TEXCOORDS); + } + else + { + #if _GLES + glDisable(GL_TEXTURE_GEN_STR); + #else + glDisable(GL_TEXTURE_GEN_R); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + #endif + + if(tmu > 1) + oglMesh.texCoords.use(texCoord, 2, GL_FLOAT, 0, oglMesh.texCoords.buffer ? null : mesh.texCoords); + GLEnableClientState(TEXCOORDS); + } + glClientActiveTexture(GL_TEXTURE0); + } +#endif + if(flags.tile) + { + glTexParameteri(diffuseTarget, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(diffuseTarget, GL_TEXTURE_WRAP_T, GL_REPEAT); + } + else + { + glTexParameteri(diffuseTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(diffuseTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + } + else + { + GLSetupTexturing(false); + } + +#if ENABLE_GL_FFP && !defined(_GLES) + if(!glCaps_shaders) + { + int separate = material.flags.separateSpecular ? GL_SEPARATE_SPECULAR_COLOR : GL_SINGLE_COLOR; + if(separate != lastSeparate) + { + GLLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, separate); + lastSeparate = separate; + } + } +#endif - // *** Projection Matrix *** - if(!display.display3D.camera) - glPushMatrix(); - else - glMatrixMode(GL_PROJECTION); - if(display.display3D.collectingHits) + if((flags.cubeMap && material.baseMap) || + (mesh.texCoords && (material.baseMap || material.bumpMap || material.specularMap || material.reflectMap))) + { +#if ENABLE_GL_FFP + if(!glCaps_shaders) { - float pickX = display.display3D.pickX + surface.offset.x; - float pickY = display.height - (display.display3D.pickY + surface.offset.y) - 1; - Matrix pickMatrix - { - { - w / display.display3D.pickWidth, 0, 0, 0, - 0, h / display.display3D.pickHeight, 0, 0, - 0, 0, 1, 0, - (w + 2.0f * (x - pickX)) / display.display3D.pickWidth, - (h + 2.0f * (y - pickY)) / display.display3D.pickHeight, 0, 1 - } - }; - glLoadMatrixd(pickMatrix.array); + glActiveTexture(GL_TEXTURE0 + tmu - 1); + glClientActiveTexture(GL_TEXTURE0 + tmu - 1); } - else - glLoadIdentity(); - glFrustum( - (left - origX) * camera.zMin / camera.focalX, - (right - origX) * camera.zMin / camera.focalX, - (bottom - origY) * camera.zMin / camera.focalY, - (top - origY) * camera.zMin / camera.focalY, - camera.zMin, camera.zMax); +#endif + GLMatrixMode(GL_TEXTURE); + GLLoadIdentity(); + if(material.uScale && material.vScale) + GLScalef(material.uScale, material.vScale, 1); + GLMatrixMode(MatrixMode::modelView); +#if ENABLE_GL_FFP + if(!glCaps_shaders) + { + glActiveTexture(GL_TEXTURE0); + glClientActiveTexture(GL_TEXTURE0); + } +#endif + } - glDisable(GL_BLEND); +#if ENABLE_GL_FFP + if(!glCaps_shaders) + { + if(material.envMap && material.refractiveIndex) + { + float color[4] = { material.opacity, material.opacity, material.opacity, 1.0 }; + glActiveTexture(GL_TEXTURE0 + tmu); + glClientActiveTexture(GL_TEXTURE0 + tmu++); + glBindTexture(GL_TEXTURE_CUBE_MAP, (GLuint)(uintptr)material.envMap.driverData); + glEnable(GL_TEXTURE_CUBE_MAP); + #if _GLES + glEnable(GL_TEXTURE_GEN_STR); + glTexGeni(GL_TEXTURE_GEN_STR_OES, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + #else + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glEnable(GL_TEXTURE_GEN_R); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + #endif + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + + if(normalMapped) + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); + else + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); - // *** Z Inverted Identity Matrix *** - glMatrixMode(GL_MODELVIEW); - if(!display.display3D.camera) - glPushMatrix(); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); - glLoadIdentity(); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE); - glScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); - // *** View Matrix *** - glMultMatrixd(camera.viewMatrix.array); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); - // *** Lights *** - // ... + if(!normalMapped) + { + glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_ALPHA, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA); + } - glEnable(GL_DEPTH_TEST); - glEnable(GL_LIGHTING); - glShadeModel(GL_SMOOTH); - glDepthMask((byte)bool::true); - oglDisplay.depthWrite = true; + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color ); - glEnable(GL_MULTISAMPLE_ARB); - } - else if(display.display3D.camera) - { - oglDisplay.depthWrite = false; - glViewport(0,0,display.width,display.height); + GLMatrixMode(MatrixMode::texture); + { + double * s = display.display3D.camera.viewMatrix.array; + double k = 2.0; + Matrix m + { { + k*s[0],-k*s[4],-k*s[8], 0, + k*s[1],-k*s[5],-k*s[9], 0, + k*s[2],-k*s[6],-k*s[10],0, + 0,0,0,1 + } }; + GLLoadMatrixd(m.array); + } + GLMatrixMode(MatrixMode::modelView); + } - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glDisable(GL_FOG); - glDisable(GL_TEXTURE_2D); - glShadeModel(GL_FLAT); - glEnable(GL_BLEND); - glDisable(GL_MULTISAMPLE_ARB); + if(material.envMap && material.reflectivity) + { + float color[4] = { 1.0f - material.reflectivity, 1.0f - material.reflectivity, 1.0f - material.reflectivity, 1.0 }; + glActiveTexture(GL_TEXTURE0 + tmu); + glClientActiveTexture(GL_TEXTURE0 + tmu++); + glBindTexture(GL_TEXTURE_CUBE_MAP, (GLuint)(uintptr)material.envMap.driverData); + glEnable(GL_TEXTURE_CUBE_MAP); + #if _GLES + glEnable(GL_TEXTURE_GEN_STR); + glTexGeni(GL_TEXTURE_GEN_STR_OES, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + #else + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glEnable(GL_TEXTURE_GEN_R); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + #endif + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + + if(normalMapped) + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); + else + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); - // *** Restore 2D MODELVIEW Matrix *** - glPopMatrix(); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS); - // *** Restore 2D PROJECTION Matrix *** - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - } + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); - GLBindBuffer(GL_ARRAY_BUFFER_ARB, 0); - } + if(!normalMapped) + { + glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_ALPHA, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA); + } - void ApplyMaterial(Display display, Material material, Mesh mesh) - { - //Logf("ApplyMaterial\n"); + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color ); - // Basic Properties - if(material.flags.doubleSided) - { - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, !material.flags.singleSideLight); - glDisable(GL_CULL_FACE); - } - else - { - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, bool::false); - glEnable(GL_CULL_FACE); + GLMatrixMode(MatrixMode::texture); + { + double * s = display.display3D.camera.inverseTranspose.array; + Matrix m + { { + s[0],s[1],-s[2],0, + s[4],-s[5],-s[6],0, + -s[8],s[9],s[10],0, + 0,0,0,1 + } }; + GLLoadMatrixd(m.array); + } + GLMatrixMode(MatrixMode::modelView); + } } +#endif - // Fog - if(material.flags.noFog) - glDisable(GL_FOG); - else - glEnable(GL_FOG); - - // Maps - if(material.baseMap && mesh.texCoords) +#if ENABLE_GL_FFP + if(!glCaps_shaders) { - Bitmap map = material.baseMap; - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, (GLuint)(uintptr)map.driverData); + disableRemainingTMUs(display, tmu); - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - if(material.uScale && material.vScale) - glScalef(material.uScale, material.vScale, 1); - glMatrixMode(GL_MODELVIEW); - - if(material.flags.tile) + if(mesh.flags.colors) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + GLColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glDisable(GL_COLOR_MATERIAL); + { + float color[4] = { material.diffuse.r, material.diffuse.g, material.diffuse.b, material.opacity }; + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color); + } + { + float color[4] = { material.ambient.r, material.ambient.g, material.ambient.b, 0 }; + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color); + } + } + if(material.power > 0.1) + { + float color[4] = { material.specular.r, material.specular.g, material.specular.b, 0 }; + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color); } - } - else - glDisable(GL_TEXTURE_2D); - - if(mesh.flags.colors) - { - glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - glEnable(GL_COLOR_MATERIAL); - } - else - { - glDisable(GL_COLOR_MATERIAL); + else { - float color[4] = { material.diffuse.r, material.diffuse.g, material.diffuse.b, material.opacity }; - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color); + float color[4] = { 0,0,0,0 }; + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color); } { - float color[4] = { material.ambient.r, material.ambient.g, material.ambient.b, 0 }; - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, color); + float color[4] = { material.emissive.r, material.emissive.g, material.emissive.b, 0 }; + glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color); } + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &material.power); } - { - float color[4] = { material.specular.r, material.specular.g, material.specular.b, 0 }; - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color); - } - { - float color[4] = { material.emissive.r, material.emissive.g, material.emissive.b, 0 }; - glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, color); - } - - glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &material.power); +#endif } void FreeMesh(DisplaySystem displaySystem, Mesh mesh) @@ -3559,61 +3723,55 @@ class OpenGLDisplayDriver : DisplayDriver OGLMesh oglMesh = mesh.data; if(oglMesh) { + OGLSystem oglSystem = displaySystem.driverData; + GLCapabilities caps = glCaps; + SETCAPS(oglSystem.capabilities); + if(!mesh.flags.vertices) { - if(oglMesh.vertices) - { - GLDeleteBuffers(1, &oglMesh.vertices); - oglMesh.vertices = 0; - } + oglMesh.vertices.free(); delete mesh.vertices; } if(!mesh.flags.normals) { - if(oglMesh.normals) - { - GLDeleteBuffers(1, &oglMesh.normals); - oglMesh.normals = 0; - } + oglMesh.normals.free(); delete mesh.normals; } + if(!mesh.flags.tangents) + { + oglMesh.tangents.free(); + delete mesh.tangents; + } + if(!mesh.flags.lightVectors) + { + oglMesh.lightVectors.free(); + delete mesh.lightVectors; + } if(!mesh.flags.texCoords1) { - if(oglMesh.texCoords) - { - GLDeleteBuffers(1, &oglMesh.texCoords); - oglMesh.texCoords = 0; - } + oglMesh.texCoords.free(); delete mesh.texCoords; } if(!mesh.flags.texCoords2) { - if(oglMesh.texCoords2) - { - GLDeleteBuffers(1, &oglMesh.texCoords2); - oglMesh.texCoords2 = 0; - } - /* - delete mesh.texCoords2; - */ + oglMesh.texCoords2.free(); + // delete mesh.texCoords2; } if(!mesh.flags.colors) { - if(oglMesh.colors) - { - GLDeleteBuffers(1, &oglMesh.colors); - oglMesh.colors = 0; - } + oglMesh.colors.free(); + delete mesh.colors; } if(!mesh.flags) { delete oglMesh; mesh.data = null; } + SETCAPS(caps); } } - bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh) + bool AllocateMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags, int nVertices) { bool result = false; @@ -3621,27 +3779,85 @@ class OpenGLDisplayDriver : DisplayDriver mesh.data = OGLMesh { }; if(mesh.data) { - OGLMesh oglMesh = mesh.data; - - if(mesh.flags.vertices && !oglMesh.vertices && !mesh.vertices) - { - mesh.vertices = mesh.flags.doubleVertices ? (Vector3Df *)new Vector3D[mesh.nVertices] : new Vector3Df[mesh.nVertices]; - GLGenBuffers(1, &oglMesh.vertices); - } - if(mesh.flags.normals && !oglMesh.normals && !mesh.normals) + if(mesh.nVertices == nVertices) { - GLGenBuffers( 1, &oglMesh.normals); - mesh.normals = mesh.flags.doubleNormals ? (Vector3Df *)new Vector3D[mesh.nVertices] : new Vector3Df[mesh.nVertices]; - } - if(mesh.flags.texCoords1 && !oglMesh.texCoords && !mesh.texCoords) - { - GLGenBuffers( 1, &oglMesh.texCoords); - mesh.texCoords = new Pointf[mesh.nVertices]; + // Same number of vertices, adding features (Leaves the other features pointers alone) + if(mesh.flags != flags) + { + if(!mesh.flags.vertices && flags.vertices) + { + if(flags.doubleVertices) + { + mesh.vertices = (Vector3Df *)new Vector3D[nVertices]; + } + else + mesh.vertices = new Vector3Df[nVertices]; + } + if(!mesh.flags.normals && flags.normals) + { + if(flags.doubleNormals) + { + mesh.normals = (Vector3Df *)new Vector3D[nVertices]; + } + else + mesh.normals = new Vector3Df[nVertices]; + } + if(!mesh.flags.tangents && flags.tangents) + { + mesh.tangents = new Vector3Df[2*nVertices]; + } + if(!mesh.flags.lightVectors && flags.lightVectors) + { + mesh.lightVectors = new ColorRGB[nVertices]; + } + if(!mesh.flags.texCoords1 && flags.texCoords1) + { + mesh.texCoords = new Pointf[nVertices]; + } + if(!mesh.flags.colors && flags.colors) + { + mesh.colors = new ColorRGBAf[nVertices]; + } + } } - if(mesh.flags.colors && !oglMesh.colors && !mesh.colors) + else { - GLGenBuffers( 1, &oglMesh.colors); - mesh.colors = new ColorRGBAf[mesh.nVertices]; + // New number of vertices, reallocate all current and new features + flags |= mesh.flags; + if(flags.vertices) + { + if(flags.doubleVertices) + { + mesh.vertices = (Vector3Df *)renew mesh.vertices Vector3D[nVertices]; + } + else + mesh.vertices = renew mesh.vertices Vector3Df[nVertices]; + } + if(flags.normals) + { + if(flags.doubleNormals) + { + mesh.normals = (Vector3Df *)renew mesh.normals Vector3D[nVertices]; + } + else + mesh.normals = renew mesh.normals Vector3Df[nVertices]; + } + if(flags.texCoords1) + { + mesh.texCoords = renew mesh.texCoords Pointf[nVertices]; + } + if(flags.colors) + { + mesh.colors = renew mesh.colors ColorRGBAf[nVertices]; + } + if(flags.tangents) + { + mesh.tangents = renew mesh.tangents Vector3Df[2 * nVertices]; + } + if(flags.lightVectors) + { + mesh.lightVectors = renew mesh.lightVectors ColorRGB[nVertices]; + } } result = true; } @@ -3650,55 +3866,59 @@ class OpenGLDisplayDriver : DisplayDriver void UnlockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags) { - OGLMesh oglMesh = mesh.data; - if(!flags) flags = mesh.flags; + OGLSystem oglSystem = displaySystem.driverData; + GLCapabilities caps = glCaps; + SETCAPS(oglSystem.capabilities); - if(vboAvailable) + if(glCaps_vertexBuffer) { - if(!(flags.vertices) || oglMesh.vertices) - { - GLBindBuffer(GL_ARRAY_BUFFER_ARB, oglMesh.vertices); - GLBufferData( mesh.flags.doubleVertices ? GL_DOUBLE : GL_FLOAT, GL_ARRAY_BUFFER_ARB, mesh.nVertices * (mesh.flags.doubleVertices ? sizeof(Vector3D) : sizeof(Vector3Df)), mesh.vertices, GL_STATIC_DRAW_ARB ); - } + OGLMesh oglMesh = mesh.data; + if(!flags) flags = mesh.flags; + if(flags.vertices) + oglMesh.vertices.allocate( + mesh.nVertices * (mesh.flags.doubleVertices ? sizeof(Vector3D) : sizeof(Vector3Df)), mesh.vertices, staticDraw); - if(!(flags.normals) || oglMesh.normals) - { - GLBindBuffer(GL_ARRAY_BUFFER_ARB, oglMesh.normals); - GLBufferData( mesh.flags.doubleNormals ? GL_DOUBLE : GL_FLOAT, GL_ARRAY_BUFFER_ARB, mesh.nVertices * (mesh.flags.doubleNormals ? sizeof(Vector3D) : sizeof(Vector3Df)), mesh.normals, GL_STATIC_DRAW_ARB ); - } + if(flags.normals) + oglMesh.normals.allocate( + mesh.nVertices * (mesh.flags.doubleNormals ? sizeof(Vector3D) : sizeof(Vector3Df)), mesh.normals, staticDraw); - if(!(flags.texCoords1) || oglMesh.texCoords) - { - GLBindBuffer(GL_ARRAY_BUFFER_ARB, oglMesh.texCoords); - GLBufferData( GL_FLOAT, GL_ARRAY_BUFFER_ARB, mesh.nVertices * sizeof(Pointf), mesh.texCoords, GL_STATIC_DRAW_ARB ); - } + if(flags.texCoords1) + oglMesh.texCoords.allocate( + mesh.nVertices * sizeof(Pointf), mesh.texCoords, staticDraw); - if(!(flags.colors) || oglMesh.colors) - { - GLBindBuffer( GL_ARRAY_BUFFER_ARB, oglMesh.colors); - GLBufferData( GL_FLOAT, GL_ARRAY_BUFFER_ARB, mesh.nVertices * sizeof(ColorRGBAf), mesh.colors, GL_STATIC_DRAW_ARB ); - } + if(flags.colors) + oglMesh.colors.allocate( + mesh.nVertices * sizeof(ColorRGBAf), mesh.colors, staticDraw); - GLBindBuffer( GL_ARRAY_BUFFER_ARB, 0); + if(flags.tangents) + oglMesh.tangents.allocate(mesh.nVertices * 2*sizeof(Vector3Df), mesh.tangents, staticDraw); + + if(flags.lightVectors) + oglMesh.lightVectors.allocate(mesh.nVertices * sizeof(ColorRGB), mesh.lightVectors, staticDraw); } + SETCAPS(caps); } bool LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags) { bool result = true; - return result; + return result; } void FreeIndices(DisplaySystem displaySystem, OGLIndices oglIndices) { + OGLSystem oglSystem = displaySystem.driverData; + GLCapabilities caps = glCaps; + SETCAPS(oglSystem.capabilities); + if(oglIndices) { - if(oglIndices.buffer) - GLDeleteBuffers(1, &oglIndices.buffer); + oglIndices.buffer.free(); delete oglIndices.indices; delete oglIndices; } + SETCAPS(caps); } void * AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit) @@ -3707,7 +3927,6 @@ class OpenGLDisplayDriver : DisplayDriver if(oglIndices) { oglIndices.indices = (void *)(indices32bit ? new uint32[nIndices] : new uint16[nIndices]); - GLGenBuffers( 1, &oglIndices.buffer); oglIndices.nIndices = nIndices; } return oglIndices; @@ -3715,13 +3934,41 @@ class OpenGLDisplayDriver : DisplayDriver void UnlockIndices(DisplaySystem displaySystem, OGLIndices oglIndices, bool indices32bit, int nIndices) { - if(vboAvailable) + OGLSystem oglSystem = displaySystem.driverData; + GLCapabilities caps = glCaps; + SETCAPS(oglSystem.capabilities); + + if(glCaps_vertexBuffer) { - GLBindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB, oglIndices.buffer); - GLBufferData( indices32bit ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, GL_ELEMENT_ARRAY_BUFFER_ARB, nIndices * (indices32bit ? sizeof(uint32) : sizeof(uint16)), - oglIndices.indices, GL_STATIC_DRAW_ARB); - GLBindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + if(!glCaps_intAndDouble && indices32bit) + { + if(!oglIndices.buffer.buffer) + glGenBuffers(1, &oglIndices.buffer.buffer); + if(glabCurElementBuffer != oglIndices.buffer.buffer) + GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, oglIndices.buffer.buffer); + + { + uint * pointer = (uint *)oglIndices.indices; + int i; + uint16 * b; + if(nIndices > oglSystem.shortBDSize) + { + oglSystem.shortBDSize = nIndices; + oglSystem.shortBDBuffer = renew oglSystem.shortBDBuffer uint16[oglSystem.shortBDSize]; + } + b = oglSystem.shortBDBuffer; + for(i = 0; i < nIndices; i++) + b[i] = (uint16)pointer[i]; + + glBufferData(GL_ELEMENT_ARRAY_BUFFER, nIndices * sizeof(uint16), b, GL_STATIC_DRAW); + } + } + else + oglIndices.buffer.allocate( + nIndices * (indices32bit ? sizeof(uint32) : sizeof(uint16)), + oglIndices.indices, staticDraw); } + SETCAPS(caps); } uint16 * LockIndices(DisplaySystem displaySystem, OGLIndices oglIndices) @@ -3732,13 +3979,11 @@ class OpenGLDisplayDriver : DisplayDriver void SelectMesh(Display display, Mesh mesh) { - //Logf("SelectMesh\n"); - -#if !defined( __ANDROID__) && !defined(__APPLE__) +#if !defined( __ANDROID__) && !defined(__APPLE__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__) #if defined(__WIN32__) if(glUnlockArraysEXT) #endif - if(display.display3D.mesh) + if(!glCaps_vertexBuffer && display.display3D.mesh) glUnlockArraysEXT(); #endif if(mesh) @@ -3746,140 +3991,177 @@ class OpenGLDisplayDriver : DisplayDriver OGLMesh oglMesh = mesh.data; // *** Vertex Stream *** - glEnableClientState(GL_VERTEX_ARRAY); + GLEnableClientState(VERTICES); if(!display.display3D.collectingHits && oglMesh) { - GLBindBuffer(GL_ARRAY_BUFFER_ARB, oglMesh.vertices ); - glVertexPointer(3, mesh.flags.doubleVertices ? GL_DOUBLE : GL_FLOAT, 0, vboAvailable ? null : mesh.vertices); + oglMesh.vertices.use(vertex, 3, (mesh.flags.doubleVertices ? GL_DOUBLE : GL_FLOAT), 0, oglMesh.vertices.buffer ? null : (double *)mesh.vertices); // *** Normals Stream *** - if(mesh.normals) + if(mesh.normals || mesh.flags.normals) { - glEnableClientState(GL_NORMAL_ARRAY); - GLBindBuffer(GL_ARRAY_BUFFER_ARB, oglMesh.normals); - glNormalPointer(mesh.flags.doubleNormals ? GL_DOUBLE : GL_FLOAT, 0, vboAvailable ? null : mesh.normals); + GLEnableClientState(NORMALS); + oglMesh.normals.use(normal, 3, GL_FLOAT, 0, oglMesh.normals.buffer ? null : mesh.normals); } else - glDisableClientState(GL_NORMAL_ARRAY); + GLDisableClientState(NORMALS); + +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + { + // *** Tangents Stream *** + if(mesh.tangents || mesh.flags.tangents) + { + GLEnableClientState(TANGENTS1); + GLEnableClientState(TANGENTS2); + oglMesh.tangents.use(tangent1, 3, GL_FLOAT, sizeof(Vector3Df)*2, oglMesh.tangents.buffer ? null : mesh.tangents); + oglMesh.tangents.use(tangent2, 3, GL_FLOAT, sizeof(Vector3Df)*2, oglMesh.tangents.buffer ? (void *)sizeof(Vector3Df) : mesh.tangents+1); + } + else + { + GLDisableClientState(TANGENTS1); + GLDisableClientState(TANGENTS2); + } + } +#endif // *** Texture Coordinates Stream *** - if(mesh.texCoords) + if(mesh.texCoords || mesh.flags.texCoords1) { - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - GLBindBuffer( GL_ARRAY_BUFFER_ARB, oglMesh.texCoords); - glTexCoordPointer(2, GL_FLOAT, 0, vboAvailable ? null : mesh.texCoords); + GLEnableClientState(TEXCOORDS); + oglMesh.texCoords.use(texCoord, 2, GL_FLOAT, 0, oglMesh.texCoords.buffer ? null : mesh.texCoords); } else - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + GLDisableClientState(TEXCOORDS); +#if ENABLE_GL_FFP + if(!glCaps_shaders) + { + // *** Normal Map Aligned Light Vector *** + if(mesh.lightVectors || mesh.flags.lightVectors) + { + GLEnableClientState(LIGHTVECTORS); + oglMesh.lightVectors.use(lightVector, 3, GL_FLOAT, 0, oglMesh.lightVectors.buffer ? null : mesh.lightVectors); + } + else + GLDisableClientState(LIGHTVECTORS); + } + else +#endif // *** Color Stream *** - if(mesh.colors) + if(mesh.colors || mesh.flags.colors) { - glEnableClientState(GL_COLOR_ARRAY); - GLBindBuffer( GL_ARRAY_BUFFER_ARB, oglMesh.colors); - glColorPointer(4, GL_FLOAT, 0, vboAvailable ? null : mesh.colors); + GLEnableClientState(COLORS); + oglMesh.colors.use(color, 4, GL_FLOAT, 0, oglMesh.colors.buffer ? null : mesh.colors); } else - glDisableClientState(GL_COLOR_ARRAY); - + GLDisableClientState(COLORS); } else { - GLBindBuffer( GL_ARRAY_BUFFER_ARB, 0); - glVertexPointer(3,mesh.flags.doubleVertices ? GL_DOUBLE : GL_FLOAT,0,mesh.vertices); - if(mesh.normals && !display.display3D.collectingHits) + noAB.use(vertex, 3, (mesh.flags.doubleVertices ? GL_DOUBLE : GL_FLOAT), 0, (double *)mesh.vertices); + if((mesh.normals || mesh.flags.normals) && !display.display3D.collectingHits) + { + GLEnableClientState(NORMALS); + noAB.use(normal, 3, GL_FLOAT, 0, mesh.normals); + } + else + GLDisableClientState(NORMALS); +#if ENABLE_GL_SHADERS + if(glCaps_shaders) + { + if((mesh.tangents || mesh.flags.tangents) && !display.display3D.collectingHits) + { + GLEnableClientState(TANGENTS1); + GLEnableClientState(TANGENTS2); + noAB.use(tangent1, 3, GL_FLOAT, sizeof(Vector3Df)*2, mesh.tangents); + noAB.use(tangent2, 3, GL_FLOAT, sizeof(Vector3Df)*2, mesh.tangents+1); + } + else + { + GLDisableClientState(TANGENTS1); + GLDisableClientState(TANGENTS2); + } + } +#endif + + if((mesh.texCoords || mesh.flags.texCoords1) && !display.display3D.collectingHits) { - glEnableClientState(GL_NORMAL_ARRAY); - glNormalPointer(mesh.flags.doubleNormals ? GL_DOUBLE : GL_FLOAT, 0, mesh.normals); + GLEnableClientState(TEXCOORDS); + noAB.use(texCoord, 2, GL_FLOAT, 0, mesh.texCoords); } else - glDisableClientState(GL_NORMAL_ARRAY); - if(mesh.texCoords && !display.display3D.collectingHits) + GLDisableClientState(TEXCOORDS); + +#if ENABLE_GL_FFP + if(!glCaps_shaders) { - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 0, mesh.texCoords); + if((mesh.lightVectors || mesh.flags.lightVectors) && !display.display3D.collectingHits) + { + GLEnableClientState(LIGHTVECTORS); + noAB.use(lightVector, 3, GL_FLOAT, sizeof(ColorRGB), mesh.lightVectors); + } + else + GLDisableClientState(LIGHTVECTORS); } else - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - if(mesh.colors && !display.display3D.collectingHits) +#endif + if((mesh.colors || mesh.flags.colors) && !display.display3D.collectingHits) { - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(4, GL_FLOAT, 0, mesh.colors); + GLEnableClientState(COLORS); + noAB.use(color, 4, GL_FLOAT, 0, mesh.colors); } else - glDisableClientState(GL_COLOR_ARRAY); + GLDisableClientState(COLORS); } -#if !defined(__ANDROID__) && !defined(__APPLE__) +#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__ODROID__) && !defined(__EMSCRIPTEN__) #if defined(__WIN32__) if(glLockArraysEXT) #endif - glLockArraysEXT(0, mesh.nVertices); + if(!glCaps_vertexBuffer) + glLockArraysEXT(0, mesh.nVertices); #endif } - else - GLBindBuffer(GL_ARRAY_BUFFER_ARB, 0); } void DrawPrimitives(Display display, PrimitiveSingle * primitive, Mesh mesh) { - //Logf("DrawPrimitives\n"); - if(primitive->type.vertexRange) - glDrawArrays(primitiveTypes[primitive->type.primitiveType], primitive->first, primitive->nVertices); + { + GLFlushMatrices(); + glDrawArrays(getPrimitiveType(primitive->type.primitiveType), primitive->first, primitive->nVertices); + } else { - // *** Hoping the data won't be uploaded at all (Won't really work if another group of the mesh is using the mesh ) *** - // HACK TO SPEED THINGS UP... -#ifndef __ANDROID__ - GLBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); - if(primitive->nIndices < (mesh.nVertices >> 2) && !primitive->type.indices32bit) + OGLIndices oglIndices = primitive->data; + GLEAB eab = ((!display.display3D.collectingHits && oglIndices && glCaps_vertexBuffer) ? oglIndices.buffer : noEAB); + if(!glCaps_intAndDouble && !glCaps_vertexBuffer && primitive->type.indices32bit) { - int c; - glBegin(primitiveTypes[primitive->type.primitiveType]); - if(primitive->data) - { - OGLIndices oglIndices = primitive->data; - MeshFeatures flags = mesh.flags; - for(c = 0; cnIndices; c++) - { - uint16 index = ((uint16 *) oglIndices.indices)[c]; - if(flags.normals) glNormal3fv((float *)&mesh.normals[index]); - if(flags.texCoords1) glTexCoord2fv((float *)&mesh.texCoords[index]); - if(flags.colors) glColor4fv((float *)&mesh.colors[index]); - glVertex3fv((float *)&mesh.vertices[index]); - } - } - glEnd(); + uint16 * temp = new uint16[primitive->nIndices]; + uint32 * src = (uint32 *)(oglIndices ? oglIndices.indices : primitive->indices); + int i; + for(i = 0; i < primitive->nIndices; i++) + temp[i] = (uint16)src[i]; + eab.draw(getPrimitiveType(primitive->type.primitiveType), primitive->nIndices, GL_UNSIGNED_SHORT, temp); + delete temp; } else -#endif - { - OGLIndices oglIndices = primitive->data; - - if(!display.display3D.collectingHits && vboAvailable && oglIndices) - { - GLBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, oglIndices.buffer); - glDrawElements(primitiveTypes[primitive->type.primitiveType], primitive->nIndices, - primitive->type.indices32bit ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0); - GLBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); - } - else - glDrawElements(primitiveTypes[primitive->type.primitiveType], primitive->nIndices, - primitive->type.indices32bit ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, oglIndices ? oglIndices.indices : primitive->indices); - } + eab.draw(getPrimitiveType(primitive->type.primitiveType), primitive->nIndices, + primitive->type.indices32bit ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, + eab.buffer ? 0 : (oglIndices ? oglIndices.indices : primitive->indices)); + GLABBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } } void PushMatrix(Display display) { - glPushMatrix(); + GLPushMatrix(); } void PopMatrix(Display display, bool setMatrix) { - glPopMatrix(); + GLPopMatrix(); } void SetTransform(Display display, Matrix transMatrix, bool viewSpace, bool useCamera) @@ -3889,18 +4171,18 @@ class OpenGLDisplayDriver : DisplayDriver if(viewSpace) { - glLoadIdentity(); - glScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane); + GLLoadIdentity(); + GLScaled(1.0/nearPlane, 1.0/nearPlane, -1.0/nearPlane); } else if(camera) { - glTranslated( + GLTranslated( matrix.m[3][0] - camera.cPosition.x, matrix.m[3][1] - camera.cPosition.y, matrix.m[3][2] - camera.cPosition.z); } else - glTranslated( + GLTranslated( matrix.m[3][0], matrix.m[3][1], matrix.m[3][2]); @@ -3909,7 +4191,7 @@ class OpenGLDisplayDriver : DisplayDriver matrix.m[3][1] = 0; matrix.m[3][2] = 0; - glMultMatrixd(matrix.array); + GLMultMatrixd(matrix.array); } #endif } @@ -3930,11 +4212,14 @@ IS_GLGetContext(DisplaySystem displaySystem) #if defined(__WIN32__) OGLSystem system = displaySystem.driverData; return system.glrc; -#elif !defined(__ANDROID__) +#elif defined(__ANDROID__) || defined(__ODROID__) + return eglContext; +#elif defined(__EMSCRIPTEN__) OGLSystem system = displaySystem.driverData; - return system.glContext; + return (void *)system.glc; #else - return eglContext; + OGLSystem system = displaySystem.driverData; + return system.glContext; #endif } return null;