void IRenderHandler.OnPaint(bool isPopup, Rect dirtyRect, IntPtr buffer, int width, int height, Image image)
        {
            var writeableBitmap = image.Source as WriteableBitmap;

            if (writeableBitmap == null || writeableBitmap.PixelWidth != width || writeableBitmap.PixelHeight != height)
            {
                image.Source = writeableBitmap = new WriteableBitmap(width, height, dpiX, dpiY, AbstractRenderHandler.PixelFormat, null);
            }

            if (writeableBitmap != null)
            {
                writeableBitmap.Lock();

                NativeMethodWrapper.MemoryCopy(writeableBitmap.BackBuffer, buffer, writeableBitmap.BackBufferStride * writeableBitmap.PixelHeight);

                if (invalidateDirtyRect)
                {
                    writeableBitmap.AddDirtyRect(new Int32Rect(dirtyRect.X, dirtyRect.Y, dirtyRect.Width, dirtyRect.Height));
                }
                else
                {
                    writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, writeableBitmap.PixelWidth, writeableBitmap.PixelHeight));
                }
                writeableBitmap.Unlock();
            }
        }
            internal void UpdateBuffer(Rect dirtyRect, IntPtr sourceBuffer, int width, int height, Image image)
            {
                imageSize = (width * height) * AbstractRenderHandler.BytesPerPixel;

                if (bufferSize < imageSize)
                {
                    Marshal.FreeHGlobal(buffer);
                    buffer     = Marshal.AllocHGlobal(imageSize);
                    bufferSize = imageSize;
                }

                this.width     = width;
                this.height    = height;
                this.dirtyRect = dirtyRect;

                NativeMethodWrapper.MemoryCopy(buffer, sourceBuffer, imageSize);

                this.image = image;
                IsDirty    = true;
            }
            internal void OnPaint(Rect dirtyRect, IntPtr sourceBuffer, int width, int height, Image image)
            {
                ImageSize = (width * height) * AbstractRenderHandler.BytesPerPixel;

                if (BufferSize < ImageSize)
                {
                    Marshal.FreeHGlobal(Buffer);
                    Buffer     = Marshal.AllocHGlobal(ImageSize);
                    BufferSize = ImageSize;
                }

                Width     = width;
                Height    = height;
                DirtyRect = dirtyRect;

                NativeMethodWrapper.MemoryCopy(Buffer, sourceBuffer, ImageSize);

                Image   = image;
                IsDirty = true;
            }
        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;

            lock (lockObject)
            {
                int pixels        = width * height;
                int numberOfBytes = pixels * BytesPerPixel;

                createNewBitmap = mappedFile == null || currentSize.Height != height || currentSize.Width != width;

                if (createNewBitmap)
                {
                    //If the MemoryMappedFile is smaller than we need then create a larger one
                    //If it's larger then we need then rather than going through the costly expense of
                    //allocating a new one we'll just use the old one and only access the number of bytes we require.
                    if (viewAccessor == null || viewAccessor.Capacity < numberOfBytes)
                    {
                        ReleaseMemoryMappedView(ref mappedFile, ref viewAccessor);

                        mappedFile = MemoryMappedFile.CreateNew(null, numberOfBytes, MemoryMappedFileAccess.ReadWrite);

                        viewAccessor = mappedFile.CreateViewAccessor();
                    }

                    currentSize.Height = height;
                    currentSize.Width  = width;
                }

                NativeMethodWrapper.MemoryCopy(viewAccessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), buffer, numberOfBytes);

                //Take a reference to the sourceBuffer that's used to update our WritableBitmap,
                //once we're on the UI thread we need to check if it's still valid
                var sourceBuffer = viewAccessor.SafeMemoryMappedViewHandle;

                image.Dispatcher.BeginInvoke((Action)(() =>
                {
                    lock (lockObject)
                    {
                        if (sourceBuffer.IsClosed || sourceBuffer.IsInvalid)
                        {
                            return;
                        }

                        var size = isPopup ? popupSize : viewSize;

                        //If OnPaint is called multiple times before
                        //our BeginInvoke call we check the size matches our most recent
                        //update, the buffer has already been overriden (frame is dropped effectively)
                        //so we ignore this call
                        //https://github.com/cefsharp/CefSharp/issues/3114
                        if (size.Width != width || size.Height != height)
                        {
                            return;
                        }

                        if (createNewBitmap)
                        {
                            if (image.Source != null)
                            {
                                image.Source = null;
                                GC.Collect(1);
                            }

                            image.Source = new WriteableBitmap(width, height, dpiX, dpiY, PixelFormat, null);
                        }

                        var stride = width * BytesPerPixel;
                        var noOfBytes = stride * height;

                        var bitmap = (WriteableBitmap)image.Source;

                        //When agressively resizing the ChromiumWebBrowser sometimes
                        //we can end up with our buffer size not matching our bitmap size
                        //Just ignore these frames as the rendering should eventually catch up
                        //(CEF can generate multiple frames before WPF has performed a render cycle)
                        //https://github.com/cefsharp/CefSharp/issues/3474
                        if (width > bitmap.PixelWidth || height > bitmap.PixelHeight)
                        {
                            return;
                        }

                        //By default we'll only update the dirty rect, for those that run into a MILERR_WIN32ERROR Exception (#2035)
                        //it's desirably to either upgrade to a newer .Net version (only client runtime needs to be installed, not compiled
                        //against a newer version. Or invalidate the whole bitmap
                        if (invalidateDirtyRect)
                        {
                            // Update the dirty region
                            var sourceRect = new Int32Rect(dirtyRect.X, dirtyRect.Y, dirtyRect.Width, dirtyRect.Height);

                            bitmap.Lock();
                            bitmap.WritePixels(sourceRect, sourceBuffer.DangerousGetHandle(), noOfBytes, stride, dirtyRect.X, dirtyRect.Y);
                            bitmap.Unlock();
                        }
                        else
                        {
                            // Update whole bitmap
                            var sourceRect = new Int32Rect(0, 0, width, height);

                            bitmap.Lock();
                            bitmap.WritePixels(sourceRect, sourceBuffer.DangerousGetHandle(), noOfBytes, stride);
                            bitmap.Unlock();
                        }
                    }
                }), dispatcherPriority);
            }
        }
