1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ui/display/util/x11/edid_parser_x11.h" 6 7 #include <X11/extensions/Xrandr.h> 8 #include <X11/Xatom.h> 9 #include <X11/Xlib.h> 10 11 #include "base/strings/string_util.h" 12 #include "ui/display/util/edid_parser.h" 13 #include "ui/gfx/x/x11_types.h" 14 15 namespace ui { 16 17 namespace { 18 19 bool IsRandRAvailable() { 20 int randr_version_major = 0; 21 int randr_version_minor = 0; 22 static bool is_randr_available = XRRQueryVersion( 23 gfx::GetXDisplay(), &randr_version_major, &randr_version_minor); 24 return is_randr_available; 25 } 26 27 // Get the EDID data from the |output| and stores to |edid|. 28 // Returns true if EDID property is successfully obtained. Otherwise returns 29 // false and does not touch |edid|. 30 bool GetEDIDProperty(XID output, std::vector<uint8_t>* edid) { 31 if (!IsRandRAvailable()) 32 return false; 33 34 Display* display = gfx::GetXDisplay(); 35 36 static Atom edid_property = XInternAtom( 37 gfx::GetXDisplay(), 38 RR_PROPERTY_RANDR_EDID, false); 39 40 bool has_edid_property = false; 41 int num_properties = 0; 42 Atom* properties = XRRListOutputProperties(display, output, &num_properties); 43 for (int i = 0; i < num_properties; ++i) { 44 if (properties[i] == edid_property) { 45 has_edid_property = true; 46 break; 47 } 48 } 49 XFree(properties); 50 if (!has_edid_property) 51 return false; 52 53 Atom actual_type; 54 int actual_format; 55 unsigned long bytes_after; 56 unsigned long nitems = 0; 57 unsigned char* prop = NULL; 58 XRRGetOutputProperty(display, 59 output, 60 edid_property, 61 0, // offset 62 128, // length 63 false, // _delete 64 false, // pending 65 AnyPropertyType, // req_type 66 &actual_type, 67 &actual_format, 68 &nitems, 69 &bytes_after, 70 &prop); 71 DCHECK_EQ(XA_INTEGER, actual_type); 72 DCHECK_EQ(8, actual_format); 73 edid->assign(prop, prop + nitems); 74 XFree(prop); 75 return true; 76 } 77 78 // Gets some useful data from the specified output device, such like 79 // manufacturer's ID, product code, and human readable name. Returns false if it 80 // fails to get those data and doesn't touch manufacturer ID/product code/name. 81 // NULL can be passed for unwanted output parameters. 82 bool GetOutputDeviceData(XID output, 83 uint16_t* manufacturer_id, 84 std::string* human_readable_name) { 85 std::vector<uint8_t> edid; 86 if (!GetEDIDProperty(output, &edid)) 87 return false; 88 89 bool result = ParseOutputDeviceData( 90 edid, manufacturer_id, human_readable_name); 91 return result; 92 } 93 94 } // namespace 95 96 bool GetDisplayId(XID output_id, 97 uint8_t output_index, 98 int64_t* display_id_out) { 99 std::vector<uint8_t> edid; 100 if (!GetEDIDProperty(output_id, &edid)) 101 return false; 102 103 bool result = GetDisplayIdFromEDID(edid, output_index, display_id_out); 104 return result; 105 } 106 107 std::string GetDisplayName(RROutput output) { 108 std::string display_name; 109 GetOutputDeviceData(output, NULL, &display_name); 110 return display_name; 111 } 112 113 bool GetOutputOverscanFlag(RROutput output, bool* flag) { 114 std::vector<uint8_t> edid; 115 if (!GetEDIDProperty(output, &edid)) 116 return false; 117 118 bool found = ParseOutputOverscanFlag(edid, flag); 119 return found; 120 } 121 122 } // namespace ui 123