Visual Studio 2012 Support
[xy_vsfilter.git] / src / thirdparty / VirtualDub / system / source / cpuaccel.cpp
blob439a701dced5a1c4cef572629607332a85c30d57
1 // VirtualDub - Video processing and capture application
2 // System library component
3 // Copyright (C) 1998-2004 Avery Lee, All Rights Reserved.
4 //
5 // Beginning with 1.6.0, the VirtualDub system library is licensed
6 // differently than the remainder of VirtualDub. This particular file is
7 // thus licensed as follows (the "zlib" license):
8 //
9 // This software is provided 'as-is', without any express or implied
10 // warranty. In no event will the authors be held liable for any
11 // damages arising from the use of this software.
13 // Permission is granted to anyone to use this software for any purpose,
14 // including commercial applications, and to alter it and redistribute it
15 // freely, subject to the following restrictions:
17 // 1. The origin of this software must not be misrepresented; you must
18 // not claim that you wrote the original software. If you use this
19 // software in a product, an acknowledgment in the product
20 // documentation would be appreciated but is not required.
21 // 2. Altered source versions must be plainly marked as such, and must
22 // not be misrepresented as being the original software.
23 // 3. This notice may not be removed or altered from any source
24 // distribution.
26 #include "stdafx.h"
27 #include <wtypes.h>
28 #include <winnt.h>
29 #include <vd2/system/win32/intrin.h>
30 #include <vd2/system/cpuaccel.h>
32 static long g_lCPUExtensionsEnabled;
33 static long g_lCPUExtensionsAvailable;
35 extern "C" {
36 bool FPU_enabled, MMX_enabled, SSE_enabled, ISSE_enabled, SSE2_enabled;
39 #if (!defined(VD_CPU_X86) && !defined(VD_CPU_AMD64)) || defined(__MINGW32__)
40 long CPUCheckForExtensions() {
41 return 0;
43 #else
45 namespace {
46 #ifdef _M_IX86
47 bool VDIsAVXSupportedByOS() {
48 uint32 xfeature_enabled_mask;
50 __asm {
51 xor ecx, ecx
52 __emit 0x0f ;xgetbv
53 __emit 0x01
54 __emit 0xd0
55 mov dword ptr xfeature_enabled_mask, eax
58 return (xfeature_enabled_mask & 0x06) == 0x06;
60 #else
61 extern "C" bool VDIsAVXSupportedByOS();
62 #endif
65 // This code used to use IsProcessorFeaturePresent(), but this function is somewhat
66 // suboptimal in Win64 -- for one thing, it doesn't return true for MMX, at least
67 // on Vista 64.
68 long CPUCheckForExtensions() {
69 // check for CPUID (x86 only)
70 #ifdef _M_IX86
71 uint32 id;
72 __asm {
73 pushfd
74 or dword ptr [esp], 00200000h ;set the ID bit
75 popfd
76 pushfd ;flags -> EAX
77 pop dword ptr id
80 if (!(id & 0x00200000)) {
81 // if we don't have CPUID, we probably won't want to try FPU optimizations
82 // (80486).
83 return 0;
85 #endif
87 // check for features register
88 long flags = CPUF_SUPPORTS_FPU | CPUF_SUPPORTS_CPUID;
90 int cpuInfo[4];
91 __cpuid(cpuInfo, 0);
92 if (cpuInfo[0] == 0)
93 return flags;
95 __cpuid(cpuInfo, 1);
97 if (cpuInfo[3] & (1 << 23))
98 flags |= CPUF_SUPPORTS_MMX;
100 if (cpuInfo[3] & (1 << 25)) {
101 // Check if SSE is actually supported.
102 bool sseSupported = true;
104 #ifdef _M_IX86
105 __try {
106 __asm andps xmm0,xmm0
107 } __except(EXCEPTION_EXECUTE_HANDLER) {
108 if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION)
109 sseSupported = false;
111 #endif
113 if (sseSupported) {
114 flags |= CPUF_SUPPORTS_SSE | CPUF_SUPPORTS_INTEGER_SSE;
116 if (cpuInfo[3] & (1 << 26))
117 flags |= CPUF_SUPPORTS_SSE2;
119 if (cpuInfo[2] & 0x00000001)
120 flags |= CPUF_SUPPORTS_SSE3;
122 if (cpuInfo[2] & 0x00000200)
123 flags |= CPUF_SUPPORTS_SSSE3;
125 if (cpuInfo[2] & 0x00080000)
126 flags |= CPUF_SUPPORTS_SSE41;
128 // check OSXSAVE and AVX bits
129 if ((cpuInfo[2] & ((1 << 27) | (1 << 28))) == ((1 << 27) | (1 << 28))) {
130 if (VDIsAVXSupportedByOS())
131 flags |= CPUF_SUPPORTS_AVX;
136 // check for 3DNow!, 3DNow! extensions
137 __cpuid(cpuInfo, 0x80000000);
138 if ((unsigned)cpuInfo[0] >= 0x80000001U) {
139 __cpuid(cpuInfo, 0x80000001);
141 if (cpuInfo[3] & (1 << 31))
142 flags |= CPUF_SUPPORTS_3DNOW;
144 if (cpuInfo[3] & (1 << 30))
145 flags |= CPUF_SUPPORTS_3DNOW_EXT;
147 if (cpuInfo[3] & (1 << 22))
148 flags |= CPUF_SUPPORTS_INTEGER_SSE;
151 return flags;
153 #endif
155 long CPUEnableExtensions(long lEnableFlags) {
156 g_lCPUExtensionsEnabled = lEnableFlags;
158 MMX_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_MMX);
159 FPU_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_FPU);
160 SSE_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_SSE);
161 ISSE_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_INTEGER_SSE);
162 SSE2_enabled = !!(g_lCPUExtensionsEnabled & CPUF_SUPPORTS_SSE2);
164 return g_lCPUExtensionsEnabled;
167 long CPUGetAvailableExtensions() {
168 return g_lCPUExtensionsAvailable;
171 long CPUGetEnabledExtensions() {
172 return g_lCPUExtensionsEnabled;
175 void VDCPUCleanupExtensions() {
176 #if defined(VD_CPU_X86)
177 if (ISSE_enabled)
178 _mm_sfence();
180 if (MMX_enabled)
181 _mm_empty();
182 #elif defined(VD_CPU_AMD64)
183 _mm_sfence();
184 #endif