Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Side by Side Diff: content/browser/gamepad/platform_data_fetcher_win.cc

Issue 10781023: use Loadlibrary/GetProcAddress for XInput, rather than /DELAYLOAD (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: use FILE_PATH_LITERAL Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/gamepad/platform_data_fetcher_win.h" 5 #include "content/browser/gamepad/platform_data_fetcher_win.h"
6 6
7 #include "base/debug/trace_event.h" 7 #include "base/debug/trace_event.h"
8 #include "content/common/gamepad_messages.h" 8 #include "content/common/gamepad_messages.h"
9 #include "content/common/gamepad_hardware_buffer.h" 9 #include "content/common/gamepad_hardware_buffer.h"
10 10
11 #if defined(_WIN32_WINNT_WIN8)
12 // The Windows 8 SDK defines FACILITY_VISUALCPP in winerror.h.
13 #undef FACILITY_VISUALCPP
14 #endif
15 #include <delayimp.h>
16
17 #pragma comment(lib, "delayimp.lib")
18 #pragma comment(lib, "xinput.lib")
19
20 namespace content { 11 namespace content {
21 12
22 using namespace WebKit; 13 using namespace WebKit;
23 14
24 namespace { 15 namespace {
25 16
26 // See http://goo.gl/5VSJR. These are not available in all versions of the 17 // See http://goo.gl/5VSJR. These are not available in all versions of the
27 // header, but they can be returned from the driver, so we define our own 18 // header, but they can be returned from the driver, so we define our own
28 // versions here. 19 // versions here.
29 static const BYTE kDeviceSubTypeGamepad = 1; 20 static const BYTE kDeviceSubTypeGamepad = 1;
(...skipping 20 matching lines...) Expand all
50 case kDeviceSubTypeDancePad: return L"DANCE_PAD"; 41 case kDeviceSubTypeDancePad: return L"DANCE_PAD";
51 case kDeviceSubTypeGuitar: return L"GUITAR"; 42 case kDeviceSubTypeGuitar: return L"GUITAR";
52 case kDeviceSubTypeGuitarAlternate: return L"GUITAR_ALTERNATE"; 43 case kDeviceSubTypeGuitarAlternate: return L"GUITAR_ALTERNATE";
53 case kDeviceSubTypeDrumKit: return L"DRUM_KIT"; 44 case kDeviceSubTypeDrumKit: return L"DRUM_KIT";
54 case kDeviceSubTypeGuitarBass: return L"GUITAR_BASS"; 45 case kDeviceSubTypeGuitarBass: return L"GUITAR_BASS";
55 case kDeviceSubTypeArcadePad: return L"ARCADE_PAD"; 46 case kDeviceSubTypeArcadePad: return L"ARCADE_PAD";
56 default: return L"<UNKNOWN>"; 47 default: return L"<UNKNOWN>";
57 } 48 }
58 } 49 }
59 50
60 // Trap only the exceptions that DELAYLOAD can throw, otherwise rethrow.
61 // See http://msdn.microsoft.com/en-us/library/1c9e046h(v=VS.90).aspx.
62 LONG WINAPI DelayLoadDllExceptionFilter(PEXCEPTION_POINTERS pExcPointers) {
63 LONG disposition = EXCEPTION_EXECUTE_HANDLER;
64 switch (pExcPointers->ExceptionRecord->ExceptionCode) {
65 case VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND):
66 case VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND):
67 break;
68 default:
69 // Exception is not related to delay loading.
70 disposition = EXCEPTION_CONTINUE_SEARCH;
71 break;
72 }
73 return disposition;
74 }
75
76 bool EnableXInput() {
77 // We have specified DELAYLOAD for xinput1_3.dll. If the DLL is not
78 // installed (XP w/o DirectX redist installed), we disable functionality.
79 __try {
80 XInputEnable(true);
81 } __except(DelayLoadDllExceptionFilter(GetExceptionInformation())) {
82 return false;
83 }
84 return true;
85 }
86
87 } // namespace 51 } // namespace
88 52
89 GamepadPlatformDataFetcherWin::GamepadPlatformDataFetcherWin() 53 GamepadPlatformDataFetcherWin::GamepadPlatformDataFetcherWin() :
jochen (gone - plz use gerrit) 2012/07/19 14:34:04 the : should go on the next line
scottmg 2012/07/19 16:45:16 Done.
90 : xinput_available_(EnableXInput()) { 54 xinput_dll_(FilePath(FILE_PATH_LITERAL("xinput1_3.dll"))),
55 xinput_available_(GetXinputDllFunctions()) {
91 } 56 }
92 57
93 void GamepadPlatformDataFetcherWin::GetGamepadData(WebGamepads* pads, 58 void GamepadPlatformDataFetcherWin::GetGamepadData(WebGamepads* pads,
94 bool devices_changed_hint) { 59 bool devices_changed_hint) {
95 TRACE_EVENT0("GAMEPAD", "GetGamepadData"); 60 TRACE_EVENT0("GAMEPAD", "GetGamepadData");
96 61
97 // If there's no XInput DLL on the system, early out so that we don't 62 // If there's no XInput DLL on the system, early out so that we don't
98 // call any other XInput functions. 63 // call any other XInput functions.
99 if (!xinput_available_) { 64 if (!xinput_available_) {
100 pads->length = 0; 65 pads->length = 0;
101 return; 66 return;
102 } 67 }
103 68
104 pads->length = WebGamepads::itemsLengthCap; 69 pads->length = WebGamepads::itemsLengthCap;
105 70
106 // If we got notification that system devices have been updated, then 71 // If we got notification that system devices have been updated, then
107 // run GetCapabilities to update the connected status and the device 72 // run GetCapabilities to update the connected status and the device
108 // identifier. It can be slow to do to both GetCapabilities and 73 // identifier. It can be slow to do to both GetCapabilities and
109 // GetState on unconnected devices, so we want to avoid a 2-5ms pause 74 // GetState on unconnected devices, so we want to avoid a 2-5ms pause
110 // here by only doing this when the devices are updated (despite 75 // here by only doing this when the devices are updated (despite
111 // documentation claiming it's OK to call it any time). 76 // documentation claiming it's OK to call it any time).
112 if (devices_changed_hint) { 77 if (devices_changed_hint) {
113 for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) { 78 for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) {
114 WebGamepad& pad = pads->items[i]; 79 WebGamepad& pad = pads->items[i];
115 TRACE_EVENT1("GAMEPAD", "GetCapabilities", "id", i); 80 TRACE_EVENT1("GAMEPAD", "GetCapabilities", "id", i);
116 XINPUT_CAPABILITIES caps; 81 XINPUT_CAPABILITIES caps;
117 DWORD res = XInputGetCapabilities(i, XINPUT_FLAG_GAMEPAD, &caps); 82 DWORD res = xinput_get_capabilities_(i, XINPUT_FLAG_GAMEPAD, &caps);
118 if (res == ERROR_DEVICE_NOT_CONNECTED) { 83 if (res == ERROR_DEVICE_NOT_CONNECTED) {
119 pad.connected = false; 84 pad.connected = false;
120 } else { 85 } else {
121 pad.connected = true; 86 pad.connected = true;
122 base::swprintf(pad.id, 87 base::swprintf(pad.id,
123 WebGamepad::idLengthCap, 88 WebGamepad::idLengthCap,
124 L"Xbox 360 Controller (XInput STANDARD %ls)", 89 L"Xbox 360 Controller (XInput STANDARD %ls)",
125 GamepadSubTypeName(caps.SubType)); 90 GamepadSubTypeName(caps.SubType));
126 } 91 }
127 } 92 }
128 } 93 }
129 94
130 // We've updated the connection state if necessary, now update the actual 95 // We've updated the connection state if necessary, now update the actual
131 // data for the devices that are connected. 96 // data for the devices that are connected.
132 for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) { 97 for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) {
133 WebGamepad& pad = pads->items[i]; 98 WebGamepad& pad = pads->items[i];
134 99
135 // We rely on device_changed and GetCapabilities to tell us that 100 // We rely on device_changed and GetCapabilities to tell us that
136 // something's been connected, but we will mark as disconnected if 101 // something's been connected, but we will mark as disconnected if
137 // GetState returns that we've lost the pad. 102 // GetState returns that we've lost the pad.
138 if (!pad.connected) 103 if (!pad.connected)
139 continue; 104 continue;
140 105
141 XINPUT_STATE state; 106 XINPUT_STATE state;
142 memset(&state, 0, sizeof(XINPUT_STATE)); 107 memset(&state, 0, sizeof(XINPUT_STATE));
143 TRACE_EVENT_BEGIN1("GAMEPAD", "XInputGetState", "id", i); 108 TRACE_EVENT_BEGIN1("GAMEPAD", "XInputGetState", "id", i);
144 DWORD dwResult = XInputGetState(i, &state); 109 DWORD dwResult = xinput_get_state_(i, &state);
145 TRACE_EVENT_END1("GAMEPAD", "XInputGetState", "id", i); 110 TRACE_EVENT_END1("GAMEPAD", "XInputGetState", "id", i);
146 111
147 if (dwResult == ERROR_SUCCESS) { 112 if (dwResult == ERROR_SUCCESS) {
148 pad.timestamp = state.dwPacketNumber; 113 pad.timestamp = state.dwPacketNumber;
149 pad.buttonsLength = 0; 114 pad.buttonsLength = 0;
150 #define ADD(b) pad.buttons[pad.buttonsLength++] = \ 115 #define ADD(b) pad.buttons[pad.buttonsLength++] = \
151 ((state.Gamepad.wButtons & (b)) ? 1.0 : 0.0); 116 ((state.Gamepad.wButtons & (b)) ? 1.0 : 0.0);
152 ADD(XINPUT_GAMEPAD_A); 117 ADD(XINPUT_GAMEPAD_A);
153 ADD(XINPUT_GAMEPAD_B); 118 ADD(XINPUT_GAMEPAD_B);
154 ADD(XINPUT_GAMEPAD_X); 119 ADD(XINPUT_GAMEPAD_X);
(...skipping 16 matching lines...) Expand all
171 pad.axes[pad.axesLength++] = NormalizeAxis(state.Gamepad.sThumbLX); 136 pad.axes[pad.axesLength++] = NormalizeAxis(state.Gamepad.sThumbLX);
172 pad.axes[pad.axesLength++] = -NormalizeAxis(state.Gamepad.sThumbLY); 137 pad.axes[pad.axesLength++] = -NormalizeAxis(state.Gamepad.sThumbLY);
173 pad.axes[pad.axesLength++] = NormalizeAxis(state.Gamepad.sThumbRX); 138 pad.axes[pad.axesLength++] = NormalizeAxis(state.Gamepad.sThumbRX);
174 pad.axes[pad.axesLength++] = -NormalizeAxis(state.Gamepad.sThumbRY); 139 pad.axes[pad.axesLength++] = -NormalizeAxis(state.Gamepad.sThumbRY);
175 } else { 140 } else {
176 pad.connected = false; 141 pad.connected = false;
177 } 142 }
178 } 143 }
179 } 144 }
180 145
146 bool GamepadPlatformDataFetcherWin::GetXinputDllFunctions() {
147 xinput_enable_ = static_cast<XInputEnableFunc>(
148 xinput_dll_.GetFunctionPointer("XInputEnable"));
149 if (!xinput_enable_)
150 return false;
151 xinput_get_capabilities_ = static_cast<XInputGetCapabilitiesFunc>(
152 xinput_dll_.GetFunctionPointer("XInputGetCapabilities"));
153 if (!xinput_get_capabilities_)
154 return false;
155 xinput_get_state_ = static_cast<XInputGetStateFunc>(
156 xinput_dll_.GetFunctionPointer("XInputGetState"));
157 if (!xinput_get_state_)
158 return false;
159 xinput_enable_(true);
160 return true;
161 }
162
181 } // namespace content 163 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698