0%

1.首先定义一个DX操作类

复制代码

1 using System; 2 using SlimDX; 3 using SlimDX.Direct3D9; 4 using System.Windows.Interop; 5 using System.Windows.Media; 6
7 public class DX 8 {
9 private enum DirectXStatus 10 {
11 Available,
12 Unavailable_RemoteSession,
13 Unavailable_LowTier,
14 Unavailable_MissingDirectX,
15 Unavailable_Unknown
16 };
17
18 public static Device Device { get; private set; }
19 public static bool Available { get { return DX.Device != null; } }// = false;
20
21 private static DX _dx; 22 private static DirectXStatus _status = DirectXStatus.Unavailable_Unknown; 23 private static string _statusMessage = “”;
24
25 [System.Runtime.InteropServices.DllImport(“user32”)]
26 private static extern int GetSystemMetrics(int smIndex); 27 private const int SM_REMOTESESSION = 0x1000;
28
29 // device settings
30 private const Format _adapterFormat = Format.X8R8G8B8; 31 private const Format _backbufferFormat = Format.A8R8G8B8; 32 private const Format _depthStencilFormat = Format.D16; 33 private static CreateFlags _createFlags = CreateFlags.Multithreaded | CreateFlags.FpuPreserve; 34
35 private Direct3D _d3d; 36
37
38 private DX() 39 {
40 initD3D();
41 if (_d3d != null)
42 initDevice();
43 //if (!DX.Available)
44 // MessageBox.Show(“DirectX硬件加速不可用!\n\n” + _statusMessage, “”, MessageBoxButton.OK, MessageBoxImage.Warning);
45 }
46
47 ~DX()
48 {
49 if (DX.Device != null)
50 if (!DX.Device.Disposed)
51 DX.Device.Dispose();
52 if (_d3d != null)
53 if (!_d3d.Disposed)
54 _d3d.Dispose();
55 }
56
57 public static void Init() 58 {
59 if (_dx == null)
60 _dx = new DX(); 61 }
62
63 private void initD3D() 64 {
65 if (_d3d != null)
66 return;
67
68 _status = DirectXStatus.Unavailable_Unknown; 69
70 //// assume that we can’t run at all under terminal services
71 if (GetSystemMetrics(SM_REMOTESESSION) != 0)
72 {
73 _status = DirectXStatus.Unavailable_RemoteSession; 74 return;
75 }
76
77 int renderingTier = (RenderCapability.Tier >> 16);
78 if (renderingTier < 2)
79 {
80 _status = DirectXStatus.Unavailable_LowTier; 81 _statusMessage = “low tier”;
82 return;//注意:发现某些集成显卡,在这里出去!!
83 }
84
85 try
86 {
87 _d3d = new Direct3DEx(); 88 }
89 catch
90 {
91 try
92 {
93 _d3d = new Direct3D(); 94 }
95 catch (Direct3DX9NotFoundException dfe) 96 {
97 _status = DirectXStatus.Unavailable_MissingDirectX; 98 _statusMessage = “Direct3DX9 Not Found\n” + dfe.Message; 99 return; 100 } 101 catch (Exception e) 102 { 103 _status = DirectXStatus.Unavailable_Unknown; 104 _statusMessage = e.Message; 105 return; 106 } 107 } 108
109 bool ok; 110 Result result; 111
112 ok = _d3d.CheckDeviceType(0, DeviceType.Hardware, _adapterFormat, _backbufferFormat, true, out result); 113 if (!ok) 114 { 115 //Debug.WriteLine(“*** failed to CheckDeviceType”); 116 //MessageBox.Show(“Failed to CheckDeviceType”);
117 return; 118 } 119
120 ok = _d3d.CheckDepthStencilMatch(0, DeviceType.Hardware, _adapterFormat, _backbufferFormat, _depthStencilFormat, out result); 121 if (!ok) 122 { 123 //Debug.WriteLine(“*** failed to CheckDepthStencilMatch”);
124 _statusMessage = “Failed to CheckDepthStencilMatch”; 125 return; 126 } 127
128 Capabilities deviceCaps = _d3d.GetDeviceCaps(0, DeviceType.Hardware); 129 if ((deviceCaps.DeviceCaps & DeviceCaps.HWTransformAndLight) != 0) 130 _createFlags |= CreateFlags.HardwareVertexProcessing; 131 else
132 _createFlags |= CreateFlags.SoftwareVertexProcessing; 133
134 _status = DirectXStatus.Available; 135 } 136
137 private void initDevice() 138 { 139 if (_status != DirectXStatus.Available) 140 return; 141
142 HwndSource hwnd = new HwndSource(0, 0, 0, 0, 0, 0, 0, “SlimDX_Wnd”, IntPtr.Zero); 143 PresentParameters pp = new PresentParameters(); 144 //pp.SwapEffect = SwapEffect.Copy; 145 //pp.DeviceWindowHandle = hwnd.Handle;
146 pp.Windowed = true; 147 pp.PresentFlags = PresentFlags.Video; 148 pp.SwapEffect = SwapEffect.Discard; 149 //pp.BackBufferCount = 1; 150 //pp.BackBufferWidth = 320; 151 //pp.BackBufferHeight = 240; 152 //pp.BackBufferFormat = _backbufferFormat; 153 //pp.AutoDepthStencilFormat = _depthStencilFormat;
154 try
155 { 156 DeviceType deviceType = DeviceType.Hardware; 157 if (_d3d is Direct3DEx) 158 DX.Device = new DeviceEx((Direct3DEx)_d3d, 0, deviceType, hwnd.Handle, _createFlags, pp); 159 else
160 DX.Device = new Device(_d3d, 0, deviceType, hwnd.Handle, _createFlags, pp); 161 } 162 catch (Exception ex) 163 { 164 //Debug.WriteLine(“Exception in Direct3DReset “ + ex.StackTrace); 165 //Debug.WriteLine(“Exception in Direct3DReset “ + ex.Message);
166 } 167 } 168 }

