Пример #1
0
        protected override void DoUpload(ITextureUpload upload, IntPtr dataPointer)
        {
            if (!(upload is VideoTextureUpload videoUpload))
            {
                return;
            }

            // Do we need to generate a new texture?
            if (textureIds == null)
            {
                Debug.Assert(memoryLease == null);
                memoryLease = NativeMemoryTracker.AddMemory(this, Width * Height * 3 / 2);

                textureIds = new int[3];
                GL.GenTextures(textureIds.Length, textureIds);

                for (int i = 0; i < textureIds.Length; i++)
                {
                    GLWrapper.BindTexture(textureIds[i]);

                    if (i == 0)
                    {
                        int width  = videoUpload.Frame->width;
                        int height = videoUpload.Frame->height;

                        GL.TexImage2D(TextureTarget2d.Texture2D, 0, TextureComponentCount.R8, width, height, 0, PixelFormat.Red, PixelType.UnsignedByte, IntPtr.Zero);

                        textureSize += width * height;
                    }
                    else
                    {
                        int width  = (videoUpload.Frame->width + 1) / 2;
                        int height = (videoUpload.Frame->height + 1) / 2;

                        GL.TexImage2D(TextureTarget2d.Texture2D, 0, TextureComponentCount.R8, width, height, 0, PixelFormat.Red, PixelType.UnsignedByte, IntPtr.Zero);

                        textureSize += width * height;
                    }

                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear);
                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);

                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
                    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
                }
            }

            for (int i = 0; i < textureIds.Length; i++)
            {
                GLWrapper.BindTexture(textureIds[i]);

                GL.PixelStore(PixelStoreParameter.UnpackRowLength, videoUpload.Frame->linesize[(uint)i]);
                GL.TexSubImage2D(TextureTarget2d.Texture2D, 0, 0, 0, videoUpload.Frame->width / (i > 0 ? 2 : 1), videoUpload.Frame->height / (i > 0 ? 2 : 1),
                                 PixelFormat.Red, PixelType.UnsignedByte, (IntPtr)videoUpload.Frame->data[(uint)i]);
            }

            GL.PixelStore(PixelStoreParameter.UnpackRowLength, 0);

            UploadComplete = true;
        }
Пример #2
0
        public override bool Bind()
        {
            if (IsDisposed)
            {
                throw new ObjectDisposedException(ToString(), "Can not bind a disposed texture.");
            }

            Upload();

            if (textureId <= 0)
            {
                return(false);
            }

            if (IsTransparent)
            {
                return(false);
            }

            GLWrapper.BindTexture(this);

            if (internalWrapMode != WrapMode)
            {
                updateWrapMode();
            }

            return(true);
        }
Пример #3
0
        public override bool Bind()
        {
            Debug.Assert(!isDisposed);

            Upload();

            if (textureId <= 0)
            {
                return(false);
            }

            if (IsTransparent)
            {
                return(false);
            }

            GLWrapper.BindTexture(this);

            if (internalWrapMode != WrapMode)
            {
                updateWrapMode();
            }

            return(true);
        }
Пример #4
0
        internal override bool Bind(TextureUnit unit, WrapMode wrapModeS, WrapMode wrapModeT)
        {
            if (!Available)
            {
                throw new ObjectDisposedException(ToString(), "Can not bind a disposed texture.");
            }

            Upload();

            if (textureIds == null)
            {
                return(false);
            }

            bool anyBound = false;

            for (int i = 0; i < textureIds.Length; i++)
            {
                anyBound |= GLWrapper.BindTexture(textureIds[i], unit + i, wrapModeS, wrapModeT);
            }

            if (anyBound)
            {
                BindCount++;
            }

            return(true);
        }
