コード例 #1
0
ファイル: OglRasterizer.cs プロジェクト: zpoo32/Ryujinx
        public void DrawArrays(int first, int count, GalPrimitiveType primType)
        {
            if (count == 0)
            {
                return;
            }

            if (primType == GalPrimitiveType.Quads)
            {
                for (int offset = 0; offset < count; offset += 4)
                {
                    GL.DrawArrays(PrimitiveType.TriangleFan, first + offset, 4);
                }
            }
            else if (primType == GalPrimitiveType.QuadStrip)
            {
                GL.DrawArrays(PrimitiveType.TriangleFan, first, 4);

                for (int offset = 2; offset < count; offset += 2)
                {
                    GL.DrawArrays(PrimitiveType.TriangleFan, first + offset, 4);
                }
            }
            else
            {
                GL.DrawArrays(OglEnumConverter.GetPrimitiveType(primType), first, count);
            }
        }
コード例 #2
0
        private void SetAllBlendState(BlendState New)
        {
            Enable(EnableCap.Blend, New.Enabled);

            if (New.Enabled)
            {
                if (New.SeparateAlpha)
                {
                    GL.BlendEquationSeparate(
                        OglEnumConverter.GetBlendEquation(New.EquationRgb),
                        OglEnumConverter.GetBlendEquation(New.EquationAlpha));

                    GL.BlendFuncSeparate(
                        (BlendingFactorSrc)OglEnumConverter.GetBlendFactor(New.FuncSrcRgb),
                        (BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstRgb),
                        (BlendingFactorSrc)OglEnumConverter.GetBlendFactor(New.FuncSrcAlpha),
                        (BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstAlpha));
                }
                else
                {
                    GL.BlendEquation(OglEnumConverter.GetBlendEquation(New.EquationRgb));

                    GL.BlendFunc(
                        OglEnumConverter.GetBlendFactor(New.FuncSrcRgb),
                        OglEnumConverter.GetBlendFactor(New.FuncDstRgb));
                }
            }
        }
コード例 #3
0
ファイル: OglRasterizer.cs プロジェクト: zpoo32/Ryujinx
        public void SetIndexArray(int size, GalIndexFormat format)
        {
            _indexBuffer.Type = OglEnumConverter.GetDrawElementsType(format);

            _indexBuffer.Count = size >> (int)format;

            _indexBuffer.ElemSizeLog2 = (int)format;
        }
コード例 #4
0
        public void Compile()
        {
            if (Handle == 0)
            {
                Handle = GL.CreateShader(OglEnumConverter.GetShaderType(Type));

                CompileAndCheck(Handle, Code);
            }
        }
コード例 #5
0
        public void Reinterpret(long key, GalImage newImage)
        {
            if (!_texture.TryGetImage(key, out GalImage oldImage))
            {
                return;
            }

            if (newImage.Format == oldImage.Format &&
                newImage.Width == oldImage.Width &&
                newImage.Height == oldImage.Height &&
                newImage.Depth == oldImage.Depth &&
                newImage.LayerCount == oldImage.LayerCount &&
                newImage.TextureTarget == oldImage.TextureTarget)
            {
                return;
            }

            if (_copyPbo == 0)
            {
                _copyPbo = GL.GenBuffer();
            }

            GL.BindBuffer(BufferTarget.PixelPackBuffer, _copyPbo);

            // The buffer should be large enough to hold the largest texture.
            int bufferSize = Math.Max(ImageUtils.GetSize(oldImage),
                                      ImageUtils.GetSize(newImage));

            GL.BufferData(BufferTarget.PixelPackBuffer, bufferSize, IntPtr.Zero, BufferUsageHint.StreamCopy);

            if (!_texture.TryGetImageHandler(key, out ImageHandler cachedImage))
            {
                throw new InvalidOperationException();
            }

            (_, PixelFormat format, PixelType type) = OglEnumConverter.GetImageFormat(cachedImage.Format);

            TextureTarget target = ImageUtils.GetTextureTarget(newImage.TextureTarget);

            GL.BindTexture(target, cachedImage.Handle);

            GL.GetTexImage(target, 0, format, type, IntPtr.Zero);

            GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
            GL.BindBuffer(BufferTarget.PixelUnpackBuffer, _copyPbo);

            GL.PixelStore(PixelStoreParameter.UnpackRowLength, oldImage.Width);

            _texture.Create(key, ImageUtils.GetSize(newImage), newImage);

            GL.PixelStore(PixelStoreParameter.UnpackRowLength, 0);

            GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
        }
