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); }
/// <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..];