示例#1
0
        private void getImageGL(Action <Image <Rgba32> > callback)
        {
            host.DrawThread.Scheduler.Add(() =>
            {
                var image = new Image <Rgba32>((int)DrawWidth, (int)DrawHeight);

                var sharedData = (BufferedDrawNodeSharedData)typeof(BufferedContainer <Drawable>).GetField("sharedData", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this);

                var fbo = new FrameBuffer();
                fbo.Bind();
                GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget2d.Texture2D, sharedData.MainBuffer.Texture.TextureId, 0);

                bool success = image.TryGetSinglePixelSpan(out var span);
                Debug.Assert(success);
                GL.ReadPixels(0, 0, (int)DrawWidth, (int)DrawHeight, PixelFormat.Rgba, PixelType.UnsignedByte, ref MemoryMarshal.GetReference(span));
                fbo.Dispose();
                GLWrapper.BindFrameBuffer(GLWrapper.DefaultFrameBuffer);

                callback(image);
            });
        }
示例#2
0
        public void Bind()
        {
            if (IsBound)
            {
                return;
            }

            ensureLoaded();

            GLWrapper.UseProgram(this);

            foreach (var uniform in uniformsArray)
            {
                if (uniform.HasChanged)
                {
                    uniform.Update();
                }
            }

            IsBound = true;
        }
示例#3
0
        public override void SetData(TextureUpload upload)
        {
            if (IsDisposed)
            {
                throw new ObjectDisposedException(ToString(), "Can not set data of a disposed texture.");
            }

            if (upload.Bounds.IsEmpty)
            {
                upload.Bounds = new RectangleI(0, 0, width, height);
            }

            IsTransparent = false;

            bool requireUpload = uploadQueue.Count == 0;

            uploadQueue.Enqueue(upload);
            if (requireUpload)
            {
                GLWrapper.EnqueueTextureUpload(this);
            }
        }
示例#4
0
            public override void Draw(Action <TexturedVertex2D> vertexAction)
            {
                base.Draw(vertexAction);

                if (texture?.Available != true || segments.Count == 0)
                {
                    return;
                }

                GLWrapper.PushDepthInfo(DepthInfo.Default);

                Shader.Bind();

                texture.TextureGL.WrapMode = TextureWrapMode.ClampToEdge;
                texture.TextureGL.Bind();

                updateVertexBuffer();

                Shader.Unbind();

                GLWrapper.PopDepthInfo();
            }
示例#5
0
        public void Bind()
        {
            if (IsBound)
            {
                return;
            }

            if (!Loaded)
            {
                return;
            }

            GLWrapper.UseProgram(this);
            previousShader = GLWrapper.CurrentShader;

            foreach (var kvp in uniforms)
            {
                kvp.Value.Update();
            }

            IsBound = true;
        }
            private ValueInvokeOnDisposal establishFrameBufferViewport(Vector2 roundedSize)
            {
                // Disable masking for generating the frame buffer since masking will be re-applied
                // when actually drawing later on anyways. This allows more information to be captured
                // in the frame buffer and helps with cached buffers being re-used.
                RectangleI screenSpaceMaskingRect = new RectangleI((int)Math.Floor(screenSpaceDrawRectangle.X), (int)Math.Floor(screenSpaceDrawRectangle.Y), (int)roundedSize.X + 1,
                                                                   (int)roundedSize.Y + 1);

                GLWrapper.PushMaskingInfo(new MaskingInfo
                {
                    ScreenSpaceAABB = screenSpaceMaskingRect,
                    MaskingRect     = screenSpaceDrawRectangle,
                    ToMaskingSpace  = Matrix3.Identity,
                    BlendRange      = 1,
                    AlphaExponent   = 1,
                }, true);

                // Match viewport to FrameBuffer such that we don't draw unnecessary pixels.
                GLWrapper.PushViewport(new RectangleI(0, 0, (int)roundedSize.X, (int)roundedSize.Y));

                return(new ValueInvokeOnDisposal(returnViewport));
            }
        /// <summary>
        /// Removes texture from GL memory.
        /// </summary>
        private void unload()
        {
            lock (this)
            {
                if (dataToBeUploaded != null)
                {
                    FreeBuffer(dataToBeUploaded);
                }
                dataToBeUploaded = null;
            }

            int disposableId = textureId;

            if (disposableId <= 0)
            {
                return;
            }

            GLWrapper.DeleteTextures(disposableId);

            textureId = 0;
        }