コード例 #6
0
        private void SetBlendState(int index, BlendState New, BlendState old)
        {
            if (New.Enabled != old.Enabled)
            {
                Enable(IndexedEnableCap.Blend, index, New.Enabled);
            }

            if (New.Enabled)
            {
                if (New.SeparateAlpha)
                {
                    if (New.EquationRgb != old.EquationRgb ||
                        New.EquationAlpha != old.EquationAlpha)
                    {
                        GL.BlendEquationSeparate(
                            index,
                            OglEnumConverter.GetBlendEquation(New.EquationRgb),
                            OglEnumConverter.GetBlendEquation(New.EquationAlpha));
                    }

                    if (New.FuncSrcRgb != old.FuncSrcRgb ||
                        New.FuncDstRgb != old.FuncDstRgb ||
                        New.FuncSrcAlpha != old.FuncSrcAlpha ||
                        New.FuncDstAlpha != old.FuncDstAlpha)
                    {
                        GL.BlendFuncSeparate(
                            index,
                            (BlendingFactorSrc)OglEnumConverter.GetBlendFactor(New.FuncSrcRgb),
                            (BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstRgb),
                            (BlendingFactorSrc)OglEnumConverter.GetBlendFactor(New.FuncSrcAlpha),
                            (BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstAlpha));
                    }
                }
                else
                {
                    if (New.EquationRgb != old.EquationRgb)
                    {
                        GL.BlendEquation(index, OglEnumConverter.GetBlendEquation(New.EquationRgb));
                    }

                    if (New.FuncSrcRgb != old.FuncSrcRgb ||
                        New.FuncDstRgb != old.FuncDstRgb)
                    {
                        GL.BlendFunc(
                            index,
                            (BlendingFactorSrc)OglEnumConverter.GetBlendFactor(New.FuncSrcRgb),
                            (BlendingFactorDest)OglEnumConverter.GetBlendFactor(New.FuncDstRgb));
                    }
                }
            }
        }
コード例 #7
0
        public void Bind(long key, int index, GalImage image)
        {
            if (_textureCache.TryGetValue(key, out ImageHandler cachedImage))
            {
                GL.ActiveTexture(TextureUnit.Texture0 + index);

                TextureTarget target = ImageUtils.GetTextureTarget(image.TextureTarget);

                GL.BindTexture(target, cachedImage.Handle);

                int[] swizzleRgba = new int[]
                {
                    (int)OglEnumConverter.GetTextureSwizzle(image.XSource),
                    (int)OglEnumConverter.GetTextureSwizzle(image.YSource),
                    (int)OglEnumConverter.GetTextureSwizzle(image.ZSource),
                    (int)OglEnumConverter.GetTextureSwizzle(image.WSource)
                };

                GL.TexParameter(target, TextureParameterName.TextureSwizzleRgba, swizzleRgba);
            }
        }
コード例 #8
0
        public void SetSampler(GalImage image, GalTextureSampler sampler)
        {
            int wrapS = (int)OglEnumConverter.GetTextureWrapMode(sampler.AddressU);
            int wrapT = (int)OglEnumConverter.GetTextureWrapMode(sampler.AddressV);
            int wrapR = (int)OglEnumConverter.GetTextureWrapMode(sampler.AddressP);

            int minFilter = (int)OglEnumConverter.GetTextureMinFilter(sampler.MinFilter, sampler.MipFilter);
            int magFilter = (int)OglEnumConverter.GetTextureMagFilter(sampler.MagFilter);

            TextureTarget target = ImageUtils.GetTextureTarget(image.TextureTarget);

            GL.TexParameter(target, TextureParameterName.TextureWrapS, wrapS);
            GL.TexParameter(target, TextureParameterName.TextureWrapT, wrapT);
            GL.TexParameter(target, TextureParameterName.TextureWrapR, wrapR);

            GL.TexParameter(target, TextureParameterName.TextureMinFilter, minFilter);
            GL.TexParameter(target, TextureParameterName.TextureMagFilter, magFilter);

            float[] color = new float[]
            {
                sampler.BorderColor.Red,
                sampler.BorderColor.Green,
                sampler.BorderColor.Blue,
                sampler.BorderColor.Alpha
            };

            GL.TexParameter(target, TextureParameterName.TextureBorderColor, color);

            if (sampler.DepthCompare)
            {
                GL.TexParameter(target, TextureParameterName.TextureCompareMode, (int)All.CompareRToTexture);
                GL.TexParameter(target, TextureParameterName.TextureCompareFunc, (int)OglEnumConverter.GetDepthCompareFunc(sampler.DepthCompareFunc));
            }
            else
            {
                GL.TexParameter(target, TextureParameterName.TextureCompareMode, (int)All.None);
                GL.TexParameter(target, TextureParameterName.TextureCompareFunc, (int)All.Never);
            }
        }
