Reputation: 191
I have a problem that I couldn't be able to fix since one week, I hope someone could have ever experienced this.
I'm using SharpDX with a windows form project, basically there is a form with a picturebox and some panel over it.
The typical Swapchain.Present(1,PresentFlags.None) works good when I zoom or translate the image. However I get this strange situation where when I minimize my screen and reopen it back, all the swapchain content is hidden like if it has been erased. However, I know it hasn't and this is probably a race condition between GDI refresh and SharpDX.
So, I tried to overrides WndProc(Message m) in every control and handle it's paint and eraseBackground event. This is not working. When I debug, windows message are always different from time to time so it is quite hard to figure out what could be wrong.
If anyone has ever experience this behavior while mixing SharpDX(or directX) on Windows form, I would really like an answer.
Here is how I handle the resize event of my SharpDX DeviceContext
Public Overrides Sub Resize(Width As Integer, Height As Integer)
If m_SwapChain IsNot Nothing Then
If m_BackBuffer IsNot Nothing Then
m_BackBuffer.Dispose()
End If
If m_2DDeviceContext IsNot Nothing Then
m_2DDeviceContext.Dispose()
End If
If m_2DTarget IsNot Nothing Then
m_2DTarget.Dispose()
End If
m_SwapChain.ResizeBuffers(2, Width, Height, Format.B8G8R8A8_UNorm, SwapChainFlags.GdiCompatible)
m_BackBuffer = m_SwapChain.GetBackBuffer(Of Surface)(0)
m_2DDeviceContext = New SharpDX.Direct2D1.DeviceContext(m_2DDevice, SharpDX.Direct2D1.DeviceContextOptions.EnableMultithreadedOptimizations)
m_2DTarget = New SharpDX.Direct2D1.Bitmap(m_2DDeviceContext, m_BackBuffer, m_Properties)
m_2DDeviceContext.AntialiasMode = AntialiasMode.PerPrimitive
m_2DDeviceContext.Target = m_2DTarget
CType(m_Context, GPUDrawingContext).DeviceContext = m_2DDeviceContext
End If
End Sub
EDIT : After trying many stuff, I realize it was happening right when I call base.Wndproc(m) where m = WM_PAINT.
I can't ignore the paint message because if I do, my control is still invalidated and it will add a new WM_PAINT to the event queue and send me into an infinite loop. I really cannot do base.Wndproc(m) because this is where my swapchain gets hide.
Is their any way to handle(ignore) this event message without having it back in the loop because SharpDX doesn't require this function since it's a paint layer over the control.
Upvotes: 0
Views: 739
Reputation: 1737
When you just want to resize the swapchain you don't have to recreate the DeviceContext. Maybe here is the first cause of your problem, because the swapchain was created with a different DeviceContext than the backbuffer. For me this is working in C#:
first add eventhandlers to the resize events of the control. No need to override the WM_PAINT:
form.ResizeBegin += (o, e) => {
formHeight = ((Form)o).Height;
formWidth = ((Form)o).Width;
};
form.ResizeBegin += (o, e) => {
isResizing = true;
};
form.ResizeEnd += (o, e) => {
isResizing = false;
HandleResize(o, e);
};
form.SizeChanged += HandleResize;
with this I can save the old size of the control for comparison. And I'm just resizing the swapchain after the resize is finished and not for every event (like when resizing a window). Also I will only resize if the control is not minimized:
private void HandleResize(object sender, System.EventArgs e) {
Form f = (Form)sender;
if ((f.ClientSize.Width != formWidth || f.ClientSize.Height != formHeight)
&& !isResizing
&& !(f.WindowState == FormWindowState.Minimized)) {
formWidth = f.ClientSize.Width;
formHeight = f.ClientSize.Height;
DoResize(formWidth, formHeight);
}
}
Finally DoResize is following (renderTarget is my custom class):
private void DoResize(int width, int height) {
renderTarget.Dispose();
swapChain.ResizeBuffers(1, width, height, Format.R8G8B8A8_UNorm, SwapChainFlags.AllowModeSwitch);
using (var resource = Resource.FromSwapChain<Texture2D>(swapChain, 0)) {
//recreate the rendertarget with the new backbuffer
renderTarget.Resize(width, height, resource);
}
}
Upvotes: 1