Example #1
0
        private static VectorFormat AddVectorFormat(SurfaceFormat surfaceFormat, params Type[] vectorTypes)
        {
            var vectorInfos  = vectorTypes.Select(x => VectorType.Get(x));
            var vectorFormat = new VectorFormat(surfaceFormat, vectorInfos);

            if (!VectorFormatBySurface.TryGetValue(surfaceFormat, out var bySurfaceSet))
            {
                bySurfaceSet = new HashSet <VectorFormat>();
                VectorFormatBySurface.TryAdd(surfaceFormat, bySurfaceSet);
                VectorFormatBySurfaceRO.TryAdd(surfaceFormat, bySurfaceSet.AsReadOnly());
            }
            bySurfaceSet.Add(vectorFormat);

            foreach (var vectorType in vectorTypes)
            {
                if (!VectorFormatsByType.TryGetValue(vectorType, out var byTypeSet))
                {
                    byTypeSet = new HashSet <VectorFormat>();
                    VectorFormatsByType.TryAdd(vectorType, byTypeSet);
                    VectorFormatsByTypeRO.TryAdd(vectorType, byTypeSet.AsReadOnly());
                }
                byTypeSet.Add(vectorFormat);
            }

            return(vectorFormat);
        }
Example #2
0
        /// <summary>
        /// Changes the pixels of the texture.
        /// </summary>
        /// <remarks>
        /// Pixel data is converted to the texture format.
        /// </remarks>
        /// <param name="image">New data for the texture.</param>
        /// <param name="rectangle">Area to modify; defaults to texture bounds.</param>
        /// <param name="level">Layer of the texture to modify.</param>
        /// <param name="arraySlice">Index inside the texture array.</param>
        /// <exception cref="ArgumentException">
        ///  <paramref name="arraySlice"/> is greater than 0 and the graphics device does not support texture arrays.
        /// </exception>
        public void SetData(
            Image image,
            Rectangle?rectangle = null,
            int level           = 0,
            int arraySlice      = 0)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            VectorType srcVectorType = image.PixelType;

            ValidateParams(
                Format.GetSize(), srcVectorType.Type.Name, level, arraySlice, rectangle,
                image.Width * image.Height, out Rectangle checkedRect);

            VectorFormat dstVectorFormat             = GetVectorFormat(Format);
            ReadOnlySpan <VectorType> dstVectorTypes = dstVectorFormat.VectorTypes.Span;

            foreach (VectorType vectorType in dstVectorTypes)
            {
                if (srcVectorType == vectorType)
                {
                    int rowStride = checkedRect.Width * vectorType.ElementSize;
                    if (image.ByteStride == rowStride)
                    {
                        SetData(image.GetPixelByteSpan(), checkedRect, level, arraySlice);
                    }
                    else
                    {
                        for (int y = 0; y < checkedRect.Height; y++)
                        {
                            Span <byte> row = image.GetPixelByteRowSpan(y).Slice(0, rowStride);

                            var textureRect = new Rectangle(
                                checkedRect.X,
                                checkedRect.Y + y,
                                checkedRect.Width,
                                height: 1);

                            SetData(row, textureRect, level, arraySlice);
                        }
                    }
                    return;
                }
            }

            Span <byte> buffer         = stackalloc byte[4096];
            VectorType  dstVectorType  = dstVectorTypes[0];
            int         bufferCapacity = buffer.Length / dstVectorType.ElementSize;
            int         srcRowStride   = checkedRect.Width * srcVectorType.ElementSize;
            var         convertPixels  = Image.GetConvertPixelsDelegate(srcVectorType, dstVectorType);

            for (int y = 0; y < checkedRect.Height; y++)
            {
                Span <byte> vectorRow = image.GetPixelByteRowSpan(y).Slice(0, srcRowStride);
                int         offsetX   = 0;
                do
                {
                    int         sliceWidth = checkedRect.Width - offsetX;
                    int         count      = sliceWidth > bufferCapacity ? bufferCapacity : sliceWidth;
                    Span <byte> srcSlice   = vectorRow.Slice(0, count * srcVectorType.ElementSize);
                    Span <byte> dstSlice   = buffer.Slice(0, count * dstVectorType.ElementSize);

                    convertPixels.Invoke(srcSlice, dstSlice);

                    Rectangle textureRect = new(
                        checkedRect.X + offsetX,
                        checkedRect.Y + y,
                        width : count,
                        height : 1);

                    SetData(dstSlice, textureRect, level, arraySlice);

                    vectorRow = vectorRow[srcSlice.Length..];