示例#8
0
        public void TestOrtho()
        {
            var pixels = new[] { new Pixel(), new Pixel(), new Pixel(), new Pixel() };

            _window = new GameWindow {
                Width = 200, Height = 200
            };
            _window.RenderFrame += (caller, args) =>
            {
                IGL gl = new GLWrapper();
                gl.MatrixMode(MatrixMode.Projection);
                gl.LoadIdentity();
                gl.Ortho(0.0, 2.0, 0.0, 2.0, 0.0, 4.0);
                gl.Viewport(0, 0, 200, 200);
                gl.MatrixMode(MatrixMode.Modelview);
                gl.ReadBuffer(ReadBufferMode.Front);
                gl.Clear(ClearBufferMask.ColorBufferBit);
                gl.Begin(PrimitiveType.Quads);
                {
                    gl.Color3(1.0f, 1.0f, 1.0f);
                    gl.Vertex2(0.0f, 0.0f);
                    gl.Vertex2(1.0f, 0.0f);
                    gl.Vertex2(1.0f, 1.0f);
                    gl.Vertex2(0.0f, 1.0f);
                }
                gl.End();
                _window.SwapBuffers();
                pixels[0].ReadBuffer(99, 99);
                pixels[1].ReadBuffer(99, 100);
                pixels[2].ReadBuffer(100, 100);
                pixels[3].ReadBuffer(100, 99);
                _window.Close();
            };
            _window.Run();
            Assert.AreEqual(new Pixel(1.0f, 1.0f, 1.0f), pixels[0]);
            Assert.AreEqual(new Pixel(0.0f, 0.0f, 0.0f), pixels[1]);
            Assert.AreEqual(new Pixel(0.0f, 0.0f, 0.0f), pixels[2]);
            Assert.AreEqual(new Pixel(0.0f, 0.0f, 0.0f), pixels[3]);
        }
示例#9
0
        private void resize(int amountVertices)
        {
            Debug.Assert(!IsDisposed);

            T[] oldVertices = Vertices;
            Vertices = new T[amountVertices];

            if (oldVertices != null)
            {
                for (int i = 0; i < oldVertices.Length && i < Vertices.Length; ++i)
                {
                    Vertices[i] = oldVertices[i];
                }
            }

            if (GLWrapper.BindBuffer(BufferTarget.ArrayBuffer, vboId))
            {
                bind_attributes();
            }

            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(Vertices.Length * stride), IntPtr.Zero, usage);
        }
示例#10
0
            protected virtual void DrawChildrenOpaqueInteriors(DepthValue depthValue, Action <TexturedVertex2D> vertexAction)
            {
                bool canIncrement = depthValue.CanIncrement;

                // Assume that if we can't increment the depth value, no child can, thus nothing will be drawn.
                if (canIncrement)
                {
                    updateTriangleBatch();

                    // Prefer to use own vertex batch instead of the parent-owned one.
                    if (triangleBatch != null)
                    {
                        vertexAction = triangleBatch.AddAction;
                    }

                    if (maskingInfo != null)
                    {
                        GLWrapper.PushMaskingInfo(maskingInfo.Value);
                    }
                }

                // We still need to invoke this method recursively for all children so their depth value is updated
                if (Children != null)
                {
                    for (int i = Children.Count - 1; i >= 0; i--)
                    {
                        Children[i].DrawOpaqueInteriorSubTree(depthValue, vertexAction);
                    }
                }

                // Assume that if we can't increment the depth value, no child can, thus nothing will be drawn.
                if (canIncrement)
                {
                    if (maskingInfo != null)
                    {
                        GLWrapper.PopMaskingInfo();
                    }
                }
            }
