diff --git a/CefSharp.Wpf/CefSharp.Wpf.csproj b/CefSharp.Wpf/CefSharp.Wpf.csproj index f71f07899f..aad2fda87e 100644 --- a/CefSharp.Wpf/CefSharp.Wpf.csproj +++ b/CefSharp.Wpf/CefSharp.Wpf.csproj @@ -96,6 +96,7 @@ + diff --git a/CefSharp.Wpf/Rendering/AbstractRenderHandler.cs b/CefSharp.Wpf/Rendering/AbstractRenderHandler.cs new file mode 100644 index 0000000000..f7b2985133 --- /dev/null +++ b/CefSharp.Wpf/Rendering/AbstractRenderHandler.cs @@ -0,0 +1,143 @@ +// Copyright © 2019 The CefSharp Authors. All rights reserved. +// +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. + +using System; +using System.IO.MemoryMappedFiles; +using System.Runtime.InteropServices; +using System.Threading; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Threading; +using Rect = CefSharp.Structs.Rect; + +namespace CefSharp.Wpf.Rendering +{ + /// + /// Implements the basics of a + /// + /// + public abstract class AbstractRenderHandler : IDisposable, IRenderHandler + { + [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)] + protected static extern void CopyMemory(IntPtr dest, IntPtr src, uint count); + + protected static readonly PixelFormat PixelFormat = PixelFormats.Pbgra32; + protected static int BytesPerPixel = PixelFormat.BitsPerPixel / 8; + + protected object lockObject = new object(); + + protected Size viewSize; + protected Size popupSize; + protected DispatcherPriority dispatcherPriority; + + protected MemoryMappedFile viewMemoryMappedFile; + protected MemoryMappedFile popupMemoryMappedFile; + protected MemoryMappedViewAccessor viewMemoryMappedViewAccessor; + protected MemoryMappedViewAccessor popupMemoryMappedViewAccessor; + + /// + /// The value for disposal, if it's 1 (one) then this instance is either disposed + /// or in the process of getting disposed + /// + private int disposeSignaled; + + /// + /// Gets a value indicating whether this instance is disposed. + /// + /// if this instance is disposed; otherwise, . + public bool IsDisposed + { + get + { + return Interlocked.CompareExchange(ref disposeSignaled, 1, 1) == 1; + } + } + + /// + /// Releases all resources used by the object + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases unmanaged and - optionally - managed resources for the + /// + /// to release both managed and unmanaged resources; to release only unmanaged resources. + protected virtual void Dispose(bool disposing) + { + if (Interlocked.CompareExchange(ref disposeSignaled, 1, 0) != 0) + { + return; + } + + if (!disposing) + { + return; + } + + ReleaseMemoryMappedView(ref popupMemoryMappedFile, ref popupMemoryMappedViewAccessor); + ReleaseMemoryMappedView(ref viewMemoryMappedFile, ref viewMemoryMappedViewAccessor); + } + + protected void ReleaseMemoryMappedView(ref MemoryMappedFile mappedFile, ref MemoryMappedViewAccessor stream) + { + if (stream != null) + { + stream.Dispose(); + stream = null; + } + + if (mappedFile != null) + { + mappedFile.Dispose(); + mappedFile = null; + } + } + + /// + /// Called when an element has been rendered to the shared texture handle. + /// This method is only called when is set to true + /// + /// indicates whether the element is the view or the popup widget. + /// contains the set of rectangles in pixel coordinates that need to be repainted + /// is the handle for a D3D11 Texture2D that can be accessed via ID3D11Device using the OpenSharedResource method. + public virtual void OnAcceleratedPaint(bool isPopup, Rect dirtyRect, IntPtr sharedHandle) + { + // NOT USED + } + + /// + /// Called when an element should be painted. (Invoked from CefRenderHandler.OnPaint) + /// This method is only called when is set to false. + /// + /// indicates whether the element is the view or the popup widget. + /// contains the set of rectangles in pixel coordinates that need to be repainted + /// The bitmap will be will be width * height *4 bytes in size and represents a BGRA image with an upper-left origin + /// width + /// height + /// image used as parent for rendered bitmap + public virtual void OnPaint(bool isPopup, Rect dirtyRect, IntPtr buffer, int width, int height, Image image) + { + if (image.Dispatcher.HasShutdownStarted) + { + return; + } + + if (isPopup) + { + CreateOrUpdateBitmap(isPopup, dirtyRect, buffer, width, height, image, ref popupSize, ref popupMemoryMappedFile, ref popupMemoryMappedViewAccessor); + } + else + { + CreateOrUpdateBitmap(isPopup, dirtyRect, buffer, width, height, image, ref viewSize, ref viewMemoryMappedFile, ref viewMemoryMappedViewAccessor); + } + } + + protected abstract void CreateOrUpdateBitmap(bool isPopup, Rect dirtyRect, IntPtr buffer, int width, int height, Image image, ref Size currentSize, ref MemoryMappedFile mappedFile, ref MemoryMappedViewAccessor viewAccessor); + } +} diff --git a/CefSharp.Wpf/Rendering/Experimental/ByteArrayWritableBitmapRenderHandler.cs b/CefSharp.Wpf/Rendering/Experimental/ByteArrayWritableBitmapRenderHandler.cs index 7df73e060a..2d84ce5300 100644 --- a/CefSharp.Wpf/Rendering/Experimental/ByteArrayWritableBitmapRenderHandler.cs +++ b/CefSharp.Wpf/Rendering/Experimental/ByteArrayWritableBitmapRenderHandler.cs @@ -3,13 +3,12 @@ // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. using System; +using System.IO.MemoryMappedFiles; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Controls; -using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Threading; - using Rect = CefSharp.Structs.Rect; namespace CefSharp.Wpf.Rendering.Experimental @@ -21,18 +20,11 @@ namespace CefSharp.Wpf.Rendering.Experimental /// wise. /// /// - public class ByteArrayWritableBitmapRenderHandler : IRenderHandler + public class ByteArrayWritableBitmapRenderHandler : AbstractRenderHandler { - /// - /// The pixel format - /// - private static readonly PixelFormat PixelFormat = PixelFormats.Prgba64; - private static int BytesPerPixel = PixelFormat.BitsPerPixel / 8; - private double dpiX; private double dpiY; private bool invalidateDirtyRect; - private DispatcherPriority dispatcherPriority; /// /// Initializes a new instance of the class. @@ -49,25 +41,8 @@ public ByteArrayWritableBitmapRenderHandler(double dpiX, double dpiY, bool inval this.dispatcherPriority = dispatcherPriority; } - /// - /// Called when an element has been rendered to the shared texture handle. - /// This method is only called when is set to true - /// - /// indicates whether the element is the view or the popup widget. - /// contains the set of rectangles in pixel coordinates that need to be repainted - /// is the handle for a D3D11 Texture2D that can be accessed via ID3D11Device using the OpenSharedResource method. - void IRenderHandler.OnAcceleratedPaint(bool isPopup, Rect dirtyRect, IntPtr sharedHandle) + protected override void CreateOrUpdateBitmap(bool isPopup, Rect dirtyRect, IntPtr buffer, int width, int height, Image image, ref Size currentSize, ref MemoryMappedFile mappedFile, ref MemoryMappedViewAccessor viewAccessor) { - //NOT USED - } - - void IRenderHandler.OnPaint(bool isPopup, Rect dirtyRect, IntPtr buffer, int width, int height, Image image) - { - if (image.Dispatcher.HasShutdownStarted) - { - return; - } - int pixels = width * height; int numberOfBytes = pixels * BytesPerPixel; var stride = width * BytesPerPixel; @@ -117,10 +92,5 @@ void IRenderHandler.OnPaint(bool isPopup, Rect dirtyRect, IntPtr buffer, int wid } }), dispatcherPriority); } - - void IDisposable.Dispose() - { - - } } } diff --git a/CefSharp.Wpf/Rendering/Experimental/IncreaseBufferInteropRenderHandler.cs b/CefSharp.Wpf/Rendering/Experimental/IncreaseBufferInteropRenderHandler.cs index 46f18a319b..d5bcab284d 100644 --- a/CefSharp.Wpf/Rendering/Experimental/IncreaseBufferInteropRenderHandler.cs +++ b/CefSharp.Wpf/Rendering/Experimental/IncreaseBufferInteropRenderHandler.cs @@ -4,11 +4,9 @@ using System; using System.IO.MemoryMappedFiles; -using System.Runtime.InteropServices; using System.Windows; using System.Windows.Controls; using System.Windows.Interop; -using System.Windows.Media; using System.Windows.Threading; using Rect = CefSharp.Structs.Rect; @@ -20,28 +18,8 @@ namespace CefSharp.Wpf.Rendering.Experimental /// when the size increases /// /// - public class IncreaseBufferInteropRenderHandler : IRenderHandler + public class IncreaseBufferInteropRenderHandler : AbstractRenderHandler { - [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)] - private static extern void CopyMemory(IntPtr dest, IntPtr src, uint count); - - /// - /// The pixel format - /// - private static readonly PixelFormat PixelFormat = PixelFormats.Pbgra32; - private static int BytesPerPixel = PixelFormat.BitsPerPixel / 8; - - private object lockObject = new object(); - - private Size viewSize; - private Size popupSize; - private DispatcherPriority dispatcherPriority; - - private MemoryMappedFile viewMemoryMappedFile; - private MemoryMappedFile popupMemoryMappedFile; - private MemoryMappedViewAccessor viewMemoryMappedViewAccessor; - private MemoryMappedViewAccessor popupMemoryMappedViewAccessor; - /// /// Initializes a new instance of the class. /// @@ -51,46 +29,8 @@ public IncreaseBufferInteropRenderHandler(DispatcherPriority dispatcherPriority this.dispatcherPriority = dispatcherPriority; } - /// - /// Dispose - /// - public void Dispose() - { - ReleaseMemoryMappedView(ref popupMemoryMappedFile, ref popupMemoryMappedViewAccessor); - ReleaseMemoryMappedView(ref viewMemoryMappedFile, ref viewMemoryMappedViewAccessor); - } - - /// - /// Called when an element has been rendered to the shared texture handle. - /// This method is only called when is set to true - /// - /// indicates whether the element is the view or the popup widget. - /// contains the set of rectangles in pixel coordinates that need to be repainted - /// is the handle for a D3D11 Texture2D that can be accessed via ID3D11Device using the OpenSharedResource method. - void IRenderHandler.OnAcceleratedPaint(bool isPopup, Rect dirtyRect, IntPtr sharedHandle) - { - //NOT USED - } - - void IRenderHandler.OnPaint(bool isPopup, Rect dirtyRect, IntPtr buffer, int width, int height, Image image) - { - if (isPopup) - { - CreateOrUpdateBitmap(isPopup, dirtyRect, buffer, width, height, image, ref popupSize, ref popupMemoryMappedFile, ref popupMemoryMappedViewAccessor); - } - else - { - CreateOrUpdateBitmap(isPopup, dirtyRect, buffer, width, height, image, ref viewSize, ref viewMemoryMappedFile, ref viewMemoryMappedViewAccessor); - } - } - - private void CreateOrUpdateBitmap(bool isPopup, Rect dirtyRect, IntPtr buffer, int width, int height, Image image, ref Size currentSize, ref MemoryMappedFile mappedFile, ref MemoryMappedViewAccessor viewAccessor) + protected override void CreateOrUpdateBitmap(bool isPopup, Rect dirtyRect, IntPtr buffer, int width, int height, Image image, ref Size currentSize, ref MemoryMappedFile mappedFile, ref MemoryMappedViewAccessor viewAccessor) { - if (image.Dispatcher.HasShutdownStarted) - { - return; - } - var createNewBitmap = false; lock (lockObject) @@ -146,33 +86,15 @@ private void CreateOrUpdateBitmap(bool isPopup, Rect dirtyRect, IntPtr buffer, i var bitmap = (InteropBitmap)Imaging.CreateBitmapSourceFromMemorySection(backBufferHandle.DangerousGetHandle(), width, height, PixelFormat, stride, 0); image.Source = bitmap; } - else + else if (image.Source != null) { - if (image.Source != null) - { - var sourceRect = new Int32Rect(dirtyRect.X, dirtyRect.Y, dirtyRect.Width, dirtyRect.Height); - var bitmap = (InteropBitmap)image.Source; - bitmap.Invalidate(sourceRect); - } + var sourceRect = new Int32Rect(dirtyRect.X, dirtyRect.Y, dirtyRect.Width, dirtyRect.Height); + var bitmap = (InteropBitmap)image.Source; + bitmap.Invalidate(sourceRect); } } }), dispatcherPriority); } } - - private void ReleaseMemoryMappedView(ref MemoryMappedFile mappedFile, ref MemoryMappedViewAccessor stream) - { - if (stream != null) - { - stream.Dispose(); - stream = null; - } - - if (mappedFile != null) - { - mappedFile.Dispose(); - mappedFile = null; - } - } } } diff --git a/CefSharp.Wpf/Rendering/InteropBitmapRenderHandler.cs b/CefSharp.Wpf/Rendering/InteropBitmapRenderHandler.cs index cef266207c..c6fbbd3d00 100644 --- a/CefSharp.Wpf/Rendering/InteropBitmapRenderHandler.cs +++ b/CefSharp.Wpf/Rendering/InteropBitmapRenderHandler.cs @@ -4,11 +4,9 @@ using System; using System.IO.MemoryMappedFiles; -using System.Runtime.InteropServices; using System.Windows; using System.Windows.Controls; using System.Windows.Interop; -using System.Windows.Media; using System.Windows.Threading; using Rect = CefSharp.Structs.Rect; @@ -20,28 +18,8 @@ namespace CefSharp.Wpf.Rendering /// or creates a new InteropBitmap when required /// /// - public class InteropBitmapRenderHandler : IRenderHandler + public class InteropBitmapRenderHandler : AbstractRenderHandler { - [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)] - private static extern void CopyMemory(IntPtr dest, IntPtr src, uint count); - - /// - /// The pixel format - /// - private static readonly PixelFormat PixelFormat = PixelFormats.Pbgra32; - private static int BytesPerPixel = PixelFormat.BitsPerPixel / 8; - - private object lockObject = new object(); - - private Size viewSize; - private Size popupSize; - private DispatcherPriority dispatcherPriority; - - private MemoryMappedFile viewMemoryMappedFile; - private MemoryMappedFile popupMemoryMappedFile; - private MemoryMappedViewAccessor viewMemoryMappedViewAccessor; - private MemoryMappedViewAccessor popupMemoryMappedViewAccessor; - /// /// Initializes a new instance of the class. /// @@ -51,46 +29,8 @@ public InteropBitmapRenderHandler(DispatcherPriority dispatcherPriority = Dispat this.dispatcherPriority = dispatcherPriority; } - /// - /// Dispose - /// - public void Dispose() - { - ReleaseMemoryMappedView(ref popupMemoryMappedFile, ref popupMemoryMappedViewAccessor); - ReleaseMemoryMappedView(ref viewMemoryMappedFile, ref viewMemoryMappedViewAccessor); - } - - /// - /// Called when an element has been rendered to the shared texture handle. - /// This method is only called when is set to true - /// - /// indicates whether the element is the view or the popup widget. - /// contains the set of rectangles in pixel coordinates that need to be repainted - /// is the handle for a D3D11 Texture2D that can be accessed via ID3D11Device using the OpenSharedResource method. - void IRenderHandler.OnAcceleratedPaint(bool isPopup, Rect dirtyRect, IntPtr sharedHandle) - { - //NOT USED - } - - void IRenderHandler.OnPaint(bool isPopup, Rect dirtyRect, IntPtr buffer, int width, int height, Image image) - { - if (isPopup) - { - CreateOrUpdateBitmap(isPopup, dirtyRect, buffer, width, height, image, ref popupSize, ref popupMemoryMappedFile, ref popupMemoryMappedViewAccessor); - } - else - { - CreateOrUpdateBitmap(isPopup, dirtyRect, buffer, width, height, image, ref viewSize, ref viewMemoryMappedFile, ref viewMemoryMappedViewAccessor); - } - } - - private void CreateOrUpdateBitmap(bool isPopup, Rect dirtyRect, IntPtr buffer, int width, int height, Image image, ref Size currentSize, ref MemoryMappedFile mappedFile, ref MemoryMappedViewAccessor viewAccessor) + protected override void CreateOrUpdateBitmap(bool isPopup, Rect dirtyRect, IntPtr buffer, int width, int height, Image image, ref Size currentSize, ref MemoryMappedFile mappedFile, ref MemoryMappedViewAccessor viewAccessor) { - if (image.Dispatcher.HasShutdownStarted) - { - return; - } - var createNewBitmap = false; lock (lockObject) @@ -142,33 +82,15 @@ private void CreateOrUpdateBitmap(bool isPopup, Rect dirtyRect, IntPtr buffer, i var bitmap = (InteropBitmap)Imaging.CreateBitmapSourceFromMemorySection(backBufferHandle.DangerousGetHandle(), width, height, PixelFormat, stride, 0); image.Source = bitmap; } - else + else if (image.Source != null) { - if (image.Source != null) - { - var sourceRect = new Int32Rect(dirtyRect.X, dirtyRect.Y, dirtyRect.Width, dirtyRect.Height); - var bitmap = (InteropBitmap)image.Source; - bitmap.Invalidate(sourceRect); - } + var sourceRect = new Int32Rect(dirtyRect.X, dirtyRect.Y, dirtyRect.Width, dirtyRect.Height); + var bitmap = (InteropBitmap)image.Source; + bitmap.Invalidate(sourceRect); } } }), dispatcherPriority); } } - - private void ReleaseMemoryMappedView(ref MemoryMappedFile mappedFile, ref MemoryMappedViewAccessor stream) - { - if (stream != null) - { - stream.Dispose(); - stream = null; - } - - if (mappedFile != null) - { - mappedFile.Dispose(); - mappedFile = null; - } - } } } diff --git a/CefSharp.Wpf/Rendering/WritableBitmapRenderHandler.cs b/CefSharp.Wpf/Rendering/WritableBitmapRenderHandler.cs index 5b7eef343c..b300d3fd06 100644 --- a/CefSharp.Wpf/Rendering/WritableBitmapRenderHandler.cs +++ b/CefSharp.Wpf/Rendering/WritableBitmapRenderHandler.cs @@ -4,13 +4,10 @@ using System; using System.IO.MemoryMappedFiles; -using System.Runtime.InteropServices; using System.Windows; using System.Windows.Controls; -using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Threading; - using Rect = CefSharp.Structs.Rect; namespace CefSharp.Wpf.Rendering @@ -21,30 +18,11 @@ namespace CefSharp.Wpf.Rendering /// or creates a new WritableBitmap when required /// /// - public class WritableBitmapRenderHandler : IRenderHandler + public class WritableBitmapRenderHandler : AbstractRenderHandler { - [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)] - private static extern void CopyMemory(IntPtr dest, IntPtr src, uint count); - - /// - /// The pixel format - /// - private static readonly PixelFormat PixelFormat = PixelFormats.Pbgra32; - private static int BytesPerPixel = PixelFormat.BitsPerPixel / 8; - - private object lockObject = new object(); - - private Size viewSize; - private Size popupSize; private double dpiX; private double dpiY; private bool invalidateDirtyRect; - private DispatcherPriority dispatcherPriority; - - private MemoryMappedFile viewMemoryMappedFile; - private MemoryMappedFile popupMemoryMappedFile; - private MemoryMappedViewAccessor viewMemoryMappedViewAccessor; - private MemoryMappedViewAccessor popupMemoryMappedViewAccessor; /// /// Initializes a new instance of the class. @@ -61,51 +39,12 @@ public WritableBitmapRenderHandler(double dpiX, double dpiY, bool invalidateDirt this.dispatcherPriority = dispatcherPriority; } - /// - /// Dispose - /// - public void Dispose() - { - ReleaseMemoryMappedView(ref popupMemoryMappedFile, ref popupMemoryMappedViewAccessor); - ReleaseMemoryMappedView(ref viewMemoryMappedFile, ref viewMemoryMappedViewAccessor); - } - - /// - /// Called when an element has been rendered to the shared texture handle. - /// This method is only called when is set to true - /// - /// indicates whether the element is the view or the popup widget. - /// contains the set of rectangles in pixel coordinates that need to be repainted - /// is the handle for a D3D11 Texture2D that can be accessed via ID3D11Device using the OpenSharedResource method. - void IRenderHandler.OnAcceleratedPaint(bool isPopup, Rect dirtyRect, IntPtr sharedHandle) - { - //NOT USED - } - - void IRenderHandler.OnPaint(bool isPopup, Rect dirtyRect, IntPtr buffer, int width, int height, Image image) - { - if (isPopup) - { - CreateOrUpdateBitmap(isPopup, dirtyRect, buffer, width, height, image, ref popupSize, ref popupMemoryMappedFile, ref popupMemoryMappedViewAccessor); - } - else - { - CreateOrUpdateBitmap(isPopup, dirtyRect, buffer, width, height, image, ref viewSize, ref viewMemoryMappedFile, ref viewMemoryMappedViewAccessor); - } - } - - private void CreateOrUpdateBitmap(bool isPopup, Rect dirtyRect, IntPtr buffer, int width, int height, Image image, ref Size currentSize, ref MemoryMappedFile mappedFile, ref MemoryMappedViewAccessor viewAccessor) + protected override void CreateOrUpdateBitmap(bool isPopup, Rect dirtyRect, IntPtr buffer, int width, int height, Image image, ref Size currentSize, ref MemoryMappedFile mappedFile, ref MemoryMappedViewAccessor viewAccessor) { bool createNewBitmap = false; - if (image.Dispatcher.HasShutdownStarted) - { - return; - } - lock (lockObject) { - int pixels = width * height; int numberOfBytes = pixels * BytesPerPixel; @@ -181,20 +120,5 @@ private void CreateOrUpdateBitmap(bool isPopup, Rect dirtyRect, IntPtr buffer, i }), dispatcherPriority); } } - - private void ReleaseMemoryMappedView(ref MemoryMappedFile mappedFile, ref MemoryMappedViewAccessor stream) - { - if (stream != null) - { - stream.Dispose(); - stream = null; - } - - if (mappedFile != null) - { - mappedFile.Dispose(); - mappedFile = null; - } - } } }