Commit 499474ed authored by David Redondo's avatar David Redondo 🏎
Browse files

Fetch and parse EDIDs on X11

This allows us to get more information about the outputs like vendor
and model and for example provide them to effects which might find
the extra info useful.
parent ff9bfc2e
......@@ -67,6 +67,7 @@ Atoms::Atoms()
, incr(QByteArrayLiteral("INCR"))
, wl_selection(QByteArrayLiteral("WL_SELECTION"))
, primary(QByteArrayLiteral("PRIMARY"))
, edid(QByteArrayLiteral("EDID"))
, m_dtSmWindowInfo(QByteArrayLiteral("_DT_SM_WINDOW_INFO"))
, m_motifSupport(QByteArrayLiteral("_MOTIF_WM_INFO"))
, m_helpersRetrieved(false)
......
......@@ -76,6 +76,7 @@ public:
Xcb::Atom incr;
Xcb::Atom wl_selection;
Xcb::Atom primary;
Xcb::Atom edid;
/**
* @internal
......
......@@ -7,7 +7,6 @@ set(DRM_SOURCES
drm_object_plane.cpp
drm_output.cpp
drm_buffer.cpp
edid.cpp
logging.cpp
scene_qpainter_drm_backend.cpp
drm_gpu.cpp
......
......@@ -16,8 +16,8 @@
#include "drm_object.h"
#include "drm_pointer.h"
#include "edid.h"
#include "output.h"
#include "utils/edid.h"
namespace KWin
{
......
......@@ -10,6 +10,7 @@
#include <config-kwin.h>
#include "atoms.h"
#include "edge.h"
#include "session.h"
#include "windowselector.h"
......@@ -32,6 +33,7 @@
#include "renderloop.h"
#include "screenedges_filter.h"
#include "utils/c_ptr.h"
#include "utils/edid.h"
#include "utils/xcbutils.h"
#include "window.h"
#include "workspace.h"
......@@ -496,9 +498,11 @@ void X11StandalonePlatform::doUpdateOutputs()
xcb_randr_output_t *outputs = info.outputs();
QVector<Xcb::RandR::OutputInfo> outputInfos(outputs ? resources->num_outputs : 0);
QVector<Xcb::RandR::OutputProperty> edids(outputs ? resources->num_outputs : 0);
if (outputs) {
for (int i = 0; i < resources->num_outputs; ++i) {
outputInfos[i] = Xcb::RandR::OutputInfo(outputs[i], resources->config_timestamp);
edids[i] = Xcb::RandR::OutputProperty(outputs[i], atoms->edid, XCB_ATOM_INTEGER, 0, 100, false, false);
}
}
......@@ -562,10 +566,22 @@ void X11StandalonePlatform::doUpdateOutputs()
break;
}
output->setInformation(X11Output::Information{
X11Output::Information information{
.name = outputInfo.name(),
.physicalSize = physicalSize,
});
};
bool ok;
if (auto data = edids[i].toByteArray(&ok); ok && !data.isEmpty()) {
if (auto edid = Edid(data, edids[i].data()->num_items); edid.isValid()) {
information.manufacturer = edid.manufacturerString();
information.model = edid.monitorName();
information.serialNumber = edid.serialNumber();
information.edid = data;
}
}
output->setInformation(information);
break;
}
}
......
target_sources(kwin PRIVATE
abstract_opengl_context_attribute_builder.cpp
common.cpp
edid.cpp
egl_context_attribute_builder.cpp
realtime.cpp
subsurfacemonitor.cpp
......
......@@ -9,6 +9,8 @@
#pragma once
#include "kwin_export.h"
#include <QByteArray>
#include <QSize>
......@@ -20,7 +22,7 @@ namespace KWin
*
* http://read.pudn.com/downloads110/ebook/456020/E-EDID%20Standard.pdf
*/
class Edid
class KWIN_EXPORT Edid
{
public:
Edid();
......
......@@ -1355,6 +1355,102 @@ public:
};
XCB_WRAPPER(SetCrtcConfig, xcb_randr_set_crtc_config, xcb_randr_crtc_t, xcb_timestamp_t, xcb_timestamp_t, int16_t, int16_t, xcb_randr_mode_t, uint16_t, uint32_t, const xcb_randr_output_t *)
XCB_WRAPPER_DATA(OutputPropertyData, xcb_randr_get_output_property, xcb_randr_output_t, xcb_atom_t, xcb_atom_t, uint32_t, uint32_t, uint8_t, uint8_t)
/**
* Get an output property.
* @see Property for documentation of member functions
*/
class OutputProperty : public Wrapper<OutputPropertyData, xcb_randr_output_t, xcb_atom_t, xcb_atom_t, uint32_t, uint32_t, uint8_t, uint8_t>
{
public:
OutputProperty() = default;
explicit OutputProperty(xcb_randr_output_t output, xcb_atom_t property, xcb_atom_t type, uint32_t offset, uint32_t length, uint8_t _delete, uint8_t pending)
: Wrapper(output, property, type, offset, length, _delete, pending)
, m_type(type)
{
}
template<typename T>
inline typename std::enable_if<!std::is_pointer<T>::value, T>::type value(T defaultValue = T(), bool *ok = nullptr)
{
T *reply = value<T *>(sizeof(T) * 8, m_type, nullptr, ok);
if (!reply) {
return defaultValue;
}
return reply[0];
}
template<typename T>
inline typename std::enable_if<std::is_pointer<T>::value, T>::type value(T defaultValue = nullptr, bool *ok = nullptr)
{
return value<T>(sizeof(typename std::remove_pointer<T>::type) * 8, m_type, defaultValue, ok);
}
template<typename T>
inline typename std::enable_if<std::is_pointer<T>::value, T>::type value(uint8_t format, xcb_atom_t type, T defaultValue = nullptr, bool *ok = nullptr)
{
if (ok) {
*ok = false;
}
const OutputPropertyData::reply_type *reply = data();
if (!reply) {
return defaultValue;
}
if (reply->type != type) {
return defaultValue;
}
if (reply->format != format) {
return defaultValue;
}
if (ok) {
*ok = true;
}
if (xcb_randr_get_output_property_data_length(reply) == 0) {
return defaultValue;
}
return reinterpret_cast<T>(xcb_randr_get_output_property_data(reply));
}
inline QByteArray toByteArray(uint8_t format = 8, xcb_atom_t type = XCB_ATOM_STRING, bool *ok = nullptr)
{
bool valueOk = false;
const char *reply = value<const char *>(format, type, nullptr, &valueOk);
if (ok) {
*ok = valueOk;
}
if (valueOk && !reply) {
return QByteArray("", 0); // valid, not null, but empty data
} else if (!valueOk) {
return QByteArray(); // Property not found, data empty and null
}
return QByteArray(reply, xcb_randr_get_output_property_data_length(data()));
}
inline QByteArray toByteArray(bool *ok)
{
return toByteArray(8, m_type, ok);
}
inline bool toBool(uint8_t format = 32, xcb_atom_t type = XCB_ATOM_CARDINAL, bool *ok = nullptr)
{
bool *reply = value<bool *>(format, type, nullptr, ok);
if (!reply) {
return false;
}
if (data()->length != 1) {
if (ok) {
*ok = false;
}
return false;
}
return reply[0] != 0;
}
inline bool toBool(bool *ok)
{
return toBool(32, m_type, ok);
}
private:
xcb_atom_t m_type;
};
}
class ExtensionData
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment