Skip to content

Commit b1d86ae

Browse files
authored
replace GCHandle for short-term pinning with fixed statements (#9365)
1 parent 6110f47 commit b1d86ae

File tree

4 files changed

+69
-92
lines changed

4 files changed

+69
-92
lines changed

src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Geometry.cs

Lines changed: 39 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -679,65 +679,62 @@ public virtual PathGeometry GetWidenedPathGeometry(Pen pen, double tolerance, To
679679
unsafe
680680
{
681681
MIL_PEN_DATA penData;
682-
double[] dashArray = null;
683682

684-
pen.GetBasicPenData(&penData, out dashArray);
683+
pen.GetBasicPenData(&penData, out double[] dashArray);
685684

686-
fixed (byte *pbPathData = pathData.SerializedData)
685+
fixed (byte* pbPathData = pathData.SerializedData)
687686
{
688687
Debug.Assert(pbPathData != (byte*)0);
689688

690689
FillRule fillRule = FillRule.Nonzero;
690+
PathGeometry.FigureList list = new();
691691

692-
PathGeometry.FigureList list = new PathGeometry.FigureList();
693-
694-
// The handle to the pDashArray, if we have one.
695-
// Since the dash array is optional, we may not need to Free it.
696-
GCHandle handle = new GCHandle();
697-
698-
// Pin the pDashArray, if we have one.
699-
if (dashArray != null)
692+
int hr; //If we don't have dashArray, we call without it (its optional)
693+
if (dashArray is null)
700694
{
701-
handle = GCHandle.Alloc(dashArray, GCHandleType.Pinned);
695+
hr = UnsafeNativeMethods.MilCoreApi.MilUtility_PathGeometryWiden(&penData,
696+
null,
697+
&pathData.Matrix,
698+
pathData.FillRule,
699+
pbPathData,
700+
pathData.Size,
701+
tolerance,
702+
type == ToleranceType.Relative,
703+
new PathGeometry.AddFigureToListDelegate(list.AddFigureToList),
704+
out fillRule);
702705
}
703-
704-
try
706+
else // Pin the dashArray and use it, if we have one.
705707
{
706-
int hr = UnsafeNativeMethods.MilCoreApi.MilUtility_PathGeometryWiden(
707-
&penData,
708-
(dashArray == null) ? null : (double*)handle.AddrOfPinnedObject(),
709-
&pathData.Matrix,
710-
pathData.FillRule,
711-
pbPathData,
712-
pathData.Size,
713-
tolerance,
714-
type == ToleranceType.Relative,
715-
new PathGeometry.AddFigureToListDelegate(list.AddFigureToList),
716-
out fillRule);
717-
718-
if (hr == (int)MILErrors.WGXERR_BADNUMBER)
708+
fixed (double* ptrDashArray = dashArray)
719709
{
720-
// When we encounter NaNs in the renderer, we absorb the error and draw
721-
// nothing. To be consistent, we return an empty geometry.
722-
resultGeometry = new PathGeometry();
710+
hr = UnsafeNativeMethods.MilCoreApi.MilUtility_PathGeometryWiden(&penData,
711+
ptrDashArray,
712+
&pathData.Matrix,
713+
pathData.FillRule,
714+
pbPathData,
715+
pathData.Size,
716+
tolerance,
717+
type == ToleranceType.Relative,
718+
new PathGeometry.AddFigureToListDelegate(list.AddFigureToList),
719+
out fillRule);
723720
}
724-
else
725-
{
726-
HRESULT.Check(hr);
721+
}
727722

728-
resultGeometry = new PathGeometry(list.Figures, fillRule, null);
729-
}
723+
if (hr == (int)MILErrors.WGXERR_BADNUMBER)
724+
{
725+
// When we encounter NaNs in the renderer, we absorb the error and draw
726+
// nothing. To be consistent, we return an empty geometry.
727+
resultGeometry = new PathGeometry();
730728
}
731-
finally
729+
else
732730
{
733-
if (handle.IsAllocated)
734-
{
735-
handle.Free();
736-
}
731+
HRESULT.Check(hr);
732+
733+
resultGeometry = new PathGeometry(list.Figures, fillRule, null);
737734
}
738-
}
739735

740-
return resultGeometry;
736+
return resultGeometry;
737+
}
741738
}
742739
}
743740

src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Imaging/PropVariant.cs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ internal void InitVector(Array array, Type type, VarEnum varEnum)
122122

123123
internal void Init(Array array, Type type, VarEnum vt)
124124
{
125-
varType = (ushort) vt;
125+
varType = (ushort)vt;
126126
ca.cElems = 0;
127127
ca.pElems = IntPtr.Zero;
128128

@@ -131,17 +131,16 @@ internal void Init(Array array, Type type, VarEnum vt)
131131
if (length > 0)
132132
{
133133
long size = Marshal.SizeOf(type) * length;
134-
135-
IntPtr destPtr =IntPtr.Zero;
136-
GCHandle handle = new GCHandle();
134+
IntPtr destPtr = IntPtr.Zero;
137135

138136
try
139137
{
140-
destPtr = Marshal.AllocCoTaskMem((int) size);
141-
handle = GCHandle.Alloc(array, GCHandleType.Pinned);
138+
destPtr = Marshal.AllocCoTaskMem((int)size);
139+
142140
unsafe
143141
{
144-
CopyBytes((byte *) destPtr, (int)size, (byte *)handle.AddrOfPinnedObject(), (int)size);
142+
fixed (byte* sourcePtr = &MemoryMarshal.GetArrayDataReference(array))
143+
CopyBytes((byte*)destPtr, (int)size, sourcePtr, (int)size);
145144
}
146145

147146
ca.cElems = (uint)length;
@@ -151,11 +150,6 @@ internal void Init(Array array, Type type, VarEnum vt)
151150
}
152151
finally
153152
{
154-
if (handle.IsAllocated)
155-
{
156-
handle.Free();
157-
}
158-
159153
if (destPtr != IntPtr.Zero)
160154
{
161155
Marshal.FreeCoTaskMem(destPtr);

src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Imaging/WriteableBitmap.cs

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -397,24 +397,16 @@ int destinationY
397397
}
398398

399399
// Get the address of the data in the array by pinning it.
400-
GCHandle arrayHandle = GCHandle.Alloc(sourceBuffer, GCHandleType.Pinned);
401-
try
400+
unsafe
402401
{
403-
unsafe
404-
{
405-
IntPtr buffer = arrayHandle.AddrOfPinnedObject();
402+
fixed (byte* buffer = &MemoryMarshal.GetArrayDataReference(sourceBuffer))
406403
WritePixelsImpl(sourceRect,
407-
buffer,
404+
(nint)buffer,
408405
sourceBufferSize,
409406
sourceBufferStride,
410407
destinationX,
411408
destinationY,
412409
/*backwardsCompat*/ false);
413-
}
414-
}
415-
finally
416-
{
417-
arrayHandle.Free();
418410
}
419411
}
420412

@@ -532,28 +524,25 @@ int offset
532524
sourceRect.Y = 0;
533525

534526
// Get the address of the data in the array by pinning it.
535-
GCHandle arrayHandle = GCHandle.Alloc(pixels, GCHandleType.Pinned);
536-
try
527+
unsafe
537528
{
538-
IntPtr buffer = arrayHandle.AddrOfPinnedObject();
539-
540-
checked
529+
fixed (byte* buffer = &MemoryMarshal.GetArrayDataReference(pixels))
541530
{
542-
buffer = new IntPtr(((long) buffer) + (long) offsetInBytes);
543-
sourceBufferSize -= offsetInBytes;
531+
nint adjustedBuffer;
532+
checked
533+
{
534+
adjustedBuffer = new IntPtr(((long)buffer) + (long)offsetInBytes);
535+
sourceBufferSize -= offsetInBytes;
536+
}
537+
538+
WritePixelsImpl(sourceRect,
539+
adjustedBuffer,
540+
sourceBufferSize,
541+
stride,
542+
destinationX,
543+
destinationY,
544+
/*backwardsCompat*/ true);
544545
}
545-
546-
WritePixelsImpl(sourceRect,
547-
buffer,
548-
sourceBufferSize,
549-
stride,
550-
destinationX,
551-
destinationY,
552-
/*backwardsCompat*/ true);
553-
}
554-
finally
555-
{
556-
arrayHandle.Free();
557546
}
558547
}
559548
}

src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/WindowsRuntime/Generated/WinRT/Marshalers.cs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -314,15 +314,12 @@ public static unsafe (int length, IntPtr data) FromManagedArray(Array array)
314314
public static unsafe void CopyManagedArray(Array array, IntPtr data)
315315
{
316316
if (array is null)
317-
{
318317
return;
319-
}
320-
var length = array.Length;
321-
var byte_length = length * Marshal.SizeOf<T>();
322-
var array_handle = GCHandle.Alloc(array, GCHandleType.Pinned);
323-
var array_data = array_handle.AddrOfPinnedObject();
324-
Buffer.MemoryCopy(array_data.ToPointer(), data.ToPointer(), byte_length, byte_length);
325-
array_handle.Free();
318+
319+
int byte_length = array.Length * Marshal.SizeOf<T>();
320+
321+
fixed (void* array_data = &MemoryMarshal.GetArrayDataReference(array))
322+
Buffer.MemoryCopy(array_data, data.ToPointer(), byte_length, byte_length);
326323
}
327324

328325
public static void DisposeMarshalerArray(object box)

0 commit comments

Comments
 (0)