示例#11
0
            public override void Draw(Action <TexturedVertex2D> vertexAction)
            {
                updateQuadBatch();

                // Prefer to use own vertex batch instead of the parent-owned one.
                if (quadBatch != null)
                {
                    vertexAction = quadBatch.AddAction;
                }

                base.Draw(vertexAction);

                drawEdgeEffect();

                if (maskingInfo != null)
                {
                    MaskingInfo info = maskingInfo.Value;
                    if (info.BorderThickness > 0)
                    {
                        info.BorderColour *= DrawColourInfo.Colour.AverageColour;
                    }

                    GLWrapper.PushMaskingInfo(info);
                }

                if (Children != null)
                {
                    for (int i = 0; i < Children.Count; i++)
                    {
                        Children[i].Draw(vertexAction);
                    }
                }

                if (maskingInfo != null)
                {
                    GLWrapper.PopMaskingInfo();
                }
            }
        private void drawEdgeEffect()
        {
            if (MaskingInfo == null || EdgeEffect.Type == EdgeEffectType.None || EdgeEffect.Radius <= 0.0f || EdgeEffect.Colour.A <= 0.0f)
            {
                return;
            }

            RectangleF effectRect = MaskingInfo.Value.MaskingRect.Inflate(EdgeEffect.Radius).Offset(EdgeEffect.Offset);

            if (!ScreenSpaceMaskingQuad.HasValue)
            {
                ScreenSpaceMaskingQuad = Quad.FromRectangle(effectRect) * DrawInfo.Matrix;
            }

            MaskingInfo edgeEffectMaskingInfo = MaskingInfo.Value;

            edgeEffectMaskingInfo.MaskingRect     = effectRect;
            edgeEffectMaskingInfo.ScreenSpaceAABB = ScreenSpaceMaskingQuad.Value.AABB;
            edgeEffectMaskingInfo.CornerRadius   += EdgeEffect.Radius + EdgeEffect.Roundness;
            edgeEffectMaskingInfo.BorderThickness = 0;
            edgeEffectMaskingInfo.BlendRange      = EdgeEffect.Radius;

            GLWrapper.PushMaskingInfo(edgeEffectMaskingInfo);

            GLWrapper.SetBlend(new BlendingInfo(EdgeEffect.Type == EdgeEffectType.Glow ? BlendingMode.Additive : BlendingMode.Mixture));

            Shader.Bind();

            Color4 colour = EdgeEffect.Colour;

            colour.A *= DrawInfo.Colour.A;

            Texture.WhitePixel.Draw(ScreenSpaceMaskingQuad.Value, colour);

            Shader.Unbind();

            GLWrapper.PopMaskingInfo();
        }
示例#13
0
        public void Bind()
        {
            if (IsDisposed)
            {
                throw new ObjectDisposedException(ToString(), "Can not bind a disposed shader.");
            }

            if (IsBound)
            {
                return;
            }

            EnsureShaderCompiled();

            GLWrapper.UseProgram(this);

            foreach (var uniform in uniformsValues)
            {
                uniform?.Update();
            }

            IsBound = true;
        }
示例#14
0
        public override void Draw()
        {
            base.Draw();

            // Set camera uniforms
            Shader.SetGlobalProperty(@"g_ProjMatrix", ProjectionMatrix);
            Shader.SetGlobalProperty(@"g_ViewMatrix", ViewMatrix);
            Shader.SetGlobalProperty(@"g_InvViewMatrix", InverseViewMatrix);

            // Invert culling
            //GL.CullFace(CullFaceMode.Front); // Flip culling for 3D

            foreach (var child in Children)
            {
                child.Draw();
            }

            // Flush batch before disabling state
            GLWrapper.FlushCurrentBatch();

            // Restore 3D states
            //GL.CullFace(CullFaceMode.Back);
        }
