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

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

Issue 1627643002: Revert of Refactoring gamepad polling to support dynamically added sources (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 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
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/gamepad_platform_data_fetcher_win.h" 5 #include "content/browser/gamepad/gamepad_platform_data_fetcher_win.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <string.h> 8 #include <string.h>
9 9
10 #include "base/strings/stringprintf.h" 10 #include "base/strings/stringprintf.h"
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 case kDeviceSubTypeDrumKit: return L"DRUM_KIT"; 49 case kDeviceSubTypeDrumKit: return L"DRUM_KIT";
50 case kDeviceSubTypeGuitarBass: return L"GUITAR_BASS"; 50 case kDeviceSubTypeGuitarBass: return L"GUITAR_BASS";
51 case kDeviceSubTypeArcadePad: return L"ARCADE_PAD"; 51 case kDeviceSubTypeArcadePad: return L"ARCADE_PAD";
52 default: return L"<UNKNOWN>"; 52 default: return L"<UNKNOWN>";
53 } 53 }
54 } 54 }
55 55
56 } // namespace 56 } // namespace
57 57
58 GamepadPlatformDataFetcherWin::GamepadPlatformDataFetcherWin() 58 GamepadPlatformDataFetcherWin::GamepadPlatformDataFetcherWin()
59 : xinput_available_(false) { 59 : xinput_dll_(base::FilePath(FILE_PATH_LITERAL("xinput1_3.dll"))),
60 for (size_t i = 0; i < XUSER_MAX_COUNT; ++i) 60 xinput_available_(GetXInputDllFunctions()) {
61 xinput_connected_[i] = false; 61 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
62 platform_pad_state_[i].status = DISCONNECTED;
63 pad_state_[i].mapper = NULL;
64 pad_state_[i].axis_mask = 0;
65 pad_state_[i].button_mask = 0;
66 }
67
68 raw_input_fetcher_.reset(new RawInputDataFetcher());
69 raw_input_fetcher_->StartMonitor();
62 } 70 }
63 71
64 GamepadPlatformDataFetcherWin::~GamepadPlatformDataFetcherWin() { 72 GamepadPlatformDataFetcherWin::~GamepadPlatformDataFetcherWin() {
73 raw_input_fetcher_->StopMonitor();
65 } 74 }
66 75
67 void GamepadPlatformDataFetcherWin::OnAddedToProvider() { 76 int GamepadPlatformDataFetcherWin::FirstAvailableGamepadId() const {
68 xinput_dll_.Reset(base::LoadNativeLibrary( 77 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
69 base::FilePath(FILE_PATH_LITERAL("xinput1_3.dll")), nullptr)); 78 if (platform_pad_state_[i].status == DISCONNECTED)
70 xinput_available_ = GetXInputDllFunctions(); 79 return i;
80 }
81 return -1;
82 }
83
84 bool GamepadPlatformDataFetcherWin::HasXInputGamepad(int index) const {
85 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
86 if (platform_pad_state_[i].status == XINPUT_CONNECTED &&
87 platform_pad_state_[i].xinput_index == index)
88 return true;
89 }
90 return false;
91 }
92
93 bool GamepadPlatformDataFetcherWin::HasRawInputGamepad(
94 const HANDLE handle) const {
95 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
96 if (platform_pad_state_[i].status == RAWINPUT_CONNECTED &&
97 platform_pad_state_[i].raw_input_handle == handle)
98 return true;
99 }
100 return false;
71 } 101 }
72 102
73 void GamepadPlatformDataFetcherWin::EnumerateDevices() { 103 void GamepadPlatformDataFetcherWin::EnumerateDevices() {
74 TRACE_EVENT0("GAMEPAD", "EnumerateDevices"); 104 TRACE_EVENT0("GAMEPAD", "EnumerateDevices");
75 105
76 if (xinput_available_) { 106 // Mark all disconnected pads DISCONNECTED.
77 for (size_t i = 0; i < XUSER_MAX_COUNT; ++i) { 107 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
78 // Check to see if the xinput device is connected 108 if (!pad_state_[i].data.connected)
79 XINPUT_CAPABILITIES caps; 109 platform_pad_state_[i].status = DISCONNECTED;
80 DWORD res = xinput_get_capabilities_(i, XINPUT_FLAG_GAMEPAD, &caps); 110 }
81 xinput_connected_[i] = (res == ERROR_SUCCESS); 111
82 if (!xinput_connected_[i]) 112 for (size_t i = 0; i < XUSER_MAX_COUNT; ++i) {
113 if (HasXInputGamepad(i))
114 continue;
115 int pad_index = FirstAvailableGamepadId();
116 if (pad_index == -1)
117 return; // We can't add any more gamepads.
118 WebGamepad& pad = pad_state_[pad_index].data;
119 if (xinput_available_ && GetXInputPadConnectivity(i, &pad)) {
120 platform_pad_state_[pad_index].status = XINPUT_CONNECTED;
121 platform_pad_state_[pad_index].xinput_index = i;
122 pad_state_[pad_index].mapper = NULL;
123 pad_state_[pad_index].axis_mask = 0;
124 pad_state_[pad_index].button_mask = 0;
125 }
126 }
127
128 if (raw_input_fetcher_->Available()) {
129 std::vector<RawGamepadInfo*> raw_inputs =
130 raw_input_fetcher_->EnumerateDevices();
131 for (size_t i = 0; i < raw_inputs.size(); ++i) {
132 RawGamepadInfo* gamepad = raw_inputs[i];
133 if (gamepad->buttons_length == 0 && gamepad->axes_length == 0)
83 continue; 134 continue;
135 if (HasRawInputGamepad(gamepad->handle))
136 continue;
137 int pad_index = FirstAvailableGamepadId();
138 if (pad_index == -1)
139 return;
140 WebGamepad& pad = pad_state_[pad_index].data;
141 pad.connected = true;
142 PadState& state = pad_state_[pad_index];
143 PlatformPadState& platform_state = platform_pad_state_[pad_index];
144 platform_state.status = RAWINPUT_CONNECTED;
145 platform_state.raw_input_handle = gamepad->handle;
84 146
85 PadState* state = provider()->GetPadState(GAMEPAD_SOURCE_WIN_XINPUT, i); 147 std::string vendor = base::StringPrintf("%04x", gamepad->vendor_id);
86 if (!state) 148 std::string product = base::StringPrintf("%04x", gamepad->product_id);
87 continue; // No slot available for this gamepad. 149 state.mapper = GetGamepadStandardMappingFunction(vendor, product);
150 state.axis_mask = 0;
151 state.button_mask = 0;
88 152
89 WebGamepad& pad = state->data; 153 swprintf(pad.id, WebGamepad::idLengthCap,
154 L"%ls (%lsVendor: %04x Product: %04x)",
155 gamepad->id, state.mapper ? L"STANDARD GAMEPAD " : L"",
156 gamepad->vendor_id, gamepad->product_id);
90 157
91 if (state->active_state == GAMEPAD_NEWLY_ACTIVE) { 158 if (state.mapper)
92 // This is the first time we've seen this device, so do some one-time
93 // initialization
94 pad.connected = true;
95 swprintf(pad.id,
96 WebGamepad::idLengthCap,
97 L"Xbox 360 Controller (XInput STANDARD %ls)",
98 GamepadSubTypeName(caps.SubType));
99 swprintf(pad.mapping, WebGamepad::mappingLengthCap, L"standard"); 159 swprintf(pad.mapping, WebGamepad::mappingLengthCap, L"standard");
100 } 160 else
161 pad.mapping[0] = 0;
101 } 162 }
102 } 163 }
103 } 164 }
104 165
105 void GamepadPlatformDataFetcherWin::GetGamepadData(bool devices_changed_hint) { 166 void GamepadPlatformDataFetcherWin::GetGamepadData(WebGamepads* pads,
167 bool devices_changed_hint) {
106 TRACE_EVENT0("GAMEPAD", "GetGamepadData"); 168 TRACE_EVENT0("GAMEPAD", "GetGamepadData");
107 169
108 if (!xinput_available_) 170 if (!xinput_available_ &&
171 !raw_input_fetcher_->Available()) {
172 pads->length = 0;
109 return; 173 return;
174 }
110 175
111 // A note on XInput devices: 176 // A note on XInput devices:
112 // If we got notification that system devices have been updated, then 177 // If we got notification that system devices have been updated, then
113 // run GetCapabilities to update the connected status and the device 178 // run GetCapabilities to update the connected status and the device
114 // identifier. It can be slow to do to both GetCapabilities and 179 // identifier. It can be slow to do to both GetCapabilities and
115 // GetState on unconnected devices, so we want to avoid a 2-5ms pause 180 // GetState on unconnected devices, so we want to avoid a 2-5ms pause
116 // here by only doing this when the devices are updated (despite 181 // here by only doing this when the devices are updated (despite
117 // documentation claiming it's OK to call it any time). 182 // documentation claiming it's OK to call it any time).
118 if (devices_changed_hint) 183 if (devices_changed_hint)
119 EnumerateDevices(); 184 EnumerateDevices();
120 185
121 for (size_t i = 0; i < XUSER_MAX_COUNT; ++i) { 186 pads->length = 0;
122 if (xinput_connected_[i]) 187
123 GetXInputPadData(i); 188 for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
189 // We rely on device_changed and GetCapabilities to tell us that
190 // something's been connected, but we will mark as disconnected if
191 // Get___PadState returns that we've lost the pad.
192 if (!pad_state_[i].data.connected)
193 continue;
194
195 if (platform_pad_state_[i].status == XINPUT_CONNECTED)
196 GetXInputPadData(i, &pad_state_[i].data);
197 else if (platform_pad_state_[i].status == RAWINPUT_CONNECTED)
198 GetRawInputPadData(i, &pad_state_[i].data);
199
200 MapAndSanitizeGamepadData(&pad_state_[i], &pads->items[i]);
201
202 if (pads->items[i].connected)
203 pads->length++;
124 } 204 }
125 } 205 }
126 206
127 void GamepadPlatformDataFetcherWin::GetXInputPadData(int i) { 207 void GamepadPlatformDataFetcherWin::PauseHint(bool pause) {
128 PadState* pad_state = provider()->GetPadState(GAMEPAD_SOURCE_WIN_XINPUT, i); 208 if (pause)
129 if (!pad_state) 209 raw_input_fetcher_->StopMonitor();
130 return; 210 else
211 raw_input_fetcher_->StartMonitor();
212 }
131 213
132 WebGamepad& pad = pad_state->data; 214 bool GamepadPlatformDataFetcherWin::GetXInputPadConnectivity(
215 int i,
216 WebGamepad* pad) const {
217 DCHECK(pad);
218 TRACE_EVENT1("GAMEPAD", "GetXInputPadConnectivity", "id", i);
219 XINPUT_CAPABILITIES caps;
220 DWORD res = xinput_get_capabilities_(i, XINPUT_FLAG_GAMEPAD, &caps);
221 if (res == ERROR_DEVICE_NOT_CONNECTED) {
222 pad->connected = false;
223 return false;
224 } else {
225 pad->connected = true;
226 swprintf(pad->id,
227 WebGamepad::idLengthCap,
228 L"Xbox 360 Controller (XInput STANDARD %ls)",
229 GamepadSubTypeName(caps.SubType));
230 swprintf(pad->mapping, WebGamepad::mappingLengthCap, L"standard");
231 return true;
232 }
233 }
133 234
235 void GamepadPlatformDataFetcherWin::GetXInputPadData(
236 int i,
237 WebGamepad* pad) {
134 XINPUT_STATE state; 238 XINPUT_STATE state;
135 memset(&state, 0, sizeof(XINPUT_STATE)); 239 memset(&state, 0, sizeof(XINPUT_STATE));
136 TRACE_EVENT_BEGIN1("GAMEPAD", "XInputGetState", "id", i); 240 TRACE_EVENT_BEGIN1("GAMEPAD", "XInputGetState", "id", i);
137 DWORD dwResult = xinput_get_state_(i, &state); 241 DWORD dwResult = xinput_get_state_(platform_pad_state_[i].xinput_index,
242 &state);
138 TRACE_EVENT_END1("GAMEPAD", "XInputGetState", "id", i); 243 TRACE_EVENT_END1("GAMEPAD", "XInputGetState", "id", i);
139 244
140 if (dwResult == ERROR_SUCCESS) { 245 if (dwResult == ERROR_SUCCESS) {
141 pad.timestamp = state.dwPacketNumber; 246 pad->timestamp = state.dwPacketNumber;
142 pad.buttonsLength = 0; 247 pad->buttonsLength = 0;
143 WORD val = state.Gamepad.wButtons; 248 WORD val = state.Gamepad.wButtons;
144 #define ADD(b) pad.buttons[pad.buttonsLength].pressed = (val & (b)) != 0; \ 249 #define ADD(b) pad->buttons[pad->buttonsLength].pressed = (val & (b)) != 0; \
145 pad.buttons[pad.buttonsLength++].value = ((val & (b)) ? 1.f : 0.f); 250 pad->buttons[pad->buttonsLength++].value = ((val & (b)) ? 1.f : 0.f);
146 ADD(XINPUT_GAMEPAD_A); 251 ADD(XINPUT_GAMEPAD_A);
147 ADD(XINPUT_GAMEPAD_B); 252 ADD(XINPUT_GAMEPAD_B);
148 ADD(XINPUT_GAMEPAD_X); 253 ADD(XINPUT_GAMEPAD_X);
149 ADD(XINPUT_GAMEPAD_Y); 254 ADD(XINPUT_GAMEPAD_Y);
150 ADD(XINPUT_GAMEPAD_LEFT_SHOULDER); 255 ADD(XINPUT_GAMEPAD_LEFT_SHOULDER);
151 ADD(XINPUT_GAMEPAD_RIGHT_SHOULDER); 256 ADD(XINPUT_GAMEPAD_RIGHT_SHOULDER);
152 257
153 pad.buttons[pad.buttonsLength].pressed = 258 pad->buttons[pad->buttonsLength].pressed =
154 state.Gamepad.bLeftTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD; 259 state.Gamepad.bLeftTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD;
155 pad.buttons[pad.buttonsLength++].value = 260 pad->buttons[pad->buttonsLength++].value =
156 state.Gamepad.bLeftTrigger / 255.f; 261 state.Gamepad.bLeftTrigger / 255.f;
157 262
158 pad.buttons[pad.buttonsLength].pressed = 263 pad->buttons[pad->buttonsLength].pressed =
159 state.Gamepad.bRightTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD; 264 state.Gamepad.bRightTrigger >= XINPUT_GAMEPAD_TRIGGER_THRESHOLD;
160 pad.buttons[pad.buttonsLength++].value = 265 pad->buttons[pad->buttonsLength++].value =
161 state.Gamepad.bRightTrigger / 255.f; 266 state.Gamepad.bRightTrigger / 255.f;
162 267
163 ADD(XINPUT_GAMEPAD_BACK); 268 ADD(XINPUT_GAMEPAD_BACK);
164 ADD(XINPUT_GAMEPAD_START); 269 ADD(XINPUT_GAMEPAD_START);
165 ADD(XINPUT_GAMEPAD_LEFT_THUMB); 270 ADD(XINPUT_GAMEPAD_LEFT_THUMB);
166 ADD(XINPUT_GAMEPAD_RIGHT_THUMB); 271 ADD(XINPUT_GAMEPAD_RIGHT_THUMB);
167 ADD(XINPUT_GAMEPAD_DPAD_UP); 272 ADD(XINPUT_GAMEPAD_DPAD_UP);
168 ADD(XINPUT_GAMEPAD_DPAD_DOWN); 273 ADD(XINPUT_GAMEPAD_DPAD_DOWN);
169 ADD(XINPUT_GAMEPAD_DPAD_LEFT); 274 ADD(XINPUT_GAMEPAD_DPAD_LEFT);
170 ADD(XINPUT_GAMEPAD_DPAD_RIGHT); 275 ADD(XINPUT_GAMEPAD_DPAD_RIGHT);
171 #undef ADD 276 #undef ADD
172 pad.axesLength = 0; 277 pad->axesLength = 0;
173 278
174 float value = 0.0; 279 float value = 0.0;
175 #define ADD(a, factor) value = factor * NormalizeXInputAxis(a); \ 280 #define ADD(a, factor) value = factor * NormalizeXInputAxis(a); \
176 pad.axes[pad.axesLength++] = value; 281 pad->axes[pad->axesLength++] = value;
177 282
178 // XInput are +up/+right, -down/-left, we want -up/-left. 283 // XInput are +up/+right, -down/-left, we want -up/-left.
179 ADD(state.Gamepad.sThumbLX, 1); 284 ADD(state.Gamepad.sThumbLX, 1);
180 ADD(state.Gamepad.sThumbLY, -1); 285 ADD(state.Gamepad.sThumbLY, -1);
181 ADD(state.Gamepad.sThumbRX, 1); 286 ADD(state.Gamepad.sThumbRX, 1);
182 ADD(state.Gamepad.sThumbRY, -1); 287 ADD(state.Gamepad.sThumbRY, -1);
183 #undef ADD 288 #undef ADD
289 } else {
290 pad->connected = false;
184 } 291 }
185 } 292 }
186 293
294 void GamepadPlatformDataFetcherWin::GetRawInputPadData(
295 int index,
296 WebGamepad* pad) {
297 RawGamepadInfo* gamepad = raw_input_fetcher_->GetGamepadInfo(
298 platform_pad_state_[index].raw_input_handle);
299 if (!gamepad) {
300 pad->connected = false;
301 return;
302 }
303
304 pad->timestamp = gamepad->report_id;
305 pad->buttonsLength = gamepad->buttons_length;
306 pad->axesLength = gamepad->axes_length;
307
308 for (unsigned int i = 0; i < pad->buttonsLength; i++) {
309 pad->buttons[i].pressed = gamepad->buttons[i];
310 pad->buttons[i].value = gamepad->buttons[i] ? 1.0 : 0.0;
311 }
312
313 for (unsigned int i = 0; i < pad->axesLength; i++)
314 pad->axes[i] = gamepad->axes[i].value;
315 }
316
187 bool GamepadPlatformDataFetcherWin::GetXInputDllFunctions() { 317 bool GamepadPlatformDataFetcherWin::GetXInputDllFunctions() {
188 xinput_get_capabilities_ = NULL; 318 xinput_get_capabilities_ = NULL;
189 xinput_get_state_ = NULL; 319 xinput_get_state_ = NULL;
190 xinput_enable_ = reinterpret_cast<XInputEnableFunc>( 320 xinput_enable_ = reinterpret_cast<XInputEnableFunc>(
191 xinput_dll_.GetFunctionPointer("XInputEnable")); 321 xinput_dll_.GetFunctionPointer("XInputEnable"));
192 if (!xinput_enable_) 322 if (!xinput_enable_)
193 return false; 323 return false;
194 xinput_get_capabilities_ = reinterpret_cast<XInputGetCapabilitiesFunc>( 324 xinput_get_capabilities_ = reinterpret_cast<XInputGetCapabilitiesFunc>(
195 xinput_dll_.GetFunctionPointer("XInputGetCapabilities")); 325 xinput_dll_.GetFunctionPointer("XInputGetCapabilities"));
196 if (!xinput_get_capabilities_) 326 if (!xinput_get_capabilities_)
197 return false; 327 return false;
198 xinput_get_state_ = reinterpret_cast<XInputGetStateFunc>( 328 xinput_get_state_ = reinterpret_cast<XInputGetStateFunc>(
199 xinput_dll_.GetFunctionPointer("XInputGetState")); 329 xinput_dll_.GetFunctionPointer("XInputGetState"));
200 if (!xinput_get_state_) 330 if (!xinput_get_state_)
201 return false; 331 return false;
202 xinput_enable_(true); 332 xinput_enable_(true);
203 return true; 333 return true;
204 } 334 }
205 335
206 } // namespace content 336 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/gamepad/gamepad_platform_data_fetcher_win.h ('k') | content/browser/gamepad/gamepad_provider.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698