コード例 #9
0
ファイル: OglRasterizer.cs プロジェクト: zpoo32/Ryujinx
        public void DrawElements(long iboKey, int first, int vertexBase, GalPrimitiveType primType)
        {
            if (!_iboCache.TryGetValue(iboKey, out int iboHandle))
            {
                return;
            }

            PrimitiveType mode = OglEnumConverter.GetPrimitiveType(primType);

            GL.BindBuffer(BufferTarget.ElementArrayBuffer, iboHandle);

            first <<= _indexBuffer.ElemSizeLog2;

            if (vertexBase != 0)
            {
                IntPtr indices = new IntPtr(first);

                GL.DrawElementsBaseVertex(mode, _indexBuffer.Count, _indexBuffer.Type, indices, vertexBase);
            }
            else
            {
                GL.DrawElements(mode, _indexBuffer.Count, _indexBuffer.Type, first);
            }
        }
コード例 #10
0
        public void Create(long key, int size, GalImage image)
        {
            int handle = GL.GenTexture();

            TextureTarget target = ImageUtils.GetTextureTarget(image.TextureTarget);

            GL.BindTexture(target, handle);

            const int level  = 0; //TODO: Support mipmap textures.
            const int border = 0;

            _textureCache.AddOrUpdate(key, new ImageHandler(handle, image), (uint)size);

            if (ImageUtils.IsCompressed(image.Format))
            {
                throw new InvalidOperationException("Surfaces with compressed formats are not supported!");
            }

            (PixelInternalFormat internalFmt,
             PixelFormat format,
             PixelType type) = OglEnumConverter.GetImageFormat(image.Format);

            switch (target)
            {
            case TextureTarget.Texture1D:
                GL.TexImage1D(
                    target,
                    level,
                    internalFmt,
                    image.Width,
                    border,
                    format,
                    type,
                    IntPtr.Zero);
                break;

            case TextureTarget.Texture2D:
                GL.TexImage2D(
                    target,
                    level,
                    internalFmt,
                    image.Width,
                    image.Height,
                    border,
                    format,
                    type,
                    IntPtr.Zero);
                break;

            case TextureTarget.Texture3D:
                GL.TexImage3D(
                    target,
                    level,
                    internalFmt,
                    image.Width,
                    image.Height,
                    image.Depth,
                    border,
                    format,
                    type,
                    IntPtr.Zero);
                break;

            case TextureTarget.Texture2DArray:
                GL.TexImage3D(
                    target,
                    level,
                    internalFmt,
                    image.Width,
                    image.Height,
                    image.LayerCount,
                    border,
                    format,
                    type,
                    IntPtr.Zero);
                break;

            default:
                throw new NotImplementedException($"Unsupported texture target type: {target}");
            }
        }
