Index: System.Windows.Forms/Control.cs =================================================================== --- System.Windows.Forms/Control.cs (revision 70171) +++ System.Windows.Forms/Control.cs (working copy) @@ -127,10 +127,8 @@ ContextMenu context_menu; // Context menu associated with the control // double buffering - Graphics backbuffer_dc; - object backbuffer; - Region invalid_region; - + DoubleBuffer backbuffer; + // to implement DeviceContext without depending on double buffering Bitmap bmp; Graphics bmp_g; @@ -298,7 +296,98 @@ #endregion // ControlAccessibleObject Public Instance Methods } + + private class DoubleBuffer : IDisposable + { + public Region InvalidRegion; + private Stack real_graphics; + private object back_buffer; + private Control parent; + private bool pending_disposal; + + public DoubleBuffer (Control parent) + { + this.parent = parent; + real_graphics = new Stack (); + int width = parent.Width; + int height = parent.Height; + if (width < 1) width = 1; + if (height < 1) height = 1; + + XplatUI.CreateOffscreenDrawable (parent.Handle, width, height, out back_buffer); + Invalidate (); + } + + public void Blit (PaintEventArgs pe) + { + Graphics buffered_graphics; + buffered_graphics = XplatUI.GetOffscreenGraphics (back_buffer); + XplatUI.BlitFromOffscreen (parent.Handle, pe.Graphics, back_buffer, buffered_graphics, pe.ClipRectangle); + buffered_graphics.Dispose (); + } + + public void Start (PaintEventArgs pe) + { + // We need to get the graphics for every paint. + real_graphics.Push(pe.SetGraphics (XplatUI.GetOffscreenGraphics (back_buffer))); + } + + public void End (PaintEventArgs pe) + { + Graphics buffered_graphics; + buffered_graphics = pe.SetGraphics ((Graphics) real_graphics.Pop ()); + + if (pending_disposal) + Dispose (); + else { + XplatUI.BlitFromOffscreen (parent.Handle, pe.Graphics, back_buffer, buffered_graphics, pe.ClipRectangle); + InvalidRegion.Exclude (pe.ClipRectangle); + } + buffered_graphics.Dispose (); + } + + public void Invalidate () + { + if (InvalidRegion != null) + InvalidRegion.Dispose (); + InvalidRegion = new Region (parent.ClientRectangle); + } + + public void Dispose () + { + if (real_graphics.Count > 0) { + pending_disposal = true; + return; + } + + XplatUI.DestroyOffscreenDrawable (back_buffer); + + if (InvalidRegion != null) + InvalidRegion.Dispose (); + InvalidRegion = null; + back_buffer = null; + GC.SuppressFinalize (this); + } + + #region IDisposable Members + void IDisposable.Dispose () + { + Dispose (); + } + #endregion + + ~DoubleBuffer () + { + Dispose (); + } + } + class a + { + ~a () + { + } + } #if NET_2_0 [ComVisible (false)] #else @@ -866,10 +955,6 @@ bmp_g = null; } - if (invalid_region!=null) { - invalid_region.Dispose(); - invalid_region=null; - } if (this.InvokeRequired) { if (Application.MessageLoop) { this.BeginInvokeInternal(new MethodInvoker(DestroyHandle), null, true); @@ -1007,39 +1092,23 @@ private void InvalidateBackBuffer () { - if (invalid_region != null) - invalid_region.Dispose(); - invalid_region = new Region (ClientRectangle); + if (backbuffer != null) + backbuffer.Invalidate (); } - private void CreateBackBuffer () + private DoubleBuffer GetBackBuffer () { - if (backbuffer != null) - return; - - int width = Width; - int height = Height; - - if (width < 1) width = 1; - if (height < 1) height = 1; - - XplatUI.CreateOffscreenDrawable (Handle, width, height, out backbuffer, out backbuffer_dc); - InvalidateBackBuffer (); + if (backbuffer == null) + backbuffer = new DoubleBuffer (this); + return backbuffer; } private void DisposeBackBuffer () { - if (backbuffer == null) - return; - - XplatUI.DestroyOffscreenDrawable (backbuffer, backbuffer_dc); - backbuffer = null; - backbuffer_dc = null; - - - if (invalid_region != null) - invalid_region.Dispose (); - invalid_region = null; + if (backbuffer != null) { + backbuffer.Dispose (); + backbuffer = null; + } } internal static void SetChildColor(Control parent) { @@ -4157,27 +4226,20 @@ if (paint_event == null) { return; } - - if (invalid_region != null && !invalid_region.IsVisible (paint_event.ClipRectangle)) { - - // Just blit the previous image - XplatUI.BlitFromOffscreen (Handle, paint_event.Graphics, backbuffer, backbuffer_dc, paint_event.ClipRectangle); - XplatUI.PaintEventEnd (Handle, true); - return; - } - - Graphics dc = null; - Graphics back_dc = null; - object back = null; + DoubleBuffer current_buffer = null; if (ThemeEngine.Current.DoubleBufferingSupported) { if ((control_style & ControlStyles.DoubleBuffer) != 0) { - CreateBackBuffer (); - back = backbuffer; - back_dc = backbuffer_dc; - dc = paint_event.SetGraphics (back_dc); + current_buffer = GetBackBuffer (); + if (!current_buffer.InvalidRegion.IsVisible (paint_event.ClipRectangle)) { + // Just blit the previous image + current_buffer.Blit (paint_event); + XplatUI.PaintEventEnd (Handle, true); + return; + } + current_buffer.Start (paint_event); } } - + if (!GetStyle(ControlStyles.Opaque)) { OnPaintBackground(paint_event); } @@ -4190,17 +4252,12 @@ OnPaint(paint_event); } - if (ThemeEngine.Current.DoubleBufferingSupported) - if ((control_style & ControlStyles.DoubleBuffer) != 0) { - XplatUI.BlitFromOffscreen (Handle, dc, back, back_dc, paint_event.ClipRectangle); - paint_event.SetGraphics (dc); - invalid_region.Exclude (paint_event.ClipRectangle); - - if (back != backbuffer) - XplatUI.DestroyOffscreenDrawable (back, back_dc); - } - + if (current_buffer != null) { + current_buffer.End (paint_event); + } + XplatUI.PaintEventEnd(Handle, true); + return; } @@ -4738,10 +4795,7 @@ // invalid_region.IsVisible call) in // the WM_PAINT handling below. Rectangle r = Rectangle.Inflate(e.InvalidRect, 1,1); - if (invalid_region == null) - invalid_region = new Region (r); - else - invalid_region.Union (r); + backbuffer.InvalidRegion.Union (r); } } Index: System.Windows.Forms/XplatUI.cs =================================================================== --- System.Windows.Forms/XplatUI.cs (revision 70171) +++ System.Windows.Forms/XplatUI.cs (working copy) @@ -1000,26 +1000,31 @@ // double buffering internal static void CreateOffscreenDrawable (IntPtr handle, int width, int height, - out object offscreen_drawable, - out Graphics offscreen_dc) + out object offscreen_drawable) { #if DriverDebug Console.WriteLine("CreateOffscreenDrawable({2}, {0},{1}): Called", width, height, Window(handle)); #endif driver.CreateOffscreenDrawable (handle, width, height, - out offscreen_drawable, - out offscreen_dc); + out offscreen_drawable); } - internal static void DestroyOffscreenDrawable (object offscreen_drawable, - Graphics offscreen_dc) + internal static void DestroyOffscreenDrawable (object offscreen_drawable) { #if DriverDebug Console.WriteLine("DestroyOffscreenDrawable(): Called"); #endif - driver.DestroyOffscreenDrawable (offscreen_drawable, offscreen_dc); + driver.DestroyOffscreenDrawable (offscreen_drawable); } + internal static Graphics GetOffscreenGraphics (object offscreen_drawable) + { +#if DriverDebug + Console.WriteLine("GetOffscreenGraphics(): Called"); +#endif + return driver.GetOffscreenGraphics (offscreen_drawable); + } + internal static void BlitFromOffscreen (IntPtr dest_handle, Graphics dest_dc, object offscreen_drawable, Index: System.Windows.Forms/XplatUIDriver.cs =================================================================== --- System.Windows.Forms/XplatUIDriver.cs (revision 70171) +++ System.Windows.Forms/XplatUIDriver.cs (working copy) @@ -293,23 +293,25 @@ // Double buffering internal virtual void CreateOffscreenDrawable (IntPtr handle, int width, int height, - out object offscreen_drawable, - out Graphics offscreen_dc) + out object offscreen_drawable) { Bitmap bmp = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); offscreen_drawable = bmp; - offscreen_dc = Graphics.FromImage (bmp); } - internal virtual void DestroyOffscreenDrawable (object offscreen_drawable, - Graphics offscreen_dc) + internal virtual void DestroyOffscreenDrawable (object offscreen_drawable) { Bitmap bmp = (Bitmap)offscreen_drawable; bmp.Dispose (); - offscreen_dc.Dispose (); } + + internal virtual Graphics GetOffscreenGraphics (object offscreen_drawable) + { + Bitmap bmp = (Bitmap)offscreen_drawable; + return Graphics.FromImage (bmp); + } internal virtual void BlitFromOffscreen (IntPtr dest_handle, Graphics dest_dc, Index: System.Windows.Forms/XplatUIX11.cs =================================================================== --- System.Windows.Forms/XplatUIX11.cs (revision 70171) +++ System.Windows.Forms/XplatUIX11.cs (working copy) @@ -5154,8 +5154,7 @@ internal override void CreateOffscreenDrawable (IntPtr handle, int width, int height, - out object offscreen_drawable, - out Graphics offscreen_dc) + out object offscreen_drawable) { IntPtr root_out; int x_out, y_out, width_out, height_out, border_width_out, depth_out; @@ -5170,16 +5169,18 @@ offscreen_drawable = pixmap; - offscreen_dc = Graphics.FromHwnd (pixmap); } - internal override void DestroyOffscreenDrawable (object offscreen_drawable, - Graphics offscreen_dc) + internal override void DestroyOffscreenDrawable (object offscreen_drawable) { XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable); - offscreen_dc.Dispose (); } + internal override Graphics GetOffscreenGraphics (object offscreen_drawable) + { + return Graphics.FromHwnd ((IntPtr) offscreen_drawable); + } + internal override void BlitFromOffscreen (IntPtr dest_handle, Graphics dest_dc, object offscreen_drawable, Index: System.Windows.Forms.X11Internal/X11Display.cs =================================================================== --- System.Windows.Forms.X11Internal/X11Display.cs (revision 70171) +++ System.Windows.Forms.X11Internal/X11Display.cs (working copy) @@ -2416,8 +2416,7 @@ // double buffering support public void CreateOffscreenDrawable (IntPtr handle, int width, int height, - out object offscreen_drawable, - out Graphics offscreen_dc) + out object offscreen_drawable) { IntPtr root_out; int x_out, y_out, width_out, height_out, border_width_out, depth_out; @@ -2431,17 +2430,18 @@ IntPtr pixmap = Xlib.XCreatePixmap (display, handle, width, height, depth_out); offscreen_drawable = pixmap; - - offscreen_dc = Graphics.FromHwnd (pixmap); } - public void DestroyOffscreenDrawable (object offscreen_drawable, - Graphics offscreen_dc) + public void DestroyOffscreenDrawable (object offscreen_drawable) { Xlib.XFreePixmap (display, (IntPtr)offscreen_drawable); - offscreen_dc.Dispose (); } + public Graphics GetOffscreenGraphics (object offscreen_drawable) + { + return Graphics.FromHwnd ((IntPtr) offscreen_drawable); + } + public void BlitFromOffscreen (IntPtr dest_handle, Graphics dest_dc, object offscreen_drawable, Index: System.Windows.Forms.X11Internal/XplatUIX11-new.cs =================================================================== --- System.Windows.Forms.X11Internal/XplatUIX11-new.cs (revision 70171) +++ System.Windows.Forms.X11Internal/XplatUIX11-new.cs (working copy) @@ -1026,20 +1026,22 @@ internal override void CreateOffscreenDrawable (IntPtr handle, int width, int height, - out object offscreen_drawable, - out Graphics offscreen_dc) + out object offscreen_drawable) { display.CreateOffscreenDrawable (handle, width, height, - out offscreen_drawable, out offscreen_dc); + out offscreen_drawable); } - internal override void DestroyOffscreenDrawable (object offscreen_drawable, - Graphics offscreen_dc) + internal override void DestroyOffscreenDrawable (object offscreen_drawable) { - display.DestroyOffscreenDrawable (offscreen_drawable, - offscreen_dc); + display.DestroyOffscreenDrawable (offscreen_drawable); } + internal override Graphics GetOffscreenGraphics (object offscreen_drawable) + { + return display.GetOffscreenGraphics (offscreen_drawable); + } + internal override void BlitFromOffscreen (IntPtr dest_handle, Graphics dest_dc, object offscreen_drawable,