コード例 #1
0
ファイル: GraphicsBackend.cs プロジェクト: ozgun-kara/jazz2
        void IDualityBackend.Shutdown()
        {
            if (activeInstance == this)
            {
                activeInstance = null;
            }

            if (DualityApp.ExecContext != DualityApp.ExecutionContext.Terminated)
            {
                DefaultOpenTKBackendPlugin.GuardSingleThreadState();
                for (int i = 0; i < this.perVertexTypeVBO.Count; i++)
                {
                    uint handle = this.perVertexTypeVBO[i];
                    if (handle != 0)
                    {
                        GL.DeleteBuffers(1, ref handle);
                    }
                }
                this.perVertexTypeVBO.Clear();
            }

            // Since the window outlives the graphics backend in the usual launcher setup,
            // we'll need to unhook early, so Duality can complete its cleanup before the window does.
            if (this.activeWindow != null)
            {
                this.activeWindow.UnhookFromDuality();
                this.activeWindow = null;
            }
        }
コード例 #2
0
ファイル: NativeShaderPart.cs プロジェクト: ozgun-kara/jazz2
 void IDisposable.Dispose()
 {
     if (DualityApp.ExecContext != DualityApp.ExecutionContext.Terminated &&
         this.handle != 0)
     {
         DefaultOpenTKBackendPlugin.GuardSingleThreadState();
         GL.DeleteShader(this.handle);
         this.handle = 0;
     }
 }
コード例 #3
0
        public void ApplyPostRender()
        {
            DefaultOpenTKBackendPlugin.GuardSingleThreadState();

            if (!this.pendingPostRender)
            {
                return;
            }

            // Resolve multisampling to the main FBO
            if (this.samples > 0)
            {
                GL.Ext.BindFramebuffer(FramebufferTarget.ReadFramebuffer, this.handleMsaaFBO);
                GL.Ext.BindFramebuffer(FramebufferTarget.DrawFramebuffer, this.handleMainFBO);
                for (int i = 0; i < this.targetInfos.Count; i++)
                {
                    GL.ReadBuffer((ReadBufferMode)((int)ReadBufferMode.ColorAttachment0 + i));
                    GL.DrawBuffer((DrawBufferMode)((int)DrawBufferMode.ColorAttachment0 + i));
                    GL.Ext.BlitFramebuffer(
                        0, 0, this.targetInfos.Data[i].Target.Width, this.targetInfos.Data[i].Target.Height,
                        0, 0, this.targetInfos.Data[i].Target.Width, this.targetInfos.Data[i].Target.Height,
                        ClearBufferMask.ColorBufferBit, BlitFramebufferFilter.Nearest);
                }
            }

            // Generate mipmaps for the target textures
            int lastTexId = -1;

            for (int i = 0; i < this.targetInfos.Count; i++)
            {
                if (!this.targetInfos.Data[i].Target.HasMipmaps)
                {
                    continue;
                }

                if (lastTexId == -1)
                {
                    GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);
                    GL.GetInteger(GetPName.TextureBinding2D, out lastTexId);
                }

                int texId = this.targetInfos.Data[i].Target.Handle;
                GL.BindTexture(TextureTarget.Texture2D, texId);
                GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);
            }

            // Reset OpenGL state
            if (lastTexId != -1)
            {
                GL.BindTexture(TextureTarget.Texture2D, lastTexId);
            }
            ApplyGLBind(curBound);

            this.pendingPostRender = false;
        }
コード例 #4
0
ファイル: GraphicsBackend.cs プロジェクト: ozgun-kara/jazz2
        void IDualityBackend.Init()
        {
            // Initialize OpenTK, if not done yet
            DefaultOpenTKBackendPlugin.InitOpenTK();

            App.Log("Active graphics backend: OpenGL 2.1");

            // Log information about the available display devices
            GraphicsBackend.LogDisplayDevices();

            // Determine available and default graphics modes
            this.QueryGraphicsModes();
            activeInstance = this;
        }