コード例 #11
0
        public void Create(long key, byte[] data, GalImage image)
        {
            int handle = GL.GenTexture();

            TextureTarget target = ImageUtils.GetTextureTarget(image.TextureTarget);

            GL.BindTexture(target, handle);

            const int level  = 0; //TODO: Support mipmap textures.
            const int border = 0;

            _textureCache.AddOrUpdate(key, new ImageHandler(handle, image), (uint)data.Length);

            if (ImageUtils.IsCompressed(image.Format) && !IsAstc(image.Format))
            {
                InternalFormat internalFmt = OglEnumConverter.GetCompressedImageFormat(image.Format);

                switch (target)
                {
                case TextureTarget.Texture1D:
                    GL.CompressedTexImage1D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        border,
                        data.Length,
                        data);
                    break;

                case TextureTarget.Texture2D:
                    GL.CompressedTexImage2D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        border,
                        data.Length,
                        data);
                    break;

                case TextureTarget.Texture3D:
                    GL.CompressedTexImage3D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        image.Depth,
                        border,
                        data.Length,
                        data);
                    break;

                // Cube map arrays are just 2D texture arrays with 6 entries
                // per cube map so we can handle them in the same way
                case TextureTarget.TextureCubeMapArray:
                case TextureTarget.Texture2DArray:
                    GL.CompressedTexImage3D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        image.LayerCount,
                        border,
                        data.Length,
                        data);
                    break;

                case TextureTarget.TextureCubeMap:
                    Span <byte> array = new Span <byte>(data);

                    int faceSize = ImageUtils.GetSize(image) / 6;

                    for (int Face = 0; Face < 6; Face++)
                    {
                        GL.CompressedTexImage2D(
                            TextureTarget.TextureCubeMapPositiveX + Face,
                            level,
                            internalFmt,
                            image.Width,
                            image.Height,
                            border,
                            faceSize,
                            array.Slice(Face * faceSize, faceSize).ToArray());
                    }
                    break;

                default:
                    throw new NotImplementedException($"Unsupported texture target type: {target}");
                }
            }
            else
            {
                //TODO: Use KHR_texture_compression_astc_hdr when available
                if (IsAstc(image.Format))
                {
                    int textureBlockWidth  = ImageUtils.GetBlockWidth(image.Format);
                    int textureBlockHeight = ImageUtils.GetBlockHeight(image.Format);
                    int textureBlockDepth  = ImageUtils.GetBlockDepth(image.Format);

                    data = AstcDecoder.DecodeToRgba8888(
                        data,
                        textureBlockWidth,
                        textureBlockHeight,
                        textureBlockDepth,
                        image.Width,
                        image.Height,
                        image.Depth);

                    image.Format = GalImageFormat.Rgba8 | (image.Format & GalImageFormat.TypeMask);
                }

                (PixelInternalFormat internalFmt,
                 PixelFormat format,
                 PixelType type) = OglEnumConverter.GetImageFormat(image.Format);


                switch (target)
                {
                case TextureTarget.Texture1D:
                    GL.TexImage1D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        border,
                        format,
                        type,
                        data);
                    break;

                case TextureTarget.Texture2D:
                    GL.TexImage2D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        border,
                        format,
                        type,
                        data);
                    break;

                case TextureTarget.Texture3D:
                    GL.TexImage3D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        image.Depth,
                        border,
                        format,
                        type,
                        data);
                    break;

                // Cube map arrays are just 2D texture arrays with 6 entries
                // per cube map so we can handle them in the same way
                case TextureTarget.TextureCubeMapArray:
                case TextureTarget.Texture2DArray:
                    GL.TexImage3D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        image.LayerCount,
                        border,
                        format,
                        type,
                        data);
                    break;

                case TextureTarget.TextureCubeMap:
                    Span <byte> array = new Span <byte>(data);

                    int faceSize = ImageUtils.GetSize(image) / 6;

                    for (int face = 0; face < 6; face++)
                    {
                        GL.TexImage2D(
                            TextureTarget.TextureCubeMapPositiveX + face,
                            level,
                            internalFmt,
                            image.Width,
                            image.Height,
                            border,
                            format,
                            type,
                            array.Slice(face * faceSize, faceSize).ToArray());
                    }
                    break;

                default:
                    throw new NotImplementedException($"Unsupported texture target type: {target}");
                }
            }
        }
