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

Side by Side Diff: ui/base/x/x11_util.cc

Issue 11725005: Checks the possibility of overscans from EDID extension data. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 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 | Annotate | Revision Log
« no previous file with comments | « ui/base/x/x11_util.h ('k') | ui/base/x/x11_util_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 // This file defines utility functions for X11 (Linux only). This code has been 5 // This file defines utility functions for X11 (Linux only). This code has been
6 // ported from XCB since we can't use XCB on Ubuntu while its 32-bit support 6 // ported from XCB since we can't use XCB on Ubuntu while its 32-bit support
7 // remains woefully incomplete. 7 // remains woefully incomplete.
8 8
9 #include "ui/base/x/x11_util.h" 9 #include "ui/base/x/x11_util.h"
10 10
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 } 324 }
325 325
326 bool IsShapeAvailable() { 326 bool IsShapeAvailable() {
327 int dummy; 327 int dummy;
328 static bool is_shape_available = 328 static bool is_shape_available =
329 XShapeQueryExtension(ui::GetXDisplay(), &dummy, &dummy); 329 XShapeQueryExtension(ui::GetXDisplay(), &dummy, &dummy);
330 return is_shape_available; 330 return is_shape_available;
331 331
332 } 332 }
333 333
334 // Get the EDID data from the |output| and stores to |prop|. |nitem| will store
335 // the number of characters |prop| will have. It doesn't take the ownership of
336 // |prop|, so caller must release it by XFree().
337 // Returns true if EDID property is successfully obtained. Otherwise returns
338 // false and does not touch |prop| and |nitems|.
339 bool GetEDIDProperty(XID output, unsigned long* nitems, unsigned char** prop) {
340 if (!IsRandRAvailable())
341 return false;
342
343 static Atom edid_property = GetAtom(RR_PROPERTY_RANDR_EDID);
344
345 Display* display = GetXDisplay();
346
347 bool has_edid_property = false;
348 int num_properties = 0;
349 Atom* properties = XRRListOutputProperties(display, output, &num_properties);
350 for (int i = 0; i < num_properties; ++i) {
351 if (properties[i] == edid_property) {
352 has_edid_property = true;
353 break;
354 }
355 }
356 XFree(properties);
357 if (!has_edid_property)
358 return false;
359
360 Atom actual_type;
361 int actual_format;
362 unsigned long bytes_after;
363 XRRGetOutputProperty(display,
364 output,
365 edid_property,
366 0, // offset
367 128, // length
368 false, // _delete
369 false, // pending
370 AnyPropertyType, // req_type
371 &actual_type,
372 &actual_format,
373 nitems,
374 &bytes_after,
375 prop);
376 DCHECK_EQ(XA_INTEGER, actual_type);
377 DCHECK_EQ(8, actual_format);
378 return true;
379 }
380
334 } // namespace 381 } // namespace
335 382
336 bool XDisplayExists() { 383 bool XDisplayExists() {
337 return (GetXDisplay() != NULL); 384 return (GetXDisplay() != NULL);
338 } 385 }
339 386
340 Display* GetXDisplay() { 387 Display* GetXDisplay() {
341 return base::MessagePumpForUI::GetDefaultXDisplay(); 388 return base::MessagePumpForUI::GetDefaultXDisplay();
342 } 389 }
343 390
(...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after
1241 for (int i = 0; i < screen_resources->noutput; ++i) 1288 for (int i = 0; i < screen_resources->noutput; ++i)
1242 outputs->push_back(screen_resources->outputs[i]); 1289 outputs->push_back(screen_resources->outputs[i]);
1243 XRRFreeScreenResources(screen_resources); 1290 XRRFreeScreenResources(screen_resources);
1244 return true; 1291 return true;
1245 } 1292 }
1246 1293
1247 bool GetOutputDeviceData(XID output, 1294 bool GetOutputDeviceData(XID output,
1248 uint16* manufacturer_id, 1295 uint16* manufacturer_id,
1249 uint32* serial_number, 1296 uint32* serial_number,
1250 std::string* human_readable_name) { 1297 std::string* human_readable_name) {
1251 if (!IsRandRAvailable()) 1298 unsigned long nitems = 0;
1299 unsigned char *prop = NULL;
1300 if (!GetEDIDProperty(output, &nitems, &prop))
1252 return false; 1301 return false;
1253 1302
1254 static Atom edid_property = GetAtom(RR_PROPERTY_RANDR_EDID); 1303 bool result = ParseOutputDeviceData(
1304 prop, nitems, manufacturer_id, serial_number, human_readable_name);
1305 XFree(prop);
1306 return result;
1307 }
1255 1308
1256 Display* display = GetXDisplay(); 1309 bool ParseOutputDeviceData(const unsigned char* prop,
1257 1310 unsigned long nitems,
1258 bool has_edid_property = false; 1311 uint16* manufacturer_id,
1259 int num_properties = 0; 1312 uint32* serial_number,
1260 Atom* properties = XRRListOutputProperties(display, output, &num_properties); 1313 std::string* human_readable_name) {
1261 for (int i = 0; i < num_properties; ++i) {
1262 if (properties[i] == edid_property) {
1263 has_edid_property = true;
1264 break;
1265 }
1266 }
1267 XFree(properties);
1268 if (!has_edid_property)
1269 return false;
1270
1271 Atom actual_type;
1272 int actual_format;
1273 unsigned long nitems;
1274 unsigned long bytes_after;
1275 unsigned char *prop;
1276 XRRGetOutputProperty(display,
1277 output,
1278 edid_property,
1279 0, // offset
1280 128, // length
1281 false, // _delete
1282 false, // pending
1283 AnyPropertyType, // req_type
1284 &actual_type,
1285 &actual_format,
1286 &nitems,
1287 &bytes_after,
1288 &prop);
1289 DCHECK_EQ(XA_INTEGER, actual_type);
1290 DCHECK_EQ(8, actual_format);
1291
1292 // See http://en.wikipedia.org/wiki/Extended_display_identification_data 1314 // See http://en.wikipedia.org/wiki/Extended_display_identification_data
1293 // for the details of EDID data format. We use the following data: 1315 // for the details of EDID data format. We use the following data:
1294 // bytes 8-9: manufacturer EISA ID, in big-endian 1316 // bytes 8-9: manufacturer EISA ID, in big-endian
1295 // bytes 12-15: represents serial number, in little-endian 1317 // bytes 12-15: represents serial number, in little-endian
1296 // bytes 54-125: four descriptors (18-bytes each) which may contain 1318 // bytes 54-125: four descriptors (18-bytes each) which may contain
1297 // the display name. 1319 // the display name.
1298 const unsigned int kManufacturerOffset = 8; 1320 const unsigned int kManufacturerOffset = 8;
1299 const unsigned int kManufacturerLength = 2; 1321 const unsigned int kManufacturerLength = 2;
1300 const unsigned int kSerialNumberOffset = 12; 1322 const unsigned int kSerialNumberOffset = 12;
1301 const unsigned int kSerialNumberLength = 4; 1323 const unsigned int kSerialNumberLength = 4;
1302 const unsigned int kDescriptorOffset = 54; 1324 const unsigned int kDescriptorOffset = 54;
1303 const unsigned int kNumDescriptors = 4; 1325 const unsigned int kNumDescriptors = 4;
1304 const unsigned int kDescriptorLength = 18; 1326 const unsigned int kDescriptorLength = 18;
1305 // The specifier types. 1327 // The specifier types.
1306 const unsigned char kMonitorNameDescriptor = 0xfc; 1328 const unsigned char kMonitorNameDescriptor = 0xfc;
1307 1329
1308 if (manufacturer_id) { 1330 if (manufacturer_id) {
1309 if (nitems < kManufacturerOffset + kManufacturerLength) { 1331 if (nitems < kManufacturerOffset + kManufacturerLength)
1310 XFree(prop);
1311 return false; 1332 return false;
1312 } 1333
1313 *manufacturer_id = *reinterpret_cast<uint16*>(prop + kManufacturerOffset); 1334 *manufacturer_id =
1335 *reinterpret_cast<const uint16*>(prop + kManufacturerOffset);
1314 #if defined(ARCH_CPU_LITTLE_ENDIAN) 1336 #if defined(ARCH_CPU_LITTLE_ENDIAN)
1315 *manufacturer_id = base::ByteSwap(*manufacturer_id); 1337 *manufacturer_id = base::ByteSwap(*manufacturer_id);
1316 #endif 1338 #endif
1317 } 1339 }
1318 1340
1319 if (serial_number) { 1341 if (serial_number) {
1320 if (nitems < kSerialNumberOffset + kSerialNumberLength) { 1342 if (nitems < kSerialNumberOffset + kSerialNumberLength)
1321 XFree(prop);
1322 return false; 1343 return false;
1323 } 1344
1324 *serial_number = base::ByteSwapToLE32( 1345 *serial_number = base::ByteSwapToLE32(
1325 *reinterpret_cast<uint32*>(prop + kSerialNumberOffset)); 1346 *reinterpret_cast<const uint32*>(prop + kSerialNumberOffset));
1326 } 1347 }
1327 1348
1328 if (!human_readable_name) { 1349 if (!human_readable_name)
1329 XFree(prop);
1330 return true; 1350 return true;
1331 }
1332 1351
1333 human_readable_name->clear(); 1352 human_readable_name->clear();
1334 for (unsigned int i = 0; i < kNumDescriptors; ++i) { 1353 for (unsigned int i = 0; i < kNumDescriptors; ++i) {
1335 if (nitems < kDescriptorOffset + (i + 1) * kDescriptorLength) { 1354 if (nitems < kDescriptorOffset + (i + 1) * kDescriptorLength)
1336 break; 1355 break;
1337 }
1338 1356
1339 unsigned char* desc_buf = prop + kDescriptorOffset + i * kDescriptorLength; 1357 const unsigned char* desc_buf =
1358 prop + kDescriptorOffset + i * kDescriptorLength;
1340 // If the descriptor contains the display name, it has the following 1359 // If the descriptor contains the display name, it has the following
1341 // structure: 1360 // structure:
1342 // bytes 0-2, 4: \0 1361 // bytes 0-2, 4: \0
1343 // byte 3: descriptor type, defined above. 1362 // byte 3: descriptor type, defined above.
1344 // bytes 5-17: text data, ending with \r, padding with spaces 1363 // bytes 5-17: text data, ending with \r, padding with spaces
1345 // we should check bytes 0-2 and 4, since it may have other values in 1364 // we should check bytes 0-2 and 4, since it may have other values in
1346 // case that the descriptor contains other type of data. 1365 // case that the descriptor contains other type of data.
1347 if (desc_buf[0] == 0 && desc_buf[1] == 0 && desc_buf[2] == 0 && 1366 if (desc_buf[0] == 0 && desc_buf[1] == 0 && desc_buf[2] == 0 &&
1348 desc_buf[4] == 0) { 1367 desc_buf[4] == 0) {
1349 if (desc_buf[3] == kMonitorNameDescriptor) { 1368 if (desc_buf[3] == kMonitorNameDescriptor) {
1350 std::string found_name( 1369 std::string found_name(
1351 reinterpret_cast<char*>(desc_buf + 5), kDescriptorLength - 5); 1370 reinterpret_cast<const char*>(desc_buf + 5), kDescriptorLength - 5);
1352 TrimWhitespaceASCII(found_name, TRIM_TRAILING, human_readable_name); 1371 TrimWhitespaceASCII(found_name, TRIM_TRAILING, human_readable_name);
1353 break; 1372 break;
1354 } 1373 }
1355 } 1374 }
1356 } 1375 }
1357 1376
1358 XFree(prop);
1359
1360 if (human_readable_name->empty()) 1377 if (human_readable_name->empty())
1361 return false; 1378 return false;
1362 1379
1363 // Verify if the |human_readable_name| consists of printable characters only. 1380 // Verify if the |human_readable_name| consists of printable characters only.
1364 for (size_t i = 0; i < human_readable_name->size(); ++i) { 1381 for (size_t i = 0; i < human_readable_name->size(); ++i) {
1365 char c = (*human_readable_name)[i]; 1382 char c = (*human_readable_name)[i];
1366 if (!isascii(c) || !isprint(c)) { 1383 if (!isascii(c) || !isprint(c)) {
1367 human_readable_name->clear(); 1384 human_readable_name->clear();
1368 return false; 1385 return false;
1369 } 1386 }
1370 } 1387 }
1371 1388
1372 return true; 1389 return true;
1373 } 1390 }
1374 1391
1392 bool GetOutputOverscanFlag(XID output, bool* flag) {
1393 unsigned long nitems = 0;
1394 unsigned char *prop = NULL;
1395 if (!GetEDIDProperty(output, &nitems, &prop))
1396 return false;
1397
1398 bool found = ParseOutputOverscanFlag(prop, nitems, flag);
1399 XFree(prop);
1400 return found;
1401 }
1402
1403 bool ParseOutputOverscanFlag(const unsigned char* prop,
1404 unsigned long nitems,
1405 bool *flag) {
1406 // See http://en.wikipedia.org/wiki/Extended_display_identification_data
1407 // for the extension format of EDID. Also see EIA/CEA-861 spec for
1408 // the format of the extensions and how video capability is encoded.
1409 // - byte 0: tag. should be 02h.
1410 // - byte 1: revision. only cares revision 3 (03h).
1411 // - byte 4-: data block.
1412 const unsigned int kExtensionBase = 128;
1413 const unsigned int kExtensionSize = 128;
1414 const unsigned int kNumExtensionsOffset = 126;
1415 const unsigned int kDataBlockOffset = 4;
1416 const unsigned char kCEAExtensionTag = '\x02';
1417 const unsigned char kExpectedExtensionRevision = '\x03';
1418 const unsigned char kExtendedTag = 7;
1419 const unsigned char kExtendedVideoCapabilityTag = 0;
1420 const unsigned int kPTOverscan = 4;
1421 const unsigned int kITOverscan = 2;
1422 const unsigned int kCEOverscan = 0;
1423
1424 if (nitems <= kNumExtensionsOffset)
1425 return false;
1426
1427 unsigned char num_extensions = prop[kNumExtensionsOffset];
1428
1429 for (size_t i = 0; i < num_extensions; ++i) {
1430 // Skip parsing the whole extension if size is not enough.
1431 if (nitems <= kExtensionBase + (i + 1) * kExtensionSize)
1432 break;
1433
1434 const unsigned char* extension = prop + kExtensionBase + i * kExtensionSize;
1435 unsigned char tag = extension[0];
1436 unsigned char revision = extension[1];
1437 if (tag != kCEAExtensionTag || revision != kExpectedExtensionRevision)
1438 continue;
1439
1440 unsigned char timing_descriptors_start =
1441 std::min(extension[2], static_cast<unsigned char>(kExtensionSize));
1442 const unsigned char* data_block = extension + kDataBlockOffset;
1443 while (data_block < extension + timing_descriptors_start) {
1444 // A data block is encoded as:
1445 // - byte 1 high 3 bits: tag. '07' for extended tags.
1446 // - byte 1 remaining bits: the length of data block.
1447 // - byte 2: the extended tag. '0' for video capability.
1448 // - byte 3: the capability.
1449 unsigned char tag = data_block[0] >> 5;
1450 unsigned char payload_length = data_block[0] & 0x1f;
1451 if (static_cast<unsigned long>(data_block + payload_length - prop) >
1452 nitems)
1453 break;
1454
1455 if (tag != kExtendedTag && payload_length < 2) {
1456 data_block += payload_length + 1;
1457 continue;
1458 }
1459
1460 unsigned char extended_tag_code = data_block[1];
1461 if (extended_tag_code != kExtendedVideoCapabilityTag) {
1462 data_block += payload_length;
1463 continue;
1464 }
1465
1466 // The difference between preferred, IT, and CE video formats
1467 // doesn't matter. Sets |flag| to true if any of these flags are true.
1468 if ((data_block[2] & (1 << kPTOverscan)) ||
1469 (data_block[2] & (1 << kITOverscan)) ||
1470 (data_block[2] & (1 << kCEOverscan))) {
1471 *flag = true;
1472 } else {
1473 *flag = false;
1474 }
1475 return true;
1476 }
1477 }
1478
1479 return false;
1480 }
1481
1375 std::vector<std::string> GetDisplayNames(const std::vector<XID>& output_ids) { 1482 std::vector<std::string> GetDisplayNames(const std::vector<XID>& output_ids) {
1376 std::vector<std::string> names; 1483 std::vector<std::string> names;
1377 for (size_t i = 0; i < output_ids.size(); ++i) { 1484 for (size_t i = 0; i < output_ids.size(); ++i) {
1378 std::string display_name; 1485 std::string display_name;
1379 if (GetOutputDeviceData(output_ids[i], NULL, NULL, &display_name)) 1486 if (GetOutputDeviceData(output_ids[i], NULL, NULL, &display_name))
1380 names.push_back(display_name); 1487 names.push_back(display_name);
1381 } 1488 }
1382 return names; 1489 return names;
1383 } 1490 }
1384 1491
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
1721 << "request_code " << static_cast<int>(error_event.request_code) << ", " 1828 << "request_code " << static_cast<int>(error_event.request_code) << ", "
1722 << "minor_code " << static_cast<int>(error_event.minor_code) 1829 << "minor_code " << static_cast<int>(error_event.minor_code)
1723 << " (" << request_str << ")"; 1830 << " (" << request_str << ")";
1724 } 1831 }
1725 1832
1726 // ---------------------------------------------------------------------------- 1833 // ----------------------------------------------------------------------------
1727 // End of x11_util_internal.h 1834 // End of x11_util_internal.h
1728 1835
1729 1836
1730 } // namespace ui 1837 } // namespace ui
OLDNEW
« no previous file with comments | « ui/base/x/x11_util.h ('k') | ui/base/x/x11_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698