示例#15
0
        public override void Draw()
        {
            if (Texture == null)
            {
                return;
            }

            // For billboarding
            Shader.SetGlobalProperty("g_InverseViewMatrix", InverseViewMatrix);

            // Taken from DrawNode3D, since we don't need the world transform for particle systems
            GLWrapper.SetBlend(Blending);

            Shader.Bind();

            // Force create a separate batch so we can use instanced rendering
            if (particleInstancedBatch == null)
            {
                particleInstancedBatch = new QuadBatch <TexturedVertex2D>(TexturedVertex2D.Stride * 4, 1);
            }

            var colourInfo = new ColourInfo {
                Colour = Color4.White
            };

            Texture.DrawQuad(new Quad(-0.5f, -0.5f, 1.0f, 1.0f), colourInfo, vertexAction: v => particleInstancedBatch.Add(v));

            // Set GPU buffer data
            Buffer.SetData(BufferData);

            Buffer.Bind();

            // Render instanced
            particleInstancedBatch.DrawInstanced(InstanceCount);

            Shader.Unbind();
        }
        public override void Draw(IVertexBatch vertexBatch)
        {
            updateVertexBatch();

            // Prefer to use own vertex batch instead of the parent-owned one.
            if (Shared.VertexBatch != null)
            {
                vertexBatch = Shared.VertexBatch;
            }

            base.Draw(vertexBatch);

            drawEdgeEffect();
            if (MaskingInfo != null)
            {
                MaskingInfo info = MaskingInfo.Value;
                if (info.BorderThickness > 0)
                {
                    info.BorderColour *= DrawInfo.Colour.AverageColour;
                }

                GLWrapper.PushMaskingInfo(info);
            }

            if (Children != null)
            {
                foreach (DrawNode child in Children)
                {
                    child.Draw(vertexBatch);
                }
            }

            if (MaskingInfo != null)
            {
                GLWrapper.PopMaskingInfo();
            }
        }
示例#17
0
            private void drawBlurredFrameBuffer(int kernelRadius, float sigma, float blurRotation)
            {
                FrameBuffer current = SharedData.CurrentEffectBuffer;
                FrameBuffer target  = SharedData.GetNextEffectBuffer();

                GLWrapper.SetBlend(BlendingParameters.None);

                using (BindFrameBuffer(target))
                {
                    blurShader.GetUniform <int>(@"g_Radius").UpdateValue(ref kernelRadius);
                    blurShader.GetUniform <float>(@"g_Sigma").UpdateValue(ref sigma);

                    Vector2 size = current.Size;
                    blurShader.GetUniform <Vector2>(@"g_TexSize").UpdateValue(ref size);

                    float   radians = -MathUtils.DegreesToRadians(blurRotation);
                    Vector2 blur    = new Vector2(MathF.Cos(radians), MathF.Sin(radians));
                    blurShader.GetUniform <Vector2>(@"g_BlurDirection").UpdateValue(ref blur);

                    blurShader.Bind();
                    DrawFrameBuffer(current, new RectangleF(0, 0, current.Texture.Width, current.Texture.Height), ColourInfo.SingleColour(Color4.White));
                    blurShader.Unbind();
                }
            }
示例#18
0
        protected override void Initialise()
        {
            base.Initialise();

            if (amountIndices > QuadIndexData.MaxAmountIndices)
            {
                ushort[] indices = new ushort[amountIndices];

                for (ushort i = 0, j = 0; j < amountIndices; i += TextureGLSingle.VERTICES_PER_QUAD, j += indices_per_quad)
                {
                    indices[j]     = i;
                    indices[j + 1] = (ushort)(i + 1);
                    indices[j + 2] = (ushort)(i + 3);
                    indices[j + 3] = (ushort)(i + 2);
                    indices[j + 4] = (ushort)(i + 3);
                    indices[j + 5] = (ushort)(i + 1);
                }

                GLWrapper.BindBuffer(BufferTarget.ElementArrayBuffer, QuadIndexData.EBO_ID);
                GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(amountIndices * sizeof(ushort)), indices, BufferUsageHint.StaticDraw);

                QuadIndexData.MaxAmountIndices = amountIndices;
            }
        }