コード例 #12
0
        public void Bind(GalPipelineState New)
        {
            BindConstBuffers(New);

            BindVertexLayout(New);

            if (New.FramebufferSrgb != _old.FramebufferSrgb)
            {
                Enable(EnableCap.FramebufferSrgb, New.FramebufferSrgb);

                _renderTarget.FramebufferSrgb = New.FramebufferSrgb;
            }

            if (New.FlipX != _old.FlipX || New.FlipY != _old.FlipY || New.Instance != _old.Instance)
            {
                _shader.SetExtraData(New.FlipX, New.FlipY, New.Instance);
            }

            if (New.FrontFace != _old.FrontFace)
            {
                GL.FrontFace(OglEnumConverter.GetFrontFace(New.FrontFace));
            }

            if (New.CullFaceEnabled != _old.CullFaceEnabled)
            {
                Enable(EnableCap.CullFace, New.CullFaceEnabled);
            }

            if (New.CullFaceEnabled)
            {
                if (New.CullFace != _old.CullFace)
                {
                    GL.CullFace(OglEnumConverter.GetCullFace(New.CullFace));
                }
            }

            if (New.DepthTestEnabled != _old.DepthTestEnabled)
            {
                Enable(EnableCap.DepthTest, New.DepthTestEnabled);
            }

            if (New.DepthWriteEnabled != _old.DepthWriteEnabled)
            {
                GL.DepthMask(New.DepthWriteEnabled);
            }

            if (New.DepthTestEnabled)
            {
                if (New.DepthFunc != _old.DepthFunc)
                {
                    GL.DepthFunc(OglEnumConverter.GetDepthFunc(New.DepthFunc));
                }
            }

            if (New.DepthRangeNear != _old.DepthRangeNear ||
                New.DepthRangeFar != _old.DepthRangeFar)
            {
                GL.DepthRange(New.DepthRangeNear, New.DepthRangeFar);
            }

            if (New.StencilTestEnabled != _old.StencilTestEnabled)
            {
                Enable(EnableCap.StencilTest, New.StencilTestEnabled);
            }

            if (New.StencilTwoSideEnabled != _old.StencilTwoSideEnabled)
            {
                Enable((EnableCap)All.StencilTestTwoSideExt, New.StencilTwoSideEnabled);
            }

            if (New.StencilTestEnabled)
            {
                if (New.StencilBackFuncFunc != _old.StencilBackFuncFunc ||
                    New.StencilBackFuncRef != _old.StencilBackFuncRef ||
                    New.StencilBackFuncMask != _old.StencilBackFuncMask)
                {
                    GL.StencilFuncSeparate(
                        StencilFace.Back,
                        OglEnumConverter.GetStencilFunc(New.StencilBackFuncFunc),
                        New.StencilBackFuncRef,
                        New.StencilBackFuncMask);
                }

                if (New.StencilBackOpFail != _old.StencilBackOpFail ||
                    New.StencilBackOpZFail != _old.StencilBackOpZFail ||
                    New.StencilBackOpZPass != _old.StencilBackOpZPass)
                {
                    GL.StencilOpSeparate(
                        StencilFace.Back,
                        OglEnumConverter.GetStencilOp(New.StencilBackOpFail),
                        OglEnumConverter.GetStencilOp(New.StencilBackOpZFail),
                        OglEnumConverter.GetStencilOp(New.StencilBackOpZPass));
                }

                if (New.StencilBackMask != _old.StencilBackMask)
                {
                    GL.StencilMaskSeparate(StencilFace.Back, New.StencilBackMask);
                }

                if (New.StencilFrontFuncFunc != _old.StencilFrontFuncFunc ||
                    New.StencilFrontFuncRef != _old.StencilFrontFuncRef ||
                    New.StencilFrontFuncMask != _old.StencilFrontFuncMask)
                {
                    GL.StencilFuncSeparate(
                        StencilFace.Front,
                        OglEnumConverter.GetStencilFunc(New.StencilFrontFuncFunc),
                        New.StencilFrontFuncRef,
                        New.StencilFrontFuncMask);
                }

                if (New.StencilFrontOpFail != _old.StencilFrontOpFail ||
                    New.StencilFrontOpZFail != _old.StencilFrontOpZFail ||
                    New.StencilFrontOpZPass != _old.StencilFrontOpZPass)
                {
                    GL.StencilOpSeparate(
                        StencilFace.Front,
                        OglEnumConverter.GetStencilOp(New.StencilFrontOpFail),
                        OglEnumConverter.GetStencilOp(New.StencilFrontOpZFail),
                        OglEnumConverter.GetStencilOp(New.StencilFrontOpZPass));
                }

                if (New.StencilFrontMask != _old.StencilFrontMask)
                {
                    GL.StencilMaskSeparate(StencilFace.Front, New.StencilFrontMask);
                }
            }


            // Scissor Test
            // All scissor test are disabled before drawing final framebuffer to screen so we don't need to handle disabling
            // Skip if there are no scissor tests to enable
            if (New.ScissorTestCount != 0)
            {
                int  scissorsApplied = 0;
                bool applyToAll      = false;

                for (int index = 0; index < GalPipelineState.RenderTargetsCount; index++)
                {
                    if (New.ScissorTestEnabled[index])
                    {
                        // If viewport arrays are unavailable apply first scissor test to all or
                        // there is only 1 scissor test and it's the first, the scissor test applies to all viewports
                        if (!OglExtension.Required.ViewportArray || (index == 0 && New.ScissorTestCount == 1))
                        {
                            GL.Enable(EnableCap.ScissorTest);
                            applyToAll = true;
                        }
                        else
                        {
                            GL.Enable(IndexedEnableCap.ScissorTest, index);
                        }

                        if (New.ScissorTestEnabled[index] != _old.ScissorTestEnabled[index] ||
                            New.ScissorTestX[index] != _old.ScissorTestX[index] ||
                            New.ScissorTestY[index] != _old.ScissorTestY[index] ||
                            New.ScissorTestWidth[index] != _old.ScissorTestWidth[index] ||
                            New.ScissorTestHeight[index] != _old.ScissorTestHeight[index])
                        {
                            if (applyToAll)
                            {
                                GL.Scissor(New.ScissorTestX[index], New.ScissorTestY[index],
                                           New.ScissorTestWidth[index], New.ScissorTestHeight[index]);
                            }
                            else
                            {
                                GL.ScissorIndexed(index, New.ScissorTestX[index], New.ScissorTestY[index],
                                                  New.ScissorTestWidth[index], New.ScissorTestHeight[index]);
                            }
                        }

                        // If all scissor tests have been applied, or viewport arrays are unavailable we can skip remaining iterations
                        if (!OglExtension.Required.ViewportArray || ++scissorsApplied == New.ScissorTestCount)
                        {
                            break;
                        }
                    }
                }
            }


            if (New.BlendIndependent)
            {
                for (int index = 0; index < GalPipelineState.RenderTargetsCount; index++)
                {
                    SetBlendState(index, New.Blends[index], _old.Blends[index]);
                }
            }
            else
            {
                if (New.BlendIndependent != _old.BlendIndependent)
                {
                    SetAllBlendState(New.Blends[0]);
                }
                else
                {
                    SetBlendState(New.Blends[0], _old.Blends[0]);
                }
            }

            if (New.ColorMaskCommon)
            {
                if (New.ColorMaskCommon != _old.ColorMaskCommon || !New.ColorMasks[0].Equals(_old.ColorMasks[0]))
                {
                    GL.ColorMask(
                        New.ColorMasks[0].Red,
                        New.ColorMasks[0].Green,
                        New.ColorMasks[0].Blue,
                        New.ColorMasks[0].Alpha);
                }
            }
            else
            {
                for (int index = 0; index < GalPipelineState.RenderTargetsCount; index++)
                {
                    if (!New.ColorMasks[index].Equals(_old.ColorMasks[index]))
                    {
                        GL.ColorMask(
                            index,
                            New.ColorMasks[index].Red,
                            New.ColorMasks[index].Green,
                            New.ColorMasks[index].Blue,
                            New.ColorMasks[index].Alpha);
                    }
                }
            }

            if (New.PrimitiveRestartEnabled != _old.PrimitiveRestartEnabled)
            {
                Enable(EnableCap.PrimitiveRestart, New.PrimitiveRestartEnabled);
            }

            if (New.PrimitiveRestartEnabled)
            {
                if (New.PrimitiveRestartIndex != _old.PrimitiveRestartIndex)
                {
                    GL.PrimitiveRestartIndex(New.PrimitiveRestartIndex);
                }
            }

            _old = New;
        }