diff --git a/project/ToolkitBuild.xml b/project/ToolkitBuild.xml index 25e23194d..c515aa26b 100644 --- a/project/ToolkitBuild.xml +++ b/project/ToolkitBuild.xml @@ -4,9 +4,12 @@ + + + @@ -191,6 +194,7 @@ + @@ -484,7 +488,8 @@
- + +
diff --git a/project/include/Hardware.h b/project/include/Hardware.h index 9af77f161..4b009fd96 100644 --- a/project/include/Hardware.h +++ b/project/include/Hardware.h @@ -130,6 +130,7 @@ class HardwareRenderer : public HardwareContext virtual void DestroyShader(unsigned int inShader)=0; virtual void DestroyFramebuffer(unsigned int inBuffer)=0; virtual void DestroyRenderbuffer(unsigned int inBuffer)=0; + virtual void DestroyVertexarray(unsigned int inBuffer)=0; #ifdef NME_S3D virtual void EndS3DRender()=0; diff --git a/project/src/opengl/OGL.h b/project/src/opengl/OGL.h index 675896d4e..6837eae85 100644 --- a/project/src/opengl/OGL.h +++ b/project/src/opengl/OGL.h @@ -8,6 +8,9 @@ #define NME_GLES #define GL_GLEXT_PROTOTYPES +#ifndef NME_NO_GLES3COMPAT + #include +#endif #include #include @@ -15,6 +18,12 @@ #define NME_GLES +#ifndef NME_NO_GLES3COMPAT + #include + #if defined(ANDROID) + #define __gl2_h_ //For Android Platform < 21 + #endif +#endif #include #include @@ -22,11 +31,18 @@ #define NME_GLES +#ifndef NME_NO_GLES3COMPAT + #include +#endif #include #include #elif defined(IPHONE) +#ifndef NME_NO_GLES3COMPAT + #include + #include +#endif #include #include #include diff --git a/project/src/opengl/OGLExport.cpp b/project/src/opengl/OGLExport.cpp index 898670426..d63f5f98c 100644 --- a/project/src/opengl/OGLExport.cpp +++ b/project/src/opengl/OGLExport.cpp @@ -46,6 +46,7 @@ enum ResoType resoProgram, //4 resoFramebuffer, //5 resoRenderbuffer, //6 + resoVertexarray, //7 (GLES3) }; const char *getTypeString(int inType) @@ -59,6 +60,7 @@ const char *getTypeString(int inType) case resoProgram: return "Program"; case resoFramebuffer: return "Framebuffer"; case resoRenderbuffer: return "Renderbuffer"; + case resoVertexarray: return "Vertexarray"; } return "Unknown"; } @@ -306,6 +308,9 @@ class NmeResource : public nme::Object case resoRenderbuffer: ctx->DestroyRenderbuffer(id); break; + case resoVertexarray: + ctx->DestroyVertexarray(id); + break; } } type = resoNone; @@ -638,7 +643,6 @@ value nme_gl_get_parameter(value pname_val) case GL_SAMPLE_BUFFERS: case GL_SAMPLES: case GL_SCISSOR_TEST: - case GL_SHADING_LANGUAGE_VERSION: case GL_STENCIL_BACK_FAIL: case GL_STENCIL_BACK_FUNC: case GL_STENCIL_BACK_PASS_DEPTH_FAIL: @@ -663,6 +667,7 @@ value nme_gl_get_parameter(value pname_val) case GL_VENDOR: case GL_VERSION: + case GL_SHADING_LANGUAGE_VERSION: case GL_RENDERER: strings = 1; break; @@ -794,6 +799,17 @@ GL_GEN_RESO(buffer,glGenBuffers,resoBuffer) GL_GEN_RESO(framebuffer,glGenFramebuffers,resoFramebuffer) GL_GEN_RESO(render_buffer,glGenRenderbuffers,resoRenderbuffer) +//GLES3 +#ifdef NME_NO_GLES3COMPAT +value nme_gl_create_vertexarray(value inType) +{ + DBGFUNC("create vertex array needs NME_GLES3COMPAT"); + return alloc_int(-1); +} +DEFINE_PRIM(nme_gl_create_vertexarray,0); +#else +GL_GEN_RESO(vertexarray,glGenVertexArrays,resoVertexarray) +#endif // --- Stencil ------------------------------------------- @@ -1376,9 +1392,12 @@ value nme_gl_shader_source(value inId,value inSource) const char *lines = source.c_str(); #ifdef NME_GLES // TODO - do something better here - std::string buffer; - buffer = std::string("precision mediump float;\n") + hxToStdString(source); - lines = buffer.c_str(); + if (lines[0]!='#' && lines[1]!='v') + { + std::string buffer; + buffer = std::string("precision mediump float;\n") + hxToStdString(source); + lines = buffer.c_str(); + } #endif glShaderSource(id,1,&lines,0); @@ -1756,9 +1775,27 @@ value nme_gl_get_render_buffer_parameter(value target, value pname) } DEFINE_PRIM(nme_gl_get_render_buffer_parameter,2); -// --- Drawing ------------------------------- + +// --- GLES3: VertexArray + +value nme_gl_bind_vertexarray(value inId ) +{ + DBGFUNC("bindVertexArray"); + int id = getResourceId(inId,resoVertexarray); +#ifndef NME_NO_GLES3COMPAT + glBindVertexArray(id); +#endif + return alloc_null(); +} +DEFINE_PRIM(nme_gl_bind_vertexarray,1); + + + + +// --- Drawing ------------------------------- + value nme_gl_draw_arrays(value inMode, value inFirst, value inCount) { DBGFUNC("drawArrays"); diff --git a/project/src/opengl/OpenGLContext.cpp b/project/src/opengl/OpenGLContext.cpp index fb4b3a699..9afb0ff49 100644 --- a/project/src/opengl/OpenGLContext.cpp +++ b/project/src/opengl/OpenGLContext.cpp @@ -154,6 +154,18 @@ class OGLContext : public HardwareRenderer else glDeleteRenderbuffers(1,&inBuffer); } + void DestroyVertexarray(unsigned int inBuffer) + { + if ( !IsMainThread() ) + { + mHasZombie = true; + mZombieVertexarrays.push_back(inBuffer); + } +#ifndef NME_NO_GLES3COMPAT + else + glDeleteVertexArrays(1,&inBuffer); +#endif + } void OnContextLost() @@ -164,6 +176,7 @@ class OGLContext : public HardwareRenderer mZombieShaders.resize(0); mZombieFramebuffers.resize(0); mZombieRenderbuffers.resize(0); + mZombieVertexarrays.resize(0); mHasZombie = false; } @@ -277,6 +290,14 @@ class OGLContext : public HardwareRenderer glDeleteRenderbuffers(mZombieRenderbuffers.size(),&mZombieRenderbuffers[0]); mZombieRenderbuffers.resize(0); } + + if (mZombieVertexarrays.size()) + { + #ifndef NME_NO_GLES3COMPAT + glDeleteVertexArrays(mZombieVertexarrays.size(),&mZombieVertexarrays[0]); + #endif + mZombieVertexarrays.resize(0); + } } @@ -316,6 +337,7 @@ class OGLContext : public HardwareRenderer mZombieShaders.resize(0); mZombieFramebuffers.resize(0); mZombieRenderbuffers.resize(0); + mZombieVertexarrays.resize(0); ReloadExtentions(); } @@ -771,6 +793,7 @@ class OGLContext : public HardwareRenderer QuickVec mZombieShaders; QuickVec mZombieFramebuffers; QuickVec mZombieRenderbuffers; + QuickVec mZombieVertexarrays; GPUProg *mProg[PROG_COUNT]; diff --git a/project/src/sdl2/SDL2Stage.cpp b/project/src/sdl2/SDL2Stage.cpp index acecdd584..5e6c79b78 100644 --- a/project/src/sdl2/SDL2Stage.cpp +++ b/project/src/sdl2/SDL2Stage.cpp @@ -1550,8 +1550,13 @@ void CreateMainFrame(FrameCreationCallback inOnFrame, int inWidth, int inHeight, #ifdef NME_ANGLE SDL_GL_SetAttribute(SDL_GL_CONTEXT_EGL, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + int major = 3; + #ifdef NME_NO_GLES3COMPAT + major = 2; + #endif + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + DLOG("1 "); #endif if (opengl) @@ -1642,6 +1647,12 @@ void CreateMainFrame(FrameCreationCallback inOnFrame, int inWidth, int inHeight, if (opengl) renderFlags |= SDL_RENDERER_ACCELERATED; if (opengl && vsync) renderFlags |= SDL_RENDERER_PRESENTVSYNC; + #ifdef NME_ANGLE + //needs to be just before SDL_CreateRenderer because SDL_GetWindowFlags resets it + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + #endif + renderer = SDL_CreateRenderer (window, -1, renderFlags); if (opengl) @@ -1653,6 +1664,16 @@ void CreateMainFrame(FrameCreationCallback inOnFrame, int inWidth, int inHeight, sgIsOGL2 = false; } + #ifdef NME_ANGLE + if (!renderer && opengl && major>2) + { + fprintf(stderr, "GLES3 is not available. Retrying with GLES2. (%s)\n", SDL_GetError()); + major = 2; + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + } + else + #endif if (!renderer && (inFlags & wfHW_AA_HIRES || inFlags & wfHW_AA)) { // if no window was created and AA was enabled, disable AA and try again fprintf(stderr, "Multisampling is not available. Retrying without. (%s)\n", SDL_GetError()); diff --git a/src/nme/gl/GL.hx b/src/nme/gl/GL.hx index 5231ec467..9bfc3f28d 100644 --- a/src/nme/gl/GL.hx +++ b/src/nme/gl/GL.hx @@ -501,6 +501,11 @@ class GL nme_gl_bind_texture(target, texture); } + public static inline function bindVertexArray(vertexarray:GLVertexArray):Void + { + nme_gl_bind_vertexarray(vertexarray); + } + public static inline function blendColor(red:Float, green:Float, blue:Float, alpha:Float):Void { nme_gl_blend_color(red, green, blue, alpha); @@ -621,6 +626,11 @@ class GL return new GLTexture(version, nme_gl_create_texture()); } + public static inline function createVertexArray():GLVertexArray + { + return new GLVertexArray(version, nme_gl_create_vertexarray()); + } + public static inline function cullFace(mode:Int):Void { nme_gl_cull_face(mode); @@ -1310,6 +1320,10 @@ class GL private static var nme_gl_vertex_attrib4fv = load("nme_gl_vertex_attrib4fv", 2); private static var nme_gl_vertex_attrib_pointer = load("nme_gl_vertex_attrib_pointer", -1); private static var nme_gl_viewport = load("nme_gl_viewport", 4); + + //gles3 + private static var nme_gl_create_vertexarray = load("nme_gl_create_vertexarray", 0); + private static var nme_gl_bind_vertexarray = load("nme_gl_bind_vertexarray", 1); #else // not (neko||cpp) // Stub to get flixel to compile diff --git a/src/nme/gl/GLVertexArray.hx b/src/nme/gl/GLVertexArray.hx new file mode 100644 index 000000000..ae05c8400 --- /dev/null +++ b/src/nme/gl/GLVertexArray.hx @@ -0,0 +1,18 @@ +package nme.gl; +#if (!flash) + +@:nativeProperty +class GLVertexArray extends GLObject +{ + public function new(inVersion:Int, inId:Dynamic) + { + super(inVersion, inId); + } + + override function getType():String + { + return "VertexArray"; + } +} + +#end diff --git a/src/nme/gl/Utils.hx b/src/nme/gl/Utils.hx index 5794fb643..f99342d67 100644 --- a/src/nme/gl/Utils.hx +++ b/src/nme/gl/Utils.hx @@ -18,9 +18,20 @@ class Utils return shader; } - public static function createProgram(inVertexSource:String, inFragmentSource:String) + public static function createProgram(inVertexSource:String, inFragmentSource:String, inAutoHeader:Bool = true) { var program = GL.createProgram(); + if(inAutoHeader) + { + if( !StringTools.startsWith(inVertexSource,"#v") ) + { + inVertexSource = HEADER(GL.VERTEX_SHADER) + inVertexSource; + } + if( !StringTools.startsWith(inFragmentSource,"#v") ) + { + inFragmentSource = HEADER(GL.FRAGMENT_SHADER) + inFragmentSource; + } + } var vshader = createShader(inVertexSource, GL.VERTEX_SHADER); var fshader = createShader(inFragmentSource, GL.FRAGMENT_SHADER); GL.attachShader(program, vshader); @@ -35,5 +46,135 @@ class Utils return program; } + + public static function isGLES():Bool + { + if(!_glVersionInit) + GLVersion(); + + return _isGLES; + }; + + public static function isWebGL():Bool + { + if(!_glVersionInit) + GLVersion(); + + return _isWebGL; + }; + + //is GLES3 or OpenGL 3.3 + public static function isGLES3compat():Bool + { + if(!_glVersionInit) + GLVersion(); + + return _isGLES3compat; + }; + + //Gets version as float and inits isGLES, isGLES3compat + public static function GLVersion():Float + { + if(!_glVersionInit) + { + var version = GL.getParameter(GL.VERSION); + //trace("shading language: "+version); + + version = StringTools.ltrim(version); + if(version.indexOf("OpenGL ES")>=0) + { + _isGLES = true; + _isWebGL = false; + _glVersion = Std.parseFloat(version.split(" ")[2]); + _isGLES3compat = (_glVersion>=3.0); + } + else if(version.indexOf("WebGL")>=0) + { + _isGLES = true; //a kind of GLES + _isWebGL = true; + _glVersion = Std.parseFloat(version.split(" ")[1]); + _isGLES3compat = (_glVersion>=2.0); + } + else + { + _isGLES = false; + _isWebGL = false; + _glVersion = Std.parseFloat(version.split(" ")[0]); + _isGLES3compat = (_glVersion>=3.3); + } + _glVersionInit = true; + //trace("version: "+_glVersion+" is GLES: "+(_isGLES?"true":"false")+", is GLES3 compatible:"+(_isGLES3compat?"true":"false")); + } + return _glVersion; + } + + //Helper functions for writting compatible gles3/gles2 shader sources + //1) In VS: attribute -> IN(n) + //2) In VS: varying -> OUT() + //2a) In FS: varyng -> IN() + //3) In FS: OUT_COLOR("color"): define the name output instead of gl_FragColor + //5) HEADER is included automatically in "createProgram" unless inAutoHeader is set to false + + public static inline function IN(slot:Int = -1):String + { + return slot < 0 ? IN_FS() : IN_VS(slot); + } + + public static inline function IN_FS():String + { + return isGLES3compat()? + "\nin " : + "\nvarying "; + } + + public static inline function IN_VS(slot:Int):String + { + return isGLES3compat()? + "\nlayout(location = " + slot + ") in " : + "\nattribute "; + } + + public static inline function OUT():String + { + return isGLES3compat()? + "\nout" : + "\nvarying"; + } + + public static inline function OUT_COLOR(fragColor:String):String + { + return isGLES3compat()? + "\nout vec4 "+fragColor+";\n" : + "\n#define "+fragColor+" gl_FragColor\n"; + } + + public static inline function TEXTURE():String + { + return isGLES3compat()? + " texture" : + " texture2D"; + } + + private static inline function HEADER(type:Int):String + { + return isGLES3compat()? + ( + _isGLES? + "#version 300 es\nprecision mediump float; \n" : + "#version 330 core\n" + ) + : + ( + _isGLES? + "#version 100\nprecision mediump float; \n" : + "#version 110\n" + ); + } + + public static var _isGLES:Bool; + public static var _isWebGL:Bool; + public static var _isGLES3compat:Bool; + public static var _glVersion:Float; + public static var _glVersionInit:Bool; }