Пример #5
0
        public void TestDrawTransparentTexture()
        {
            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.Viewport(0, 0, 200, 200);
                gl.ReadBuffer(ReadBufferMode.Front);

                gl.Enable(EnableCap.Texture2D);
                gl.Enable(EnableCap.Blend);
                gl.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
                gl.ClearColor(1.0f, 1.0f, 0.0f, 1.0f);
                int textureId = GL.GenTexture();
                gl.BindTexture(TextureTarget.Texture2D, textureId);
                gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
                gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
                var bitmap = new Bitmap(@"..\..\Images\testtexture.png");
                var data   = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                                             ImageLockMode.ReadOnly,
                                             System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                gl.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height,
                              0, PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
                bitmap.UnlockBits(data);

                gl.Clear(ClearBufferMask.ColorBufferBit);
                gl.Begin(PrimitiveType.Quads);
                {
                    gl.TexCoord2(0.0f, 0.0f);
                    gl.Vertex2(-1.0f, -1.0f);
                    gl.TexCoord2(1.0f, 0.0f);
                    gl.Vertex2(1.0f, -1.0f);
                    gl.TexCoord2(1.0f, 1.0f);
                    gl.Vertex2(1.0f, 1.0f);
                    gl.TexCoord2(0.0f, 1.0f);
                    gl.Vertex2(-1.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, 0.0f, 0.0f), pixels[0]);
            Assert.AreEqual(new Pixel(0.0f, 1.0f, 0.0f), pixels[1]);
            Assert.AreEqual(new Pixel(0.0f, 0.0f, 1.0f), pixels[2]);
            Assert.AreEqual(new Pixel(1.0f, 1.0f, 0.0f), pixels[3]);
        }
Пример #6
0
        public override bool Bind(TextureUnit unit = TextureUnit.Texture0)
        {
            if (!Available)
            {
                throw new ObjectDisposedException(ToString(), "Can not bind a disposed texture.");
            }

            for (int i = 0; i < textureIds.Length; i++)
            {
                GLWrapper.BindTexture(textureIds[i], unit + i);
            }

            return(true);
        }
Пример #7
0
        internal override bool Bind(TextureUnit unit, WrapMode wrapModeS, WrapMode wrapModeT)
        {
            if (!Available)
            {
                throw new ObjectDisposedException(ToString(), "Can not bind a disposed texture.");
            }

            for (int i = 0; i < textureIds.Length; i++)
            {
                GLWrapper.BindTexture(textureIds[i], unit + i, wrapModeS, wrapModeT);
            }

            return(true);
        }
Пример #8
0
        public FrameBuffer(bool withTexture = true)
        {
            frameBuffer = GL.GenFramebuffer();

            if (withTexture)
            {
                Texture = new TextureGLSingle(1, 1);
                Texture.SetData(new TextureUpload(0));
                Texture.Upload();

                Bind();

                GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, All.ColorAttachment0, TextureTarget2d.Texture2D, Texture.TextureId, 0);
                GLWrapper.BindTexture(0);

                Unbind();
            }
        }
Пример #9
0
        internal FrameBuffer(bool withTexture = true)
        {
            frameBuffer = GL.GenFramebuffer();

            if (withTexture)
            {
                Texture = new TextureGLSingle(1, 1);
                Texture.SetData(new byte[0]);
                Texture.Upload();

                Bind();

                GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferSlot.ColorAttachment0, TextureTarget.Texture2D, Texture.TextureId, 0);
                GLWrapper.BindTexture(0);

                Unbind();
            }
        }
Пример #10
0
        public void Initialize(bool withTexture = true, All filteringMode = All.Linear)
        {
            frameBuffer = GL.GenFramebuffer();

            if (withTexture)
            {
                Texture = new TextureGLSingle(1, 1, true, filteringMode);
                Texture.SetData(new TextureUpload(new byte[0]));
                Texture.Upload();

                Bind();

                GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget2d.Texture2D, Texture.TextureId, 0);
                GLWrapper.BindTexture(null);

                Unbind();
            }

            IsInitialized = true;
        }
Пример #11
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);
        }