コード例 #5
0
ファイル: NativeTexture.cs プロジェクト: ozgun-kara/jazz2
        void INativeTexture.GetData(IntPtr target, ColorDataLayout dataLayout, ColorDataElementType dataElementType)
        {
            DefaultOpenTKBackendPlugin.GuardSingleThreadState();

            int lastTexId;

            GL.GetInteger(GetPName.TextureBinding2D, out lastTexId);
            GL.BindTexture(TextureTarget.Texture2D, this.handle);

            GL.GetTexImage(TextureTarget.Texture2D, 0,
                           dataLayout.ToOpenTK(), dataElementType.ToOpenTK(),
                           target);

            GL.BindTexture(TextureTarget.Texture2D, lastTexId);
        }
コード例 #6
0
        void INativeRenderTarget.GetData <T>(T[] buffer, ColorDataLayout dataLayout, ColorDataElementType dataElementType, int targetIndex, int x, int y, int width, int height)
        {
            DefaultOpenTKBackendPlugin.GuardSingleThreadState();

            this.ApplyPostRender();
            if (curBound != this)
            {
                ApplyGLBind(this);
            }
            {
                GL.Ext.BindFramebuffer(FramebufferTarget.ReadFramebuffer, this.handleMainFBO);
                GL.ReadBuffer((ReadBufferMode)((int)ReadBufferMode.ColorAttachment0 + targetIndex));
                GL.ReadPixels(x, y, width, height, dataLayout.ToOpenTK(), dataElementType.ToOpenTK(), buffer);
            }
            ApplyGLBind(curBound);
        }
コード例 #7
0
ファイル: GraphicsBackend.cs プロジェクト: ozgun-kara/jazz2
        void IGraphicsBackend.GetOutputPixelData(IntPtr buffer, ColorDataLayout dataLayout, ColorDataElementType dataElementType, int x, int y, int width, int height)
        {
            DefaultOpenTKBackendPlugin.GuardSingleThreadState();

            NativeRenderTarget lastRt = NativeRenderTarget.BoundRT;

            NativeRenderTarget.Bind(null);
            {
                // Use a temporary local buffer, since the image will be upside-down because
                // of OpenGL's coordinate system and we'll need to flip it before returning.
                byte[] byteData = new byte[width * height * 4];

                // Retrieve pixel data
                GL.ReadPixels(x, y, width, height, dataLayout.ToOpenTK(), dataElementType.ToOpenTK(), byteData);

                // Flip the retrieved image vertically
                int    bytesPerLine = width * 4;
                byte[] switchLine   = new byte[width * 4];
                for (int flipY = 0; flipY < height / 2; flipY++)
                {
                    int lineIndex  = flipY * width * 4;
                    int lineIndex2 = (height - 1 - flipY) * width * 4;

                    // Copy the current line to the switch buffer
                    for (int lineX = 0; lineX < bytesPerLine; lineX++)
                    {
                        switchLine[lineX] = byteData[lineIndex + lineX];
                    }

                    // Copy the opposite line to the current line
                    for (int lineX = 0; lineX < bytesPerLine; lineX++)
                    {
                        byteData[lineIndex + lineX] = byteData[lineIndex2 + lineX];
                    }

                    // Copy the switch buffer to the opposite line
                    for (int lineX = 0; lineX < bytesPerLine; lineX++)
                    {
                        byteData[lineIndex2 + lineX] = switchLine[lineX];
                    }
                }

                // Copy the flipped data to the output buffer
                Marshal.Copy(byteData, 0, buffer, width * height * 4);
            }
            NativeRenderTarget.Bind(lastRt);
        }
コード例 #8
0
ファイル: NativeTexture.cs プロジェクト: ozgun-kara/jazz2
        void INativeTexture.SetupEmpty(TexturePixelFormat format, int width, int height, TextureMinFilter minFilter, TextureMagFilter magFilter, TextureWrapMode wrapX, TextureWrapMode wrapY, int anisoLevel, bool mipmaps)
        {
            DefaultOpenTKBackendPlugin.GuardSingleThreadState();

            int lastTexId;

            GL.GetInteger(GetPName.TextureBinding2D, out lastTexId);
            if (lastTexId != this.handle)
            {
                GL.BindTexture(TextureTarget.Texture2D, this.handle);
            }

            // Set texture parameters
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)ToOpenTKTextureMinFilter(minFilter));
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)ToOpenTKTextureMagFilter(magFilter));
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)ToOpenTKTextureWrapMode(wrapX));
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)ToOpenTKTextureWrapMode(wrapY));

            // Anisotropic filtering
            if (anisoLevel > 0)
            {
                GL.TexParameter(TextureTarget.Texture2D, (TextureParameterName)ExtTextureFilterAnisotropic.TextureMaxAnisotropyExt, (float)anisoLevel);
            }

            // If needed, care for Mipmaps
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.GenerateMipmap, mipmaps ? 1 : 0);

            // Setup pixel format
            GL.TexImage2D(TextureTarget.Texture2D, 0,
                          ToOpenTKPixelFormat(format), width, height, 0,
                          GLPixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);

            this.width   = width;
            this.height  = height;
            this.format  = format;
            this.mipmaps = mipmaps;

            if (lastTexId != this.handle)
            {
                GL.BindTexture(TextureTarget.Texture2D, lastTexId);
            }
        }