示例#19
0
        protected override void Dispose(bool isDisposing)
        {
            base.Dispose(isDisposing);

            memoryLease?.Dispose();

            GLWrapper.ScheduleDisposal(v =>
            {
                int[] ids = v.textureIds;

                if (ids == null)
                {
                    return;
                }

                for (int i = 0; i < ids.Length; i++)
                {
                    if (ids[i] >= 0)
                    {
                        GL.DeleteTextures(1, new[] { ids[i] });
                    }
                }
            }, this);
        }
            public override void Draw(Action <TexturedVertex2D> vertexAction)
            {
                base.Draw(vertexAction);

                if (texture?.Available != true || segments.Count == 0)
                {
                    return;
                }

                GLWrapper.PushDepthInfo(DepthInfo.Default);

                // Blending is removed to allow for correct blending between the wedges of the path.
                GLWrapper.SetBlend(BlendingParameters.None);

                pathShader.Bind();

                texture.TextureGL.Bind();

                updateVertexBuffer();

                pathShader.Unbind();

                GLWrapper.PopDepthInfo();
            }
            private void drawBlurredFrameBuffer(int kernelRadius, float sigma, float blurRotation)
            {
                FrameBuffer source = currentFrameBuffer;
                FrameBuffer target = advanceFrameBuffer();

                GLWrapper.SetBlend(new BlendingInfo(BlendingMode.None));

                using (bindFrameBuffer(target, source.Size))
                {
                    blurShader.GetUniform <int>(@"g_Radius").UpdateValue(ref kernelRadius);
                    blurShader.GetUniform <float>(@"g_Sigma").UpdateValue(ref sigma);

                    Vector2 size = source.Size;
                    blurShader.GetUniform <Vector2>(@"g_TexSize").UpdateValue(ref size);

                    float   radians = -MathHelper.DegreesToRadians(blurRotation);
                    Vector2 blur    = new Vector2((float)Math.Cos(radians), (float)Math.Sin(radians));
                    blurShader.GetUniform <Vector2>(@"g_BlurDirection").UpdateValue(ref blur);

                    blurShader.Bind();
                    drawFrameBufferToBackBuffer(source, new RectangleF(0, 0, source.Texture.Width, source.Texture.Height), ColourInfo.SingleColour(Color4.White));
                    blurShader.Unbind();
                }
            }
        public sealed override void Draw(Action <TexturedVertex2D> vertexAction)
        {
            if (RequiresRedraw)
            {
                FrameStatistics.Increment(StatisticsCounterType.FBORedraw);

                SharedData.ResetCurrentEffectBuffer();

                using (establishFrameBufferViewport())
                {
                    // Fill the frame buffer with drawn children
                    using (BindFrameBuffer(SharedData.MainBuffer))
                    {
                        // We need to draw children as if they were zero-based to the top-left of the texture.
                        // We can do this by adding a translation component to our (orthogonal) projection matrix.
                        GLWrapper.PushOrtho(screenSpaceDrawRectangle);
                        GLWrapper.Clear(new ClearInfo(backgroundColour));

                        Child.Draw(vertexAction);

                        GLWrapper.PopOrtho();
                    }

                    PopulateContents();
                }

                SharedData.DrawVersion = GetDrawVersion();
            }

            Shader.Bind();

            base.Draw(vertexAction);
            DrawContents();

            Shader.Unbind();
        }
示例#23
0
        public override void Draw(Action <TexturedVertex2D> vertexAction)
        {
            base.Draw(vertexAction);

            if (Texture == null || Texture.IsDisposed || Segments.Count == 0)
            {
                return;
            }

            GLWrapper.SetDepthTest(true);

            Shader shader = needsRoundedShader ? RoundedTextureShader : TextureShader;

            shader.Bind();

            Texture.TextureGL.WrapMode = TextureWrapMode.ClampToEdge;
            Texture.TextureGL.Bind();

            updateVertexBuffer();

            shader.Unbind();

            GLWrapper.SetDepthTest(false);
        }