Пример #12
0
        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;
                }
            }
        }
        protected override void DrawMesh(CubismDrawable drawable, Texture texture, FrameBuffer clippingMask, Matrix4 drawMatrix)
        {
            int offset = 1 + (clippingMask != null ? (drawable.ConstantFlags.HasFlag(ConstantDrawableFlags.IsInvertedMask) ? 2 : 1) : 0) + (UsePremultipliedAlpha ? 3 : 0);

            IShader            shader;
            BlendingParameters blendingParameters;

            if (drawable.ConstantFlags.HasFlag(ConstantDrawableFlags.BlendMultiplicative))
            {
                shader             = shaders[offset];
                blendingParameters = new BlendingParameters
                {
                    Source           = BlendingType.DstColor,
                    Destination      = BlendingType.OneMinusSrcAlpha,
                    SourceAlpha      = BlendingType.Zero,
                    DestinationAlpha = BlendingType.One,
                };
            }
            else if (drawable.ConstantFlags.HasFlag(ConstantDrawableFlags.BlendAdditive))
            {
                shader             = shaders[offset];
                blendingParameters = new BlendingParameters
                {
                    Source           = BlendingType.One,
                    Destination      = BlendingType.One,
                    SourceAlpha      = BlendingType.Zero,
                    DestinationAlpha = BlendingType.One,
                };
            }
            else
            {
                shader             = shaders[offset];
                blendingParameters = new BlendingParameters
                {
                    Source           = BlendingType.One,
                    Destination      = BlendingType.OneMinusSrcAlpha,
                    SourceAlpha      = BlendingType.One,
                    DestinationAlpha = BlendingType.OneMinusSrcAlpha,
                };
            }

            GLWrapper.SetBlend(blendingParameters);
            shader.Bind();

            if (clippingMask != null)
            {
                clippingMask.Texture.Bind(TextureUnit.Texture1);

                shader.GetUniform <int>("s_texture1").Value        = 1;
                shader.GetUniform <Matrix4>("u_clipMatrix").Value  = drawMatrix;
                shader.GetUniform <Vector4>("u_channelFlag").Value = new Vector4(1.0f, 0.0f, 0.0f, 0.0f);
            }
            else
            {
                GLWrapper.BindTexture(null, TextureUnit.Texture1);
            }

            texture.TextureGL.Bind();

            shader.GetUniform <int>("s_texture0").Value   = 0;
            shader.GetUniform <Matrix4>("u_matrix").Value = MvpMatrix;

            var color = new Vector4(Color.R, Color.G, Color.B, Color.A);

            color.W *= drawable.Opacity;

            if (UsePremultipliedAlpha)
            {
                color.X *= drawable.Opacity;
                color.Y *= drawable.Opacity;
                color.Z *= drawable.Opacity;
            }

            shader.GetUniform <Vector4>("u_baseColor").Value = color;

            GL.EnableVertexAttribArray(0);

            fixed(float *pinnedVertexBuffer = drawable.Vertices)
            GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, sizeof(float) * 2, (IntPtr)pinnedVertexBuffer);

            GL.EnableVertexAttribArray(1);

            fixed(float *pinnedUVBuffer = drawable.TextureCoordinates)
            GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, sizeof(float) * 2, (IntPtr)pinnedUVBuffer);

            fixed(short *pinnedIndexBuffer = drawable.Indices)
            GL.DrawElements(PrimitiveType.Triangles, drawable.Indices.Length, DrawElementsType.UnsignedShort, (IntPtr)pinnedIndexBuffer);

            shader.Unbind();
        }
Пример #14
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)
            {
                return(false);
            }

            IntPtr        dataPointer;
            GCHandle?     h0;
            TextureUpload upload;
            bool          didUpload = false;

            while (uploadQueue.TryDequeue(out upload))
            {
                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(textureId);
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.LinearMipmapLinear);
                            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);

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

                        if (width == upload.Bounds.Width && height == upload.Bounds.Height || dataPointer == IntPtr.Zero)
                        {
                            GL.TexImage2D(TextureTarget2d.Texture2D, upload.Level, TextureComponentCount.Rgba, 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(textureId);

                        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);
        }