Ejemplo n.º 5
0
        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)
        {
            var createNewBitmap = false;

            lock (lockObject)
            {
                int pixels        = width * height;
                int numberOfBytes = pixels * BytesPerPixel;

                createNewBitmap = mappedFile == null || currentSize.Height != height || currentSize.Width != width;

                if (createNewBitmap)
                {
                    ReleaseMemoryMappedView(ref mappedFile, ref viewAccessor);

                    mappedFile = MemoryMappedFile.CreateNew(null, numberOfBytes, MemoryMappedFileAccess.ReadWrite);

                    viewAccessor = mappedFile.CreateViewAccessor();

                    currentSize.Height = height;
                    currentSize.Width  = width;
                }

                NativeMethodWrapper.MemoryCopy(viewAccessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), buffer, numberOfBytes);

                //Take a reference to the backBufferHandle, once we're on the UI thread we need to check if it's still valid
                var backBufferHandle = mappedFile.SafeMemoryMappedFileHandle;

                //Invoke on the WPF UI Thread
                image.Dispatcher.BeginInvoke((Action)(() =>
                {
                    lock (lockObject)
                    {
                        if (backBufferHandle.IsClosed || backBufferHandle.IsInvalid)
                        {
                            return;
                        }

                        if (createNewBitmap)
                        {
                            if (image.Source != null)
                            {
                                image.Source = null;
                                //TODO: Is this still required in newer versions of .Net?
                                GC.Collect(1);
                            }

                            var stride = width * BytesPerPixel;
                            var bitmap = (InteropBitmap)Imaging.CreateBitmapSourceFromMemorySection(backBufferHandle.DangerousGetHandle(), width, height, PixelFormat, stride, 0);
                            image.Source = bitmap;
                        }
                        else if (image.Source != null)
                        {
                            var sourceRect = new Int32Rect(dirtyRect.X, dirtyRect.Y, dirtyRect.Width, dirtyRect.Height);
                            var bitmap = (InteropBitmap)image.Source;
                            bitmap.Invalidate(sourceRect);
                        }
                    }
                }), dispatcherPriority);
            }
        }
Ejemplo n.º 6
0
        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;

            lock (lockObject)
            {
                int pixels        = width * height;
                int numberOfBytes = pixels * BytesPerPixel;

                createNewBitmap = mappedFile == null || currentSize.Height != height || currentSize.Width != width;

                if (createNewBitmap)
                {
                    //If the MemoryMappedFile is smaller than we need then create a larger one
                    //If it's larger then we need then rather than going through the costly expense of
                    //allocating a new one we'll just use the old one and only access the number of bytes we require.
                    if (viewAccessor == null || viewAccessor.Capacity < numberOfBytes)
                    {
                        ReleaseMemoryMappedView(ref mappedFile, ref viewAccessor);

                        mappedFile = MemoryMappedFile.CreateNew(null, numberOfBytes, MemoryMappedFileAccess.ReadWrite);

                        viewAccessor = mappedFile.CreateViewAccessor();
                    }

                    currentSize.Height = height;
                    currentSize.Width  = width;
                }

                NativeMethodWrapper.MemoryCopy(viewAccessor.SafeMemoryMappedViewHandle.DangerousGetHandle(), buffer, numberOfBytes);

                //Take a reference to the sourceBuffer that's used to update our WritableBitmap,
                //once we're on the UI thread we need to check if it's still valid
                var sourceBuffer = viewAccessor.SafeMemoryMappedViewHandle;

                image.Dispatcher.BeginInvoke((Action)(() =>
                {
                    lock (lockObject)
                    {
                        if (sourceBuffer.IsClosed || sourceBuffer.IsInvalid)
                        {
                            return;
                        }

                        if (createNewBitmap)
                        {
                            if (image.Source != null)
                            {
                                image.Source = null;
                                GC.Collect(1);
                            }

                            image.Source = new WriteableBitmap(width, height, dpiX, dpiY, PixelFormat, null);
                        }

                        var stride = width * BytesPerPixel;
                        var noOfBytes = stride * height;

                        var bitmap = (WriteableBitmap)image.Source;

                        //By default we'll only update the dirty rect, for those that run into a MILERR_WIN32ERROR Exception (#2035)
                        //it's desirably to either upgrade to a newer .Net version (only client runtime needs to be installed, not compiled
                        //against a newer version. Or invalidate the whole bitmap
                        if (invalidateDirtyRect)
                        {
                            // Update the dirty region
                            var sourceRect = new Int32Rect(dirtyRect.X, dirtyRect.Y, dirtyRect.Width, dirtyRect.Height);

                            bitmap.Lock();
                            bitmap.WritePixels(sourceRect, sourceBuffer.DangerousGetHandle(), noOfBytes, stride, dirtyRect.X, dirtyRect.Y);
                            bitmap.Unlock();
                        }
                        else
                        {
                            // Update whole bitmap
                            var sourceRect = new Int32Rect(0, 0, width, height);

                            bitmap.Lock();
                            bitmap.WritePixels(sourceRect, sourceBuffer.DangerousGetHandle(), noOfBytes, stride);
                            bitmap.Unlock();
                        }
                    }
                }), dispatcherPriority);
            }
        }