Exemplo n.º 1
0
    private static unsafe void Main(string[] args)
    {
        var parsedOpts = Parser.Default.ParseArguments <Options>(args);

        parsedOpts.WithParsed(opts => {
            if (opts.Context != null)
            {
                _useEgl = opts.Context.Contains("egl");
            }

            if (opts.GlApi != null)
            {
                _automaticFallback = false;
                _useOpenGl         = !opts.GlApi.Contains("es");
                _useOpenGl         = true;
            }

            if (opts.GlMajorVersion != null)
            {
                _automaticFallback = false;
                _glMaj             = opts.GlMajorVersion.Value;
            }

            if (opts.GlMinorVersion != null)
            {
                _automaticFallback = false;
                _glMin             = opts.GlMinorVersion.Value;
            }
        });

        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            Console.OutputEncoding = Encoding.UTF8;
            Ansi.WindowsConsole.TryEnableVirtualTerminalProcessing();
        }

        AppDomain.CurrentDomain.UnhandledException   += OnUnhandledException;
        AppDomain.CurrentDomain.FirstChanceException += OnFirstChanceException;

        //InjectNsight();

        //InjectRenderDoc();

        var options = WindowOptions.Default;

        var size = new Size(1024, 576);

        var title = "UltralightSharp - Silk.NET";

        options.Size  = size;
        options.Title = title;
        options.VSync = VSyncMode.On;
        options.TransparentFramebuffer   = false;
        options.PreferredDepthBufferBits = null;
        //options.VSync = true;

        /*
         * if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) {
         * var asmDir = Path.GetDirectoryName(new Uri(typeof(Program).Assembly.CodeBase!).LocalPath)!;
         * var glfwPath = Path.Combine(asmDir, "libglfw.so.3");
         * const string sysGlfwPath = "/lib/libglfw.so.3";
         * if (File.Exists(sysGlfwPath)) {
         *  var sb = new StringBuilder(1024);
         *  var sbSize = (UIntPtr)sb.Capacity;
         *  var used = (long)Libc.readlink(glfwPath, sb, sbSize);
         *  if (used >= 0) {
         *    var link = sb.ToString(0, (int)(used - 1));
         *    if (link != sysGlfwPath) {
         *      File.Delete(glfwPath);
         *      Libc.symlink(sysGlfwPath, glfwPath);
         *    }
         *  }
         *  else {
         *    // not a link
         *    File.Delete(glfwPath);
         *    Libc.symlink(sysGlfwPath, glfwPath);
         *    Cleanup += () => {
         *      File.Delete(glfwPath);
         *    };
         *  }
         * }
         * }
         */

        _glfw = Glfw.GetApi();
        Console.WriteLine($"GLFW v{_glfw.GetVersionString()}");

        if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
        {
            _glfw.InitHint(InitHint.CocoaMenubar, false);
            _glfw.InitHint(InitHint.CocoaChdirResources, false);
        }

        _glfw = GlfwProvider.GLFW.Value;

        {
            // setup logging
            Ultralight.SetLogger(new Logger {
                LogMessage = LoggerCallback
            });

            var tempDir = Path.GetTempPath();
            // find a place to stash instance storage
            do
            {
                _storagePath = Path.Combine(tempDir, Guid.NewGuid().ToString());
            }while (Directory.Exists(_storagePath) || File.Exists(_storagePath));

            AppCore.EnablePlatformFontLoader();

            AppCore.EnablePlatformFileSystem(AssetsDir);
        }

        /* afaik GLFW already does this, this was just to check
         * if (_useEgl || _automaticFallback) {
         * Console.WriteLine("Binding to LibEGL...");
         * var eglLib = new UnmanagedLibrary(
         *  new CustomEglLibNameContainer().GetLibraryName(),
         *  LibraryLoader.GetPlatformDefaultLoader()
         * );
         * var q = eglLib.LoadFunction("eglQueryAPI");
         * IL.Push(q);
         * IL.Emit.Calli(StandAloneMethodSig.UnmanagedMethod(CallingConvention.Cdecl, typeof(EGLEnum)));
         * IL.Pop(out EGLEnum api);
         * Console.WriteLine($"EGL API Target: {api}");
         * var b = eglLib.LoadFunction("eglBindAPI");
         * if (_useOpenGL && api != EGLEnum.OpenglApi) {
         *  IL.Push(EGLEnum.OpenglApi);
         *  IL.Push(b);
         *  IL.Emit.Calli(StandAloneMethodSig.UnmanagedMethod(CallingConvention.Cdecl, typeof(bool),
         *    typeof(EGLEnum)));
         *  IL.Pop(out bool success);
         *  Console.Error.WriteLine(!success
         *    ? "Couldn't bind EGL to OpenGL"
         *    : "EGL now bound to OpenGL");
         * }
         * else if (!_useOpenGL && api != EGLEnum.OpenglESApi){
         *  IL.Push(EGLEnum.OpenglESApi);
         *  IL.Push(b);
         *  IL.Emit.Calli(StandAloneMethodSig.UnmanagedMethod(CallingConvention.Cdecl, typeof(bool),
         *    typeof(EGLEnum)));
         *  IL.Pop(out bool success);
         *  Console.Error.WriteLine(!success
         *    ? "Couldn't bind EGL to OpenGL ES"
         *    : "EGL now bound to OpenGL ES");
         * }
         * }
         */

        if (_automaticFallback)
        {
            Console.WriteLine("Checking for supported context...");

            for (;;)
            {
                SetGlfwWindowHints();

                Console.WriteLine(
                    _useOpenGl
            ? "Attempting OpenGL v3.2 (Core)"
            : $"Attempting OpenGL ES v{_majOES}.0");
                var wh = _glfw.CreateWindow(1024, 576, title, null, null);
                if (wh != null)
                {
                    Console.WriteLine(
                        _useOpenGl
              ? "Created Window with OpenGL v3.2 (Core)"
              : $"Created Window with OpenGL ES v{_majOES}.0");
                    _glfw.DestroyWindow(wh);
                    break;
                }

                var code = _glfw.GetError(out char *pDesc);
                if (code == ErrorCode.NoError || pDesc == null)
                {
                    throw new PlatformNotSupportedException("Can't create a window via GLFW. Unknown error.");
                }

                var strLen = new ReadOnlySpan <byte>((byte *)pDesc, 32768).IndexOf <byte>(0);
                if (strLen == -1)
                {
                    strLen = 0;
                }
                var str    = new string((sbyte *)pDesc, 0, strLen, Encoding.UTF8);
                var errMsg = $"{code}: {str}";
                Console.Error.WriteLine(errMsg);
                if (code != ErrorCode.VersionUnavailable)
                {
                    throw new GlfwException(errMsg);
                }

                // attempt sequence: OpenGL ES 3.0, OpenGL 3.2, OpenGL ES 2.0
                if (!_useOpenGl && _majOES == 3)
                {
                    _useOpenGl = true;
                }
                else if (_majOES == 3 && _useOpenGl)
                {
                    _useOpenGl = false;
                    _majOES    = 2;
                }
                else
                {
                    throw new GlfwException(errMsg);
                }
            }
        }

        SetGlfwWindowHints();

        if (_useOpenGl)
        {
            options.API = new GraphicsAPI(
                ContextAPI.OpenGL,
                ContextProfile.Core,
                ContextFlags.ForwardCompatible,
                new APIVersion(_automaticFallback ? 3 : _glMaj, _automaticFallback ? 2 : _glMin)
                );
        }
        else
        {
            options.API = new GraphicsAPI(
                ContextAPI.OpenGLES,
                ContextProfile.Core,
                ContextFlags.ForwardCompatible,
                new APIVersion(_automaticFallback ? _majOES : _glMaj, _automaticFallback ? 0 : _glMin)
                );
        }
        options.IsVisible    = true;
        options.WindowBorder = WindowBorder.Resizable;
        options.WindowState  = WindowState.Normal;

        Console.WriteLine("Creating window...");

        _snView = Window.Create(options);

        _snView.Load    += OnLoad;
        _snView.Render  += OnRender;
        _snView.Update  += OnUpdate;
        _snView.Closing += OnClose;
        _snView.Resize  += OnResize;

        var glCtx = _snView.GLContext;

        if (!_useOpenGl)
        {
            Console.WriteLine("Binding to LibGLES...");
            _gl = LibraryActivator.CreateInstance <GL>
                  (
                new CustomGlEsLibNameContainer().GetLibraryName(),
                TemporarySuperInvokeClass.GetLoader(glCtx)
                  );
        }

        Console.WriteLine("Initializing window...");

        _snView.Initialize();

        if (_snView.Handle == IntPtr.Zero)
        {
            var code = _glfw.GetError(out char *pDesc);
            if (code == ErrorCode.NoError || pDesc == null)
            {
                throw new PlatformNotSupportedException("Can't create a window via GLFW. Unknown error.");
            }

            var strLen = new ReadOnlySpan <byte>((byte *)pDesc, 32768).IndexOf <byte>(0);
            if (strLen == -1)
            {
                strLen = 0;
            }
            var str = new string((sbyte *)pDesc, 0, strLen, Encoding.UTF8);
            throw new GlfwException($"{code}: {str}");
        }

        Console.WriteLine("Starting main loop...");
        _snView.Run();
    }