技术开发 频道

WPF是如何把图像画到屏幕上


【IT168技术文档】

  做下面的研究前,我是一个WPF白痴。只会花一个简单的button。我的目的很简单,弄清楚WPF如何工作的。

  我要解决的第一个问题是WPF如何Render的。据说是用DX,但是一定要亲自证实下才可以相信。怎么做呢,先找一个UI复杂的程序,这里选择了MSDN的sample:

  http://msdn2.microsoft.com/en-us/library/ms771766.aspx

  运行起来后,选择一个复杂的背景,我选择了用Video当背景。然后用Windbg断下来,接下来用~命令检查哪些线程比较繁忙,看到繁忙的线程是:
0:006> kL ChildEBP RetAddr 0363fdf8 77c40d8f ntdll!KiFastSystemCallRet 0363fe18 4e040b1c GDI32!NtGdiDdDestroySurface+0xc 0363fe30 4e055ed7 d3d9!DdDestroySurface+0x1c 0363fe54 4e05624d d3d9!CMipMap::~CMipMap+0x67 0363fe60 4e04c442 d3d9!CMipMap::`scalar deleting destructor'+0xd 0363fe70 4e060b7d d3d9!CBaseObject::ReleaseImpl+0x42 0363fe80 531bf894 d3d9!CCubeSurface::Release+0x3d 0363fe8c 531b5aa9 MilCore!CD3DTextureSurface::ReleaseD3DResources+0x12 0363fe98 531b5b0e MilCore!CD3DResourceManager::DestroyResource+0xd 0363feb4 531bf2bb MilCore!CD3DResourceManager::DestroyResources+0x4c 0363fec4 531bf2e4 MilCore!CD3DDeviceLevel1::AdvanceFrame+0x30 0363fed4 531a73c3 MilCore!CHwDisplayRenderTarget::AdvanceFrame+0x27 0363fef0 531a7172 MilCore!CDesktopRenderTarget::AdvanceFrame+0x24 0363ff00 531a7144 MilCore!CSlaveHWndRenderTarget::AdvanceFrame+0x26 0363ff10 531a6f7b MilCore!CRenderTargetManager::AdvanceFrame+0x2d 0363ff24 531a70a6 MilCore!CRenderTargetManager::Present+0xca 0363ff74 531a6ffe MilCore!CComposition::Present+0x146 0363ff8c 5319c071 MilCore!CPartitionThread::PresentPartition+0x15 0363ffa0 53208d55 MilCore!CPartitionThread::Run+0x3c 0363ffb8 77e64829 MilCore!CPartitionThread::ThreadMain+0x1e 0:015> kL ChildEBP RetAddr 04fbf794 7c827d0b ntdll!KiFastSystemCallRet 04fbf798 77e61d1e ntdll!NtWaitForSingleObject+0xc 04fbf808 77e61c8d KERNEL32!WaitForSingleObjectEx+0xac 04fbf81c 7560349d KERNEL32!WaitForSingleObject+0x12 04fbf838 4f9871b1 quartz!CBaseAllocator::GetBuffer+0x52 04fbf854 4f9ace41 wmp!CBaseOutputPin::GetDeliveryBuffer+0x24 04fbf89c 4f9ad410 wmp!CWMNodeFilter::SuckOutOutput+0xf8 04fbf8bc 4f9ae03d wmp!CWMNodeFilter::HandleSample+0x161 04fbf8dc 4f9871e3 wmp!CWMNodeFilterInputPin::Receive+0x117 04fbf8ec 4f9aba75 wmp!CBaseOutputPin::Deliver+0x22 04fbf91c 4f9ad526 wmp!CWMNodeFilter::ProcessInPlaceSample+0xb6 04fbf944 4f9ae03d wmp!CWMNodeFilter::HandleInPlaceSample+0xe3 04fbf964 4f9871e3 wmp!CWMNodeFilterInputPin::Receive+0x117 04fbf974 4f9ad116 wmp!CBaseOutputPin::Deliver+0x22 04fbf9b0 4f9ad410 wmp!CWMNodeFilter::SuckOutOutput+0x3cd 04fbf9d0 4f9ae03d wmp!CWMNodeFilter::HandleSample+0x161 04fbf9f0 4f9871e3 wmp!CWMNodeFilterInputPin::Receive+0x117 04fbfa00 4f9ad116 wmp!CBaseOutputPin::Deliver+0x22 04fbfa3c 4f9ad410 wmp!CWMNodeFilter::SuckOutOutput+0x3cd 04fbfa5c 4f9ae03d wmp!CWMNodeFilter::HandleSample+0x161
  明显了,线程6应该就是Render线程,负责画图的,这里有一个module叫d3d9,应该是Direct 3D version9的意思。如果Google以下关键子MilCore,就会知道这个是WPF的Render关键模块了。

  看看主线程:
0:000> !clrstack OS Thread Id: 0x1240 (0) ESP EIP 0012f354 7c8285ec [ComPlusMethodFrameGeneric: 0012f354] MS.Win32.UnsafeNativeMethods+ITfMessagePump.GetMessageW(System.Windows.Interop.MSG ByRef, Int32, Int32, Int32, Boolean ByRef) 0012f374 56d61937 System.Windows.Threading.Dispatcher.GetMessage(System.Windows.Interop.MSG ByRef, IntPtr, Int32, Int32) 0012f3c0 56d617e3 System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame) 0012f410 56d616c7 System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame) 0012f42c 56d6162d System.Windows.Threading.Dispatcher.Run() 0012f438 5533dce0 System.Windows.Application.RunInternal(System.Windows.Window) 0012f464 5533db15 System.Windows.Application.Run(System.Windows.Window) 0012f474 5533d766 System.Windows.Application.Run() 0012f47c 00f200ad PuzzleProject.app.Main() 0012f69c 79e7c74b [GCFrame: 0012f69c]
  很简单,在等待消息。

  从上面的例子,我得到的信息是:
  1. WPF通过worker thread进行Render。这个thread的入口是MilCore!CPartitionThread里面的相关函数
  2. WPF的确用了Direct X
0
相关文章