From d8031a161505046ed40ce6b17f6589870098f6ef Mon Sep 17 00:00:00 2001 From: Carlos Madrazo Date: Fri, 20 Oct 2017 00:42:34 -0500 Subject: [PATCH 1/5] Initial GLES3 (bis) merged and improved from https://github.com/haxenme/nme/pull/496 . Added GL3.hx for GLES3 functions. It is only activated for windows and android because needs testing on other targets (ios, linux, mac, emscripten). Windows angle needs https://github.com/native-toolkit/sdl/pull/11 , otherwise gets a GLES2 context. Tested with https://github.com/madrazo/nme-opengl-tutorials/tree/master/tutorial02_red_triangle --- project/include/Hardware.h | 1 + project/src/opengl/OGL.h | 14 +++ project/src/opengl/OGLExport.cpp | 46 ++++++++- project/src/opengl/OpenGLContext.cpp | 23 +++++ project/src/sdl2/SDL2Stage.cpp | 17 +++- src/nme/gl/GL3.hx | 41 ++++++++ src/nme/gl/GLVertexArray.hx | 18 ++++ src/nme/gl/Utils.hx | 134 ++++++++++++++++++++++++++- 8 files changed, 286 insertions(+), 8 deletions(-) create mode 100644 src/nme/gl/GL3.hx create mode 100644 src/nme/gl/GLVertexArray.hx 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..2f8e1e5d4 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,10 @@ #define NME_GLES + #ifndef NME_NO_GLES3COMPAT + #include + #define __gl2_h_ //Not needed for Android Platform >= 21 + #endif #include #include @@ -24,6 +31,9 @@ #include #include + #ifndef NME_NO_GLES3COMPAT + #include + #endif #elif defined(IPHONE) @@ -31,6 +41,10 @@ #include #include #include + #ifndef NME_NO_GLES3COMPAT + #include + #include + #endif //typedef CAEAGLLayer *WinDC; //typedef EAGLContext *GLCtx; diff --git a/project/src/opengl/OGLExport.cpp b/project/src/opengl/OGLExport.cpp index 898670426..fc1d78b14 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("createShader"); + return val_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,26 @@ 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 ) +{ + 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 ec8b6993f..ec27e1ea0 100644 --- a/project/src/sdl2/SDL2Stage.cpp +++ b/project/src/sdl2/SDL2Stage.cpp @@ -31,7 +31,6 @@ static int sgDesktopWidth = 0; static int sgDesktopHeight = 0; static Rect sgWindowRect = Rect(0, 0, 0, 0); static bool sgInitCalled = false; -//static bool sgJoystickEnabled = false; static bool sgGameControllerEnabled = false; static bool sgIsOGL2 = false; const int sgJoystickDeadZone = 1000; @@ -1806,9 +1805,13 @@ void CreateMainFrame(FrameCreationCallback inOnFrame, int inWidth, int inHeight, if (fullscreen) requestWindowFlags |= FullscreenMode; //SDL_WINDOW_FULLSCREEN_DESKTOP; #ifdef NME_ANGLE + int major = 3; + #ifdef NME_NO_GLES3COMPAT + major = 2; + #endif 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); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); #endif @@ -1938,6 +1941,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/GL3.hx b/src/nme/gl/GL3.hx new file mode 100644 index 000000000..b67c520f3 --- /dev/null +++ b/src/nme/gl/GL3.hx @@ -0,0 +1,41 @@ +package nme.gl; + +import nme.display.BitmapData; +import nme.utils.ArrayBuffer; +import nme.utils.ByteArray; +import nme.utils.IMemoryRange; +import nme.utils.ArrayBufferView; +import nme.geom.Matrix3D; +import nme.Lib; +import nme.Loader; + +#if (neko||cpp) +import nme.utils.Float32Array; +import nme.utils.Int32Array; +#end + + +@:nativeProperty +class GL3 +{ + + #if (neko||cpp) + + public static inline function bindVertexArray(vertexarray:GLVertexArray):Void + { + nme_gl_bind_vertexarray(vertexarray); + } + + public static inline function createVertexArray():GLVertexArray + { + return new GLVertexArray(GL.version, nme_gl_create_vertexarray()); + } + + + // Native Methods + private static var nme_gl_create_vertexarray = GL.load("nme_gl_create_vertexarray", 0); + private static var nme_gl_bind_vertexarray = GL.load("nme_gl_bind_vertexarray", 1); + + #end +} + 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..0a10f86d0 100644 --- a/src/nme/gl/Utils.hx +++ b/src/nme/gl/Utils.hx @@ -18,9 +18,17 @@ 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 +43,129 @@ class Utils return program; } + + public static function isGLES():Bool + { + initGLVersion(); + return _isGLES; + }; + + public static function isWebGL():Bool + { + initGLVersion(); + return _isWebGL; + }; + + //is GLES3, WebGL2, or OpenGL 3.3+ + public static function isGLES3compat():Bool + { + initGLVersion(); + return _isGLES3compat; + }; + + //Gets version as float and inits isGLES, isGLES3compat + public static function GLVersion():Float + { + initGLVersion(); + return _glVersion; + } + + //Inits glVersion, isGLES, isGLES3compat, isWebGL + public static function initGLVersion() + { + if(!_glVersionInit) + { + version = StringTools.ltrim(GL.getParameter(GL.VERSION)); + if(version.indexOf("OpenGL ES") >= 0) + { + _isGLES = true; + _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 + { + _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")); + } + } + + //Helper functions for writting gles3 shaders with gles2 fallback + //1) In VS: attribute -> IN(n) + //2) In VS: varying -> OUT() + //3) In FS: varyng -> IN() + //4) In FS: OUT_COLOR("color"): define the name output instead of gl_FragColor + //5) In FS: texture2D(x) -> TEXTURE(x) + //6) HEADER is included automatically in "createProgram" unless inAutoHeader is set to false + + public static function IN(slot:Int = -1):String + { + return slot < 0 ? IN_FS() : IN_VS(slot); + } + + public static function IN_FS():String + { + return isGLES3compat()? "\nin " : "\nvarying "; + } + + public static function IN_VS(slot:Int):String + { + return isGLES3compat()? + "\nlayout(location = " + slot + ") in " : + "\nattribute "; + } + + public static function OUT():String + { + return isGLES3compat()? "\nout " : "\nvarying "; + } + + public static function OUT_COLOR(fragColor:String):String + { + return isGLES3compat()? + "\nout vec4 "+fragColor+";\n" : + "\n#define "+fragColor+" gl_FragColor\n"; + } + + public static function TEXTURE( arg:String=null ):String + { + if(arg==null) + return isGLES3compat()? " texture" : " texture2D"; + else + return isGLES3compat()? + " texture(" + arg + ")" : + " texture2D(" + arg + ")"; + } + + 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" + ); + } + + private static var _isGLES:Bool; + private static var _isWebGL:Bool; + private static var _isGLES3compat:Bool; + private static var _glVersion:Float; + private static var _glVersionInit:Bool; } From a095f1b37d661fee9aba877c22b14982241741ba Mon Sep 17 00:00:00 2001 From: Carlos Madrazo Date: Fri, 20 Oct 2017 15:35:26 -0500 Subject: [PATCH 2/5] gles3 compile fix --- src/nme/gl/Utils.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nme/gl/Utils.hx b/src/nme/gl/Utils.hx index 0a10f86d0..b6d553d54 100644 --- a/src/nme/gl/Utils.hx +++ b/src/nme/gl/Utils.hx @@ -75,7 +75,7 @@ class Utils { if(!_glVersionInit) { - version = StringTools.ltrim(GL.getParameter(GL.VERSION)); + var version = StringTools.ltrim(GL.getParameter(GL.VERSION)); if(version.indexOf("OpenGL ES") >= 0) { _isGLES = true; From d67c5e6b544c3e32a53e466c3e8c0f1f13e3b484 Mon Sep 17 00:00:00 2001 From: Carlos Madrazo Date: Fri, 20 Oct 2017 21:44:23 -0500 Subject: [PATCH 3/5] gles3, flags NME_NO_GLES3COMPAT NME_GLES3COMPAT Use NME_NO_GLES3COMPAT to disable on Windows and Android Use NME_GLES3COMPAT flag to test gles3 in other targets Set android-18 platform for GLES3 --- project/ToolkitBuild.xml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/project/ToolkitBuild.xml b/project/ToolkitBuild.xml index dc83d5fb5..fa837fd71 100644 --- a/project/ToolkitBuild.xml +++ b/project/ToolkitBuild.xml @@ -4,9 +4,13 @@ + + + + @@ -199,6 +203,7 @@ + @@ -497,20 +502,23 @@
- + +
- + +
- + + From bb4ef1cb7602d7975c672f1af86dd1a657e75032 Mon Sep 17 00:00:00 2001 From: Carlos Madrazo Date: Fri, 20 Oct 2017 22:50:58 -0500 Subject: [PATCH 4/5] gles3, copile fix when disabling GLES3COMPAT --- project/src/opengl/OGLExport.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/src/opengl/OGLExport.cpp b/project/src/opengl/OGLExport.cpp index fc1d78b14..8f4f680c1 100644 --- a/project/src/opengl/OGLExport.cpp +++ b/project/src/opengl/OGLExport.cpp @@ -803,8 +803,8 @@ GL_GEN_RESO(render_buffer,glGenRenderbuffers,resoRenderbuffer) #ifdef NME_NO_GLES3COMPAT value nme_gl_create_vertexarray(value inType) { - DBGFUNC("createShader"); - return val_int(-1); + ELOG("Error: NME_NO_GLES3COMPAT is set"); + return alloc_int(-1); } DEFINE_PRIM(nme_gl_create_vertexarray,0); #else From 981567e649bb9bf3c187521f26279b9920390f3a Mon Sep 17 00:00:00 2001 From: Carlos Madrazo Date: Wed, 25 Oct 2017 23:03:53 -0500 Subject: [PATCH 5/5] show line numbers on shader source error Find error on shaders more easily --- src/nme/gl/Utils.hx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/nme/gl/Utils.hx b/src/nme/gl/Utils.hx index b6d553d54..3126ac6b7 100644 --- a/src/nme/gl/Utils.hx +++ b/src/nme/gl/Utils.hx @@ -10,7 +10,20 @@ class Utils GL.compileShader(shader); if (GL.getShaderParameter(shader, GL.COMPILE_STATUS)==0) { - trace("--- ERR ---\n" + source); + var lines = source.split("\n"); + var buf = new StringBuf(); + buf.add("--- ERR ---\n"); + var nline = 1; + for(line in lines) + { + if(nline<10) + buf.add("0"); + buf.add((nline++)); + buf.add(": "); + buf.add(line); + buf.add("\n"); + } + trace(buf.toString()); var err = GL.getShaderInfoLog(shader); if (err!="") throw err;