コード例 #9
0
ファイル: NativeTexture.cs プロジェクト: ozgun-kara/jazz2
        void INativeTexture.LoadData(TexturePixelFormat format, int width, int height, IntPtr data, ColorDataLayout dataLayout, ColorDataElementType dataElementType)
        {
            DefaultOpenTKBackendPlugin.GuardSingleThreadState();

            int lastTexId;

            GL.GetInteger(GetPName.TextureBinding2D, out lastTexId);
            GL.BindTexture(TextureTarget.Texture2D, this.handle);

            // Load pixel data to video memory
            GL.TexImage2D(TextureTarget.Texture2D, 0,
                          ToOpenTKPixelFormat(format), width, height, 0,
                          dataLayout.ToOpenTK(), dataElementType.ToOpenTK(),
                          data);

            this.width  = width;
            this.height = height;
            this.format = format;

            GL.BindTexture(TextureTarget.Texture2D, lastTexId);
        }
コード例 #10
0
ファイル: GraphicsBackend.cs プロジェクト: razluta/jazz2
        void IGraphicsBackend.GetOutputPixelData <T>(T[] buffer, ColorDataLayout dataLayout, ColorDataElementType dataElementType, int x, int y, int width, int height)
        {
            DefaultOpenTKBackendPlugin.GuardSingleThreadState();

            NativeRenderTarget lastRt = NativeRenderTarget.BoundRT;

            NativeRenderTarget.Bind(null);
            {
                GL.ReadPixels(x, y, width, height, dataLayout.ToOpenTK(), dataElementType.ToOpenTK(), buffer);

                // The image will be upside-down because of OpenGL's coordinate system. Flip it.
                int structSize = System.Runtime.InteropServices.Marshal.SizeOf(typeof(T));
                T[] switchLine = new T[width * 4 / structSize];
                for (int flipY = 0; flipY < height / 2; flipY++)
                {
                    int lineIndex  = flipY * width * 4 / structSize;
                    int lineIndex2 = (height - 1 - flipY) * width * 4 / structSize;

                    // Copy the current line to the switch buffer
                    for (int lineX = 0; lineX < width; lineX++)
                    {
                        switchLine[lineX] = buffer[lineIndex + lineX];
                    }

                    // Copy the opposite line to the current line
                    for (int lineX = 0; lineX < width; lineX++)
                    {
                        buffer[lineIndex + lineX] = buffer[lineIndex2 + lineX];
                    }

                    // Copy the switch buffer to the opposite line
                    for (int lineX = 0; lineX < width; lineX++)
                    {
                        buffer[lineIndex2 + lineX] = switchLine[lineX];
                    }
                }
            }
            NativeRenderTarget.Bind(lastRt);
        }
コード例 #11
0
        void IDisposable.Dispose()
        {
            if (DualityApp.ExecContext == DualityApp.ExecutionContext.Terminated)
            {
                return;
            }
            DefaultOpenTKBackendPlugin.GuardSingleThreadState();

            // If there are changes pending to be applied to the bound textures,
            // they should be executed before the render target is gone.
            this.ApplyPostRender();

            if (this.handleMainFBO != 0)
            {
                GL.Ext.DeleteFramebuffers(1, ref this.handleMainFBO);
                this.handleMainFBO = 0;
            }
            if (this.handleDepthRBO != 0)
            {
                GL.Ext.DeleteRenderbuffers(1, ref this.handleDepthRBO);
                this.handleDepthRBO = 0;
            }
            if (this.handleMsaaFBO != 0)
            {
                GL.Ext.DeleteFramebuffers(1, ref this.handleMsaaFBO);
                this.handleMsaaFBO = 0;
            }
            for (int i = 0; i < this.targetInfos.Count; i++)
            {
                if (this.targetInfos.Data[i].HandleMsaaColorRBO != 0)
                {
                    GL.Ext.DeleteRenderbuffers(1, ref this.targetInfos.Data[i].HandleMsaaColorRBO);
                    this.targetInfos.Data[i].HandleMsaaColorRBO = 0;
                }
            }
        }
コード例 #12
0
ファイル: NativeShaderPart.cs プロジェクト: ozgun-kara/jazz2
        void INativeShaderPart.LoadSource(string sourceCode, ShaderType type)
        {
            DefaultOpenTKBackendPlugin.GuardSingleThreadState();

            if (this.handle == 0)
            {
                this.handle = GL.CreateShader(GetOpenTKShaderType(type));
            }
            GL.ShaderSource(this.handle, sourceCode);
            GL.CompileShader(this.handle);

            int result;

            GL.GetShader(this.handle, ShaderParameter.CompileStatus, out result);
            if (result == 0)
            {
                string infoLog = GL.GetShaderInfoLog(this.handle);
                throw new BackendException(string.Format("{0} Compiler error:{2}{1}", type, infoLog, Environment.NewLine));
            }

            // Remove comments from source code before extracting variables
            string sourceWithoutComments;
            {
                const string blockComments   = @"/\*(.*?)\*/";
                const string lineComments    = @"//(.*?)\r?\n";
                const string strings         = @"""((\\[^\n]|[^""\n])*)""";
                const string verbatimStrings = @"@(""[^""]*"")+";
                sourceWithoutComments = Regex.Replace(sourceCode,
                                                      blockComments + "|" + lineComments + "|" + strings + "|" + verbatimStrings,
                                                      match => {
                    if (match.Value.StartsWith("/*") || match.Value.StartsWith("//"))
                    {
                        return(match.Value.StartsWith("//") ? Environment.NewLine : "");
                    }
                    else
                    {
                        return(match.Value);
                    }
                },
                                                      RegexOptions.Singleline);
            }

            // Scan remaining code chunk for variable declarations
            List <ShaderFieldInfo> varInfoList = new List <ShaderFieldInfo>();

            string[] lines = sourceWithoutComments.Split(new[] { ';', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string t in lines)
            {
                string curLine = t.TrimStart();

                ShaderFieldScope scope;
                int arrayLength;

                if (curLine.StartsWith("uniform"))
                {
                    scope = ShaderFieldScope.Uniform;
                }
                else if (curLine.StartsWith("attribute"))
                {
                    scope = ShaderFieldScope.Attribute;
                }
                else
                {
                    continue;
                }

                string[]        curLineSplit = curLine.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                ShaderFieldType varType      = ShaderFieldType.Unknown;
                switch (curLineSplit[1].ToUpper())
                {
                case "FLOAT": varType = ShaderFieldType.Float; break;

                case "VEC2": varType = ShaderFieldType.Vec2; break;

                case "VEC3": varType = ShaderFieldType.Vec3; break;

                case "VEC4": varType = ShaderFieldType.Vec4; break;

                case "MAT2": varType = ShaderFieldType.Mat2; break;

                case "MAT3": varType = ShaderFieldType.Mat3; break;

                case "MAT4": varType = ShaderFieldType.Mat4; break;

                case "INT": varType = ShaderFieldType.Int; break;

                case "BOOL": varType = ShaderFieldType.Bool; break;

                case "SAMPLER2D": varType = ShaderFieldType.Sampler2D; break;
                }

                curLineSplit = curLineSplit[2].Split(new[] { '[', ']' }, StringSplitOptions.RemoveEmptyEntries);
                arrayLength  = (curLineSplit.Length > 1) ? int.Parse(curLineSplit[1]) : 1;

                varInfoList.Add(new ShaderFieldInfo(curLineSplit[0], varType, scope, arrayLength));
            }

            this.fields = varInfoList.ToArray();
        }
コード例 #13
0
        void INativeShaderProgram.LoadProgram(INativeShaderPart vertex, INativeShaderPart fragment)
        {
            DefaultOpenTKBackendPlugin.GuardSingleThreadState();

            if (this.handle == 0)
            {
                this.handle = GL.CreateProgram();
            }
            else
            {
                this.DetachShaders();
            }

            // Attach both shaders
            if (vertex != null)
            {
                GL.AttachShader(this.handle, (vertex as NativeShaderPart).Handle);
            }
            if (fragment != null)
            {
                GL.AttachShader(this.handle, (fragment as NativeShaderPart).Handle);
            }

            // Link the shader program
            GL.LinkProgram(this.handle);

            int result;

            GL.GetProgram(this.handle, GetProgramParameterName.LinkStatus, out result);
            if (result == 0)
            {
                string errorLog = GL.GetProgramInfoLog(this.handle);
                this.RollbackAtFault();
                throw new BackendException(string.Format("Linker error:{1}{0}", errorLog, Environment.NewLine));
            }

            // Collect variable infos from sub programs
            {
                NativeShaderPart vert = vertex as NativeShaderPart;
                NativeShaderPart frag = fragment as NativeShaderPart;

                ShaderFieldInfo[] fragVarArray = frag != null ? frag.Fields : null;
                ShaderFieldInfo[] vertVarArray = vert != null ? vert.Fields : null;

                if (fragVarArray != null && vertVarArray != null)
                {
                    this.fields = vertVarArray.Union(fragVarArray).ToArray();
                }
                else if (vertVarArray != null)
                {
                    this.fields = vertVarArray.ToArray();
                }
                else
                {
                    this.fields = fragVarArray.ToArray();
                }
            }

            // Determine each variables location
            this.fieldLocations = new int[this.fields.Length];
            for (int i = 0; i < this.fields.Length; i++)
            {
                if (this.fields[i].Scope == ShaderFieldScope.Uniform)
                {
                    this.fieldLocations[i] = GL.GetUniformLocation(this.handle, this.fields[i].Name);
                }
                else
                {
                    this.fieldLocations[i] = GL.GetAttribLocation(this.handle, this.fields[i].Name);
                }
            }
        }
コード例 #14
0
        void INativeRenderTarget.Setup(IReadOnlyList <INativeTexture> targets, AAQuality multisample, bool depthBuffer)
        {
            DefaultOpenTKBackendPlugin.GuardSingleThreadState();

            if (targets == null)
            {
                return;
            }
            if (targets.Count == 0)
            {
                return;
            }
            if (targets.All(i => i == null))
            {
                return;
            }

            int highestAALevel = MathF.RoundToInt(MathF.Log(MathF.Max(MaxRenderTargetSamples, 1.0f), 2.0f));
            int targetAALevel  = highestAALevel;

            switch (multisample)
            {
            case AAQuality.High: targetAALevel = highestAALevel; break;

            case AAQuality.Medium: targetAALevel = highestAALevel / 2; break;

            case AAQuality.Low: targetAALevel = highestAALevel / 4; break;

            case AAQuality.Off: targetAALevel = 0; break;
            }
            int          targetSampleCount = MathF.RoundToInt(MathF.Pow(2.0f, targetAALevel));
            GraphicsMode sampleMode        =
                GraphicsBackend.ActiveInstance.AvailableGraphicsModes.LastOrDefault(m => m.Samples <= targetSampleCount) ??
                GraphicsBackend.ActiveInstance.AvailableGraphicsModes.Last();

            this.samples     = sampleMode.Samples;
            this.depthBuffer = depthBuffer;

            // Synchronize target information
            {
                this.targetInfos.Reserve(targets.Count);
                int localIndex = 0;
                for (int i = 0; i < targets.Count; i++)
                {
                    if (targets[i] == null)
                    {
                        continue;
                    }

                    this.targetInfos.Count = Math.Max(this.targetInfos.Count, localIndex + 1);
                    this.targetInfos.Data[localIndex].Target = targets[i] as NativeTexture;

                    localIndex++;
                }
            }

            // Setup OpenGL resources
            if (this.samples > 0)
            {
                this.SetupMultisampled();
            }
            else
            {
                this.SetupNonMultisampled();
            }
        }