复制代码

2.定义准备显卡硬件,和释放显卡硬件方法

定义一些变量

复制代码

   /// <summary>
    /// 离屏表面 /// </summary>
    private Surface \_offscrn; /// <summary>
    /// 交换链 /// </summary>
    private SwapChain \_swapChain; private D3DImage \_d3dImage = null;    

复制代码

复制代码

1      ///


2 /// 准备DirectX显卡硬件 3 ///

4 private bool prepareHardware(VideoFormat videoFormat, int videoWidth, int videoHeight)//, VideoFormat videoFormat)
5 {
6 if (!DX.Available)
7 return true;
8
9 try
10 { 11 SlimDX.Direct3D9.Format format = SlimDX.Direct3D9.Format.A8R8G8B8; 12 if (videoFormat == VideoFormat.Yuv420) 13 format = (SlimDX.Direct3D9.Format)0x32315659; 14 if (_offscrn != null) 15 if (videoWidth == _offscrn.Description.Width && videoHeight == _offscrn.Description.Height && _offscrn.Description.Format == format) 16 return true; 17
18 releaseHardware(); 19 _offscrn = Surface.CreateOffscreenPlain(DX.Device, videoWidth, videoHeight, format, Pool.Default); 20 PresentParameters pp = new PresentParameters(); 21 pp.Windowed = true; 22 pp.PresentFlags = PresentFlags.Video; 23 pp.SwapEffect = SwapEffect.Discard; 24 pp.BackBufferCount = 1; 25 pp.BackBufferWidth = videoWidth; 26 pp.BackBufferHeight = videoHeight; 27 _swapChain = new SwapChain(DX.Device, pp); 28 return true; 29 } 30 catch
31 { 32 return false; 33 } 34 } 35 ///
36 /// 释放DirectX显卡硬件 37 ///

38 private void releaseHardware() 39 { 40 if (!DX.Available) 41 return; 42 if (_offscrn != null) 43 if (!_offscrn.Disposed) 44 _offscrn.Dispose(); 45 _offscrn = null; 46 if (_swapChain != null) 47 if (!_swapChain.Disposed) 48 _swapChain.Dispose(); 49 _swapChain = null; 50 }

复制代码

复制代码

private void drawFrame(VideoFormat videoFormat, int width, int height, IntPtr Y, IntPtr U, IntPtr V)
{ if (!prepareHardware(videoFormat, width, height)) return; if (_swapChain == null) return;

        DataRectangle dr \= \_offscrn.LockRectangle(LockFlags.None);//在离屏表面上锁定一个矩形
        drawYuv420(width, height, Y, U, V, dr.Data.DataPointer, dr.Pitch);//DataPointer 内部指针指向当前流的存储备份; Pitch 两个连续的行之间的数据的字节数
        \_offscrn.UnlockRectangle();//解锁矩形
        using (Surface bb = \_swapChain.GetBackBuffer(0))//从交换链中检索一个后台缓冲区

{
System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, bb.Description.Width, bb.Description.Height);
_swapChain.Device.StretchRectangle(_offscrn, rect, bb, rect, TextureFilter.None);//将后台缓冲区的内容交换到前台缓冲区
_swapChain.Device.Present();//呈现后台缓冲区序列中下一个后台缓冲区的内容
_d3dImage.Lock();
_d3dImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, bb.ComPointer);
_d3dImage.AddDirtyRect(new Int32Rect(0, 0, _d3dImage.PixelWidth, _d3dImage.PixelHeight));
_d3dImage.Unlock();
}
} private void drawYuv420(int width, int height, IntPtr Y, IntPtr U, IntPtr V, IntPtr dest, int pitch)
{
IntPtr py = dest;
IntPtr pv = py + (pitch * height);
IntPtr pu = pv + ((pitch * height) / 4); int w2 = width / 2, pitch2 = pitch / 2; for (int y = 0; y < height; y++)
{
CopyMemory(py, Y + y * width, (uint)width);
py += pitch; if ((y & 1) != 0) continue; int offset = y / 2 * w2;
CopyMemory(pu, U + offset, (uint)w2);
CopyMemory(pv, V + offset, (uint)w2);
pu += pitch2;
pv += pitch2;
}
}
[DllImport(“kernel32.dll”, EntryPoint = “RtlMoveMemory”)] private static extern void CopyMemory(IntPtr Destination, IntPtr Source, uint Length);

复制代码