示例#24
0
        // ===========================================================
        // Getter & Setter
        // ===========================================================

        /**
         * Set the glWrapper. If the glWrapper is not null, its
         * {@link GLWrapper#wrap(GL)} method is called whenever a surface is
         * created. A GLWrapper can be used to wrap the GL object that's passed to
         * the renderer. Wrapping a GL object enables examining and modifying the
         * behavior of the GL calls made by the renderer.
         * <p>
         * Wrapping is typically used for debugging purposes.
         * <p>
         * The default value is null.
         * 
         * @param glWrapper
         *            the new GLWrapper
         */
        public void SetGLWrapper(GLWrapper glWrapper)
        {
            this.mGLWrapper = glWrapper;
        }
示例#25
0
        internal override bool Upload()
        {
            // We should never run raw OGL calls on another thread than the main thread due to race conditions.
            ThreadSafety.EnsureDrawThread();

            if (IsDisposed)
            {
                throw new ObjectDisposedException(ToString(), "Can not upload data to a disposed texture.");
            }

            bool didUpload = false;

            while (uploadQueue.TryDequeue(out TextureUpload upload))
            {
                IntPtr   dataPointer;
                GCHandle?h0;

                if (upload.Data.Length == 0)
                {
                    h0          = null;
                    dataPointer = IntPtr.Zero;
                }
                else
                {
                    h0          = GCHandle.Alloc(upload.Data, GCHandleType.Pinned);
                    dataPointer = h0.Value.AddrOfPinnedObject();
                    didUpload   = true;
                }

                try
                {
                    // Do we need to generate a new texture?
                    if (textureId <= 0 || internalWidth != width || internalHeight != height)
                    {
                        internalWidth  = width;
                        internalHeight = height;

                        // We only need to generate a new texture if we don't have one already. Otherwise just re-use the current one.
                        if (textureId <= 0)
                        {
                            int[] textures = new int[1];
                            GL.GenTextures(1, textures);

                            textureId = textures[0];

                            GLWrapper.BindTexture(this);
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter,
                                            (int)(manualMipmaps ? filteringMode : (filteringMode == All.Linear ? All.LinearMipmapLinear : All.Nearest)));
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)filteringMode);

                            // 33085 is GL_TEXTURE_MAX_LEVEL, which is not available within TextureParameterName.
                            // It controls the amount of mipmap levels generated by GL.GenerateMipmap later on.
                            GL.TexParameter(TextureTarget.Texture2D, (TextureParameterName)33085, MAX_MIPMAP_LEVELS);

                            updateWrapMode();
                        }
                        else
                        {
                            GLWrapper.BindTexture(this);
                        }

                        if (width == upload.Bounds.Width && height == upload.Bounds.Height || dataPointer == IntPtr.Zero)
                        {
                            GL.TexImage2D(TextureTarget2d.Texture2D, upload.Level, TextureComponentCount.Srgb8Alpha8, width, height, 0, upload.Format, PixelType.UnsignedByte, dataPointer);
                        }
                        else
                        {
                            initializeLevel(upload.Level, width, height);

                            GL.TexSubImage2D(TextureTarget2d.Texture2D, upload.Level, upload.Bounds.X, upload.Bounds.Y, upload.Bounds.Width, upload.Bounds.Height, upload.Format, PixelType.UnsignedByte,
                                             dataPointer);
                        }
                    }
                    // Just update content of the current texture
                    else if (dataPointer != IntPtr.Zero)
                    {
                        GLWrapper.BindTexture(this);

                        if (!manualMipmaps && upload.Level > 0)
                        {
                            //allocate mipmap levels
                            int level = 1;
                            int d     = 2;

                            while (width / d > 0)
                            {
                                initializeLevel(level, width / d, height / d);
                                level++;
                                d *= 2;
                            }

                            manualMipmaps = true;
                        }

                        int div = (int)Math.Pow(2, upload.Level);

                        GL.TexSubImage2D(TextureTarget2d.Texture2D, upload.Level, upload.Bounds.X / div, upload.Bounds.Y / div, upload.Bounds.Width / div, upload.Bounds.Height / div, upload.Format,
                                         PixelType.UnsignedByte, dataPointer);
                    }
                }
                finally
                {
                    h0?.Free();
                    upload.Dispose();
                }
            }

            if (didUpload && !manualMipmaps)
            {
                GL.Hint(HintTarget.GenerateMipmapHint, HintMode.Nicest);
                GL.GenerateMipmap(TextureTarget.Texture2D);
            }

            return(didUpload);
        }
示例#26
0
 public void Dispose()
 {
     GLWrapper.ScheduleDisposal(d => d.Dispose(true), this);
     GC.SuppressFinalize(this);
 }
示例#27
0
 /// <summary>
 /// Draws this draw node to the screen.
 /// </summary>
 /// <param name="vertexAction">The action to be performed on each vertex of
 /// the draw node in order to draw it if required. This is primarily used by
 /// textured sprites.</param>
 public virtual void Draw(Action <TexturedVertex2D> vertexAction)
 {
     GLWrapper.SetBlend(DrawColourInfo.Blending);
 }
示例#28
0
        /// <summary>
        /// Binds the renderbuffer to the specfied framebuffer.
        /// </summary>
        /// <param name="frameBuffer">The framebuffer this renderbuffer should be bound to.</param>
        internal void Bind(int frameBuffer)
        {
            // Check if we're already bound
            if (info != null)
            {
                return;
            }

            if (!renderBufferCache.ContainsKey(Format))
            {
                renderBufferCache[Format] = new Stack <RenderBufferInfo>();
            }

            // Make sure we have renderbuffers available
            if (renderBufferCache[Format].Count == 0)
            {
                renderBufferCache[Format].Push(new RenderBufferInfo()
                {
                    RenderBufferID = GL.GenRenderbuffer(), FrameBufferID = -1
                });
            }

            // Get a renderbuffer from the cache
            info = renderBufferCache[Format].Pop();

            // Check if we need to update the size
            if (info.Size != Size)
            {
                GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, info.RenderBufferID);
                GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, Format, (int)Math.Ceiling(Size.X), (int)Math.Ceiling(Size.Y));

                info.Size = Size;
            }

            // For performance reasons, we only need to re-bind the renderbuffer to
            // the framebuffer if it is not already attached to it
            if (info.FrameBufferID != frameBuffer)
            {
                // Make sure the framebuffer we want to attach to is bound
                int lastFrameBuffer = GLWrapper.BindFrameBuffer(frameBuffer);

                switch (Format)
                {
                case RenderbufferInternalFormat.DepthComponent16:
                    GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferSlot.DepthAttachment, RenderbufferTarget.Renderbuffer, info.RenderBufferID);
                    break;

                case RenderbufferInternalFormat.Rgb565:
                case RenderbufferInternalFormat.Rgb5A1:
                case RenderbufferInternalFormat.Rgba4:
                    GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferSlot.ColorAttachment0, RenderbufferTarget.Renderbuffer, info.RenderBufferID);
                    break;

                case RenderbufferInternalFormat.StencilIndex8:
                    GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferSlot.DepthAttachment, RenderbufferTarget.Renderbuffer, info.RenderBufferID);
                    break;
                }

                GLWrapper.BindFrameBuffer(lastFrameBuffer);
            }

            info.FrameBufferID = frameBuffer;
        }
示例#29
0
 void panelGL_PaintCanvas(object sender, GLWrapper.CanvasEventArgs e)
 {
     Draw(new GLGraphics(e), DrawingMode.DrawLines);
 }
        public override bool Upload()
        {
            // We should never run raw OGL calls on another thread than the main thread due to race conditions.
            //Debug.Assert(Game.MainThread == Thread.CurrentThread);

            //todo: thread safety via GLWrapper.

            if (isDisposed)
            {
                return(false);
            }

            lock (this)
            {
                if (dataToBeUploaded == null)
                {
                    return(false);
                }

                IntPtr   dataPointer;
                GCHandle?h0;

                if (dataToBeUploaded.Length == 0)
                {
                    h0          = null;
                    dataPointer = IntPtr.Zero;
                }
                else
                {
                    h0          = GCHandle.Alloc(dataToBeUploaded, GCHandleType.Pinned);
                    dataPointer = h0.Value.AddrOfPinnedObject();
                }

                try
                {
                    // Do we need to generate a new texture?
                    if (textureId <= 0 || internalWidth < width || internalHeight < height)
                    {
                        internalWidth  = width;
                        internalHeight = height;

                        // We only need to generate a new texture if we don't have one already. Otherwise just re-use the current one.
                        if (textureId <= 0)
                        {
                            int[] textures = new int[1];
                            GL.GenTextures(1, textures);

                            textureId = textures[0];

                            GLWrapper.BindTexture(textureId);
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.LinearMipmapLinear);
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.LinearMipmapLinear);

                            updateWrapMode();
                        }
                        else
                        {
                            GLWrapper.BindTexture(textureId);
                        }

                        if (width == boundsToBeUploaded.Width && height == boundsToBeUploaded.Height || dataPointer == IntPtr.Zero)
                        {
                            GL.TexImage2D(TextureTarget2d.Texture2D, levelToBeUploaded, TextureComponentCount.Rgba, width, height, 0, formatToBeUploaded, PixelType.UnsignedByte, dataPointer);
                        }
                        else
                        {
                            if (transparentBlack.Length < width * height * 4)
                            {
                                transparentBlack = new byte[width * height * 4]; // Default value is 0, exactly what we need.
                            }
                            GCHandle h1 = GCHandle.Alloc(transparentBlack, GCHandleType.Pinned);
                            GL.TexImage2D(TextureTarget2d.Texture2D, levelToBeUploaded, TextureComponentCount.Rgba, width, height, 0, formatToBeUploaded, PixelType.UnsignedByte, h1.AddrOfPinnedObject());
                            h1.Free();

                            GL.TexSubImage2D(TextureTarget2d.Texture2D, levelToBeUploaded, boundsToBeUploaded.X, boundsToBeUploaded.Y, boundsToBeUploaded.Width, boundsToBeUploaded.Height, formatToBeUploaded, PixelType.UnsignedByte, dataPointer);
                        }

                        GL.Hint(HintTarget.GenerateMipmapHint, HintMode.Nicest);
                        GL.GenerateMipmap(TextureTarget.Texture2D);
                    }
                    // Just update content of the current texture
                    else if (dataPointer != IntPtr.Zero)
                    {
                        GLWrapper.BindTexture(textureId);
                        int div = (int)Math.Pow(2, levelToBeUploaded);
                        GL.TexSubImage2D(TextureTarget2d.Texture2D, levelToBeUploaded, boundsToBeUploaded.X / div, boundsToBeUploaded.Y / div, boundsToBeUploaded.Width / div, boundsToBeUploaded.Height / div, formatToBeUploaded, PixelType.UnsignedByte, dataPointer);
                    }

                    return(true);
                }
                finally
                {
                    if (h0.HasValue)
                    {
                        h0.Value.Free();
                    }

                    if (dataToBeUploaded != null)
                    {
                        FreeBuffer(dataToBeUploaded);
                    }

                    dataToBeUploaded = null;
                }
            }
        }
示例#31
0
        protected override void Dispose(bool isDisposing)
        {
            base.Dispose(isDisposing);

            GLWrapper.ScheduleDisposal(unload);
        }
示例#32
0
 protected virtual void Dispose(bool isDisposing) => GLWrapper.ScheduleDisposal(() => Available = false);