Add QPlatformScreen::colorSpace()
Added for macOS and X11 screens Task-number: QTBUG-90535 Change-Id: Ifafe7a07ee2abc3c42cd12785db2d7329878375b Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
parent
4e2a942369
commit
fdc7eb80dd
@ -57,6 +57,7 @@
|
|||||||
#include <QtCore/qrect.h>
|
#include <QtCore/qrect.h>
|
||||||
#include <QtCore/qobject.h>
|
#include <QtCore/qobject.h>
|
||||||
|
|
||||||
|
#include <QtGui/qcolorspace.h>
|
||||||
#include <QtGui/qcursor.h>
|
#include <QtGui/qcursor.h>
|
||||||
#include <QtGui/qimage.h>
|
#include <QtGui/qimage.h>
|
||||||
#include <QtGui/qwindowdefs.h>
|
#include <QtGui/qwindowdefs.h>
|
||||||
@ -114,6 +115,7 @@ public:
|
|||||||
|
|
||||||
virtual int depth() const = 0;
|
virtual int depth() const = 0;
|
||||||
virtual QImage::Format format() const = 0;
|
virtual QImage::Format format() const = 0;
|
||||||
|
virtual QColorSpace colorSpace() const { return QColorSpace::SRgb; }
|
||||||
|
|
||||||
virtual QSizeF physicalSize() const;
|
virtual QSizeF physicalSize() const;
|
||||||
virtual QDpi logicalDpi() const;
|
virtual QDpi logicalDpi() const;
|
||||||
|
@ -52,6 +52,9 @@
|
|||||||
#define EDID_OFFSET_SERIAL 0x0c
|
#define EDID_OFFSET_SERIAL 0x0c
|
||||||
#define EDID_PHYSICAL_WIDTH 0x15
|
#define EDID_PHYSICAL_WIDTH 0x15
|
||||||
#define EDID_OFFSET_PHYSICAL_HEIGHT 0x16
|
#define EDID_OFFSET_PHYSICAL_HEIGHT 0x16
|
||||||
|
#define EDID_TRANSFER_FUNCTION 0x17
|
||||||
|
#define EDID_FEATURE_SUPPORT 0x18
|
||||||
|
#define EDID_CHROMATICITIES_BLOCK 0x19
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
@ -152,6 +155,87 @@ bool QEdidParser::parse(const QByteArray &blob)
|
|||||||
// Physical size
|
// Physical size
|
||||||
physicalSize = QSizeF(data[EDID_PHYSICAL_WIDTH], data[EDID_OFFSET_PHYSICAL_HEIGHT]) * 10;
|
physicalSize = QSizeF(data[EDID_PHYSICAL_WIDTH], data[EDID_OFFSET_PHYSICAL_HEIGHT]) * 10;
|
||||||
|
|
||||||
|
// Gamma and transfer function
|
||||||
|
const uint igamma = data[EDID_TRANSFER_FUNCTION];
|
||||||
|
if (igamma != 0xff) {
|
||||||
|
gamma = 1.0 + (igamma / 100.0f);
|
||||||
|
useTables = false;
|
||||||
|
} else {
|
||||||
|
gamma = 0.0; // Defined in DI-EXT
|
||||||
|
useTables = true;
|
||||||
|
}
|
||||||
|
sRgb = data[EDID_FEATURE_SUPPORT] & 0x04;
|
||||||
|
|
||||||
|
// Chromaticities
|
||||||
|
int rx = (data[EDID_CHROMATICITIES_BLOCK] >> 6) & 0x03;
|
||||||
|
int ry = (data[EDID_CHROMATICITIES_BLOCK] >> 4) & 0x03;
|
||||||
|
int gx = (data[EDID_CHROMATICITIES_BLOCK] >> 2) & 0x03;
|
||||||
|
int gy = (data[EDID_CHROMATICITIES_BLOCK] >> 0) & 0x03;
|
||||||
|
int bx = (data[EDID_CHROMATICITIES_BLOCK + 1] >> 6) & 0x03;
|
||||||
|
int by = (data[EDID_CHROMATICITIES_BLOCK + 1] >> 4) & 0x03;
|
||||||
|
int wx = (data[EDID_CHROMATICITIES_BLOCK + 1] >> 2) & 0x03;
|
||||||
|
int wy = (data[EDID_CHROMATICITIES_BLOCK + 1] >> 0) & 0x03;
|
||||||
|
rx |= data[EDID_CHROMATICITIES_BLOCK + 2] << 2;
|
||||||
|
ry |= data[EDID_CHROMATICITIES_BLOCK + 3] << 2;
|
||||||
|
gx |= data[EDID_CHROMATICITIES_BLOCK + 4] << 2;
|
||||||
|
gy |= data[EDID_CHROMATICITIES_BLOCK + 5] << 2;
|
||||||
|
bx |= data[EDID_CHROMATICITIES_BLOCK + 6] << 2;
|
||||||
|
by |= data[EDID_CHROMATICITIES_BLOCK + 7] << 2;
|
||||||
|
wx |= data[EDID_CHROMATICITIES_BLOCK + 8] << 2;
|
||||||
|
wy |= data[EDID_CHROMATICITIES_BLOCK + 9] << 2;
|
||||||
|
|
||||||
|
redChromaticity.setX(rx * (1.0f / 1024.0f));
|
||||||
|
redChromaticity.setY(ry * (1.0f / 1024.0f));
|
||||||
|
greenChromaticity.setX(gx * (1.0f / 1024.0f));
|
||||||
|
greenChromaticity.setY(gy * (1.0f / 1024.0f));
|
||||||
|
blueChromaticity.setX(bx * (1.0f / 1024.0f));
|
||||||
|
blueChromaticity.setY(by * (1.0f / 1024.0f));
|
||||||
|
whiteChromaticity.setX(wx * (1.0f / 1024.0f));
|
||||||
|
whiteChromaticity.setY(wy * (1.0f / 1024.0f));
|
||||||
|
|
||||||
|
// Find extensions
|
||||||
|
for (uint i = 1; i < length / 128; ++i) {
|
||||||
|
uint extensionId = data[i * 128];
|
||||||
|
if (extensionId == 0x40) { // DI-EXT
|
||||||
|
// 0x0E (sub-pixel layout)
|
||||||
|
// 0x20->0x22 (bits per color)
|
||||||
|
// 0x51->0x7e Transfer characteristics
|
||||||
|
const uchar desc = data[i * 128 + 0x51];
|
||||||
|
const uchar len = desc & 0x3f;
|
||||||
|
if ((desc & 0xc0) == 0x40) {
|
||||||
|
if (len > 45)
|
||||||
|
return false;
|
||||||
|
QList<uint16_t> whiteTRC;
|
||||||
|
whiteTRC.reserve(len + 1);
|
||||||
|
for (uint j = 0; j < len; ++j)
|
||||||
|
whiteTRC[j] = data[0x52 + j] * 0x101;
|
||||||
|
whiteTRC[len] = 0xffff;
|
||||||
|
tables.append(whiteTRC);
|
||||||
|
} else if ((desc & 0xc0) == 0x80) {
|
||||||
|
if (len > 15)
|
||||||
|
return false;
|
||||||
|
QList<uint16_t> redTRC;
|
||||||
|
QList<uint16_t> greenTRC;
|
||||||
|
QList<uint16_t> blueTRC;
|
||||||
|
blueTRC.reserve(len + 1);
|
||||||
|
greenTRC.reserve(len + 1);
|
||||||
|
redTRC.reserve(len + 1);
|
||||||
|
for (uint j = 0; j < len; ++j)
|
||||||
|
blueTRC[j] = data[0x52 + j] * 0x101;
|
||||||
|
blueTRC[len] = 0xffff;
|
||||||
|
for (uint j = 0; j < len; ++j)
|
||||||
|
greenTRC[j] = data[0x61 + j] * 0x101;
|
||||||
|
greenTRC[len] = 0xffff;
|
||||||
|
for (uint j = 0; j < len; ++j)
|
||||||
|
redTRC[j] = data[0x70 + j] * 0x101;
|
||||||
|
redTRC[len] = 0xffff;
|
||||||
|
tables.append(redTRC);
|
||||||
|
tables.append(greenTRC);
|
||||||
|
tables.append(blueTRC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,8 +40,9 @@
|
|||||||
#ifndef QEDIDPARSER_P_H
|
#ifndef QEDIDPARSER_P_H
|
||||||
#define QEDIDPARSER_P_H
|
#define QEDIDPARSER_P_H
|
||||||
|
|
||||||
#include <QtCore/QSize>
|
|
||||||
#include <QtCore/QMap>
|
#include <QtCore/QMap>
|
||||||
|
#include <QtCore/QPointF>
|
||||||
|
#include <QtCore/QSize>
|
||||||
|
|
||||||
//
|
//
|
||||||
// W A R N I N G
|
// W A R N I N G
|
||||||
@ -72,6 +73,14 @@ public:
|
|||||||
QString model;
|
QString model;
|
||||||
QString serialNumber;
|
QString serialNumber;
|
||||||
QSizeF physicalSize;
|
QSizeF physicalSize;
|
||||||
|
qreal gamma;
|
||||||
|
QPointF redChromaticity;
|
||||||
|
QPointF greenChromaticity;
|
||||||
|
QPointF blueChromaticity;
|
||||||
|
QPointF whiteChromaticity;
|
||||||
|
QList<QList<uint16_t>> tables;
|
||||||
|
bool sRgb;
|
||||||
|
bool useTables;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMap<QString, QString> m_vendorCache;
|
QMap<QString, QString> m_vendorCache;
|
||||||
|
@ -66,6 +66,7 @@ public:
|
|||||||
QRect availableGeometry() const override { return m_availableGeometry; }
|
QRect availableGeometry() const override { return m_availableGeometry; }
|
||||||
int depth() const override { return m_depth; }
|
int depth() const override { return m_depth; }
|
||||||
QImage::Format format() const override { return m_format; }
|
QImage::Format format() const override { return m_format; }
|
||||||
|
QColorSpace colorSpace() const override { return m_colorSpace; }
|
||||||
qreal devicePixelRatio() const override { return m_devicePixelRatio; }
|
qreal devicePixelRatio() const override { return m_devicePixelRatio; }
|
||||||
QSizeF physicalSize() const override { return m_physicalSize; }
|
QSizeF physicalSize() const override { return m_physicalSize; }
|
||||||
QDpi logicalDpi() const override { return m_logicalDpi; }
|
QDpi logicalDpi() const override { return m_logicalDpi; }
|
||||||
@ -122,6 +123,7 @@ private:
|
|||||||
int m_depth = 0;
|
int m_depth = 0;
|
||||||
QString m_name;
|
QString m_name;
|
||||||
QImage::Format m_format;
|
QImage::Format m_format;
|
||||||
|
QColorSpace m_colorSpace;
|
||||||
QSizeF m_physicalSize;
|
QSizeF m_physicalSize;
|
||||||
QCocoaCursor *m_cursor;
|
QCocoaCursor *m_cursor;
|
||||||
qreal m_devicePixelRatio = 0;
|
qreal m_devicePixelRatio = 0;
|
||||||
|
@ -330,6 +330,11 @@ void QCocoaScreen::update(CGDirectDisplayID displayId)
|
|||||||
|
|
||||||
m_format = QImage::Format_RGB32;
|
m_format = QImage::Format_RGB32;
|
||||||
m_depth = NSBitsPerPixelFromDepth(nsScreen.depth);
|
m_depth = NSBitsPerPixelFromDepth(nsScreen.depth);
|
||||||
|
m_colorSpace = QColorSpace::fromIccProfile(QByteArray::fromNSData(nsScreen.colorSpace.ICCProfileData));
|
||||||
|
if (!m_colorSpace.isValid()) {
|
||||||
|
qWarning() << "macOS generated a color-profile Qt couldn't parse. This shouldn't happen.";
|
||||||
|
m_colorSpace = QColorSpace::SRgb;
|
||||||
|
}
|
||||||
|
|
||||||
CGSize size = CGDisplayScreenSize(m_displayId);
|
CGSize size = CGDisplayScreenSize(m_displayId);
|
||||||
m_physicalSize = QSizeF(size.width, size.height);
|
m_physicalSize = QSizeF(size.width, size.height);
|
||||||
|
@ -234,6 +234,7 @@ static const char *xcb_atomnames = {
|
|||||||
"EDID\0"
|
"EDID\0"
|
||||||
"EDID_DATA\0"
|
"EDID_DATA\0"
|
||||||
"XFree86_DDC_EDID1_RAWDATA\0"
|
"XFree86_DDC_EDID1_RAWDATA\0"
|
||||||
|
"_ICC_PROFILE\0"
|
||||||
// \0\0 terminates loop.
|
// \0\0 terminates loop.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -240,6 +240,8 @@ public:
|
|||||||
EDID_DATA,
|
EDID_DATA,
|
||||||
XFree86_DDC_EDID1_RAWDATA,
|
XFree86_DDC_EDID1_RAWDATA,
|
||||||
|
|
||||||
|
_ICC_PROFILE,
|
||||||
|
|
||||||
NAtoms
|
NAtoms
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -547,6 +547,17 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
|
|||||||
|
|
||||||
m_cursor = new QXcbCursor(connection, this);
|
m_cursor = new QXcbCursor(connection, this);
|
||||||
|
|
||||||
|
{
|
||||||
|
// Read colord ICC data (from GNOME settings)
|
||||||
|
auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(),
|
||||||
|
false, screen()->root,
|
||||||
|
connection->atom(QXcbAtom::_ICC_PROFILE),
|
||||||
|
XCB_ATOM_CARDINAL, 0, 8192);
|
||||||
|
if (reply->format == 8 && reply->type == XCB_ATOM_CARDINAL) {
|
||||||
|
QByteArray data(reinterpret_cast<const char *>(xcb_get_property_value(reply.get())), reply->value_len);
|
||||||
|
m_colorSpace = QColorSpace::fromIccProfile(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (connection->hasXRandr()) { // Parse EDID
|
if (connection->hasXRandr()) { // Parse EDID
|
||||||
QByteArray edid = getEdid();
|
QByteArray edid = getEdid();
|
||||||
if (m_edid.parse(edid)) {
|
if (m_edid.parse(edid)) {
|
||||||
@ -558,6 +569,27 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
|
|||||||
m_edid.model.toLatin1().constData(),
|
m_edid.model.toLatin1().constData(),
|
||||||
m_edid.serialNumber.toLatin1().constData(),
|
m_edid.serialNumber.toLatin1().constData(),
|
||||||
m_edid.physicalSize.width(), m_edid.physicalSize.height());
|
m_edid.physicalSize.width(), m_edid.physicalSize.height());
|
||||||
|
if (!m_colorSpace.isValid()) {
|
||||||
|
if (m_edid.sRgb)
|
||||||
|
m_colorSpace = QColorSpace::SRgb;
|
||||||
|
else {
|
||||||
|
if (!m_edid.useTables) {
|
||||||
|
m_colorSpace = QColorSpace(m_edid.whiteChromaticity, m_edid.redChromaticity,
|
||||||
|
m_edid.greenChromaticity, m_edid.blueChromaticity,
|
||||||
|
QColorSpace::TransferFunction::Gamma, m_edid.gamma);
|
||||||
|
} else {
|
||||||
|
if (m_edid.tables.length() == 1) {
|
||||||
|
m_colorSpace = QColorSpace(m_edid.whiteChromaticity, m_edid.redChromaticity,
|
||||||
|
m_edid.greenChromaticity, m_edid.blueChromaticity,
|
||||||
|
m_edid.tables[0]);
|
||||||
|
} else if (m_edid.tables.length() == 3) {
|
||||||
|
m_colorSpace = QColorSpace(m_edid.whiteChromaticity, m_edid.redChromaticity,
|
||||||
|
m_edid.greenChromaticity, m_edid.blueChromaticity,
|
||||||
|
m_edid.tables[0], m_edid.tables[1], m_edid.tables[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// This property is defined by the xrandr spec. Parsing failure indicates a valid error,
|
// This property is defined by the xrandr spec. Parsing failure indicates a valid error,
|
||||||
// but keep this as debug, for details see 4f515815efc318ddc909a0399b71b8a684962f38.
|
// but keep this as debug, for details see 4f515815efc318ddc909a0399b71b8a684962f38.
|
||||||
@ -565,6 +597,8 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
|
|||||||
"edid data: " << edid;
|
"edid data: " << edid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!m_colorSpace.isValid())
|
||||||
|
m_colorSpace = QColorSpace::SRgb;
|
||||||
}
|
}
|
||||||
|
|
||||||
QXcbScreen::~QXcbScreen()
|
QXcbScreen::~QXcbScreen()
|
||||||
|
@ -160,6 +160,7 @@ public:
|
|||||||
QRect availableGeometry() const override;
|
QRect availableGeometry() const override;
|
||||||
int depth() const override { return screen()->root_depth; }
|
int depth() const override { return screen()->root_depth; }
|
||||||
QImage::Format format() const override;
|
QImage::Format format() const override;
|
||||||
|
QColorSpace colorSpace() const override { return m_colorSpace; }
|
||||||
QSizeF physicalSize() const override { return m_sizeMillimeters; }
|
QSizeF physicalSize() const override { return m_sizeMillimeters; }
|
||||||
QDpi logicalDpi() const override;
|
QDpi logicalDpi() const override;
|
||||||
QDpi logicalBaseDpi() const override { return QDpi(96, 96); }
|
QDpi logicalBaseDpi() const override { return QDpi(96, 96); }
|
||||||
@ -226,6 +227,7 @@ private:
|
|||||||
QSizeF m_sizeMillimeters;
|
QSizeF m_sizeMillimeters;
|
||||||
QRect m_geometry;
|
QRect m_geometry;
|
||||||
QRect m_availableGeometry;
|
QRect m_availableGeometry;
|
||||||
|
QColorSpace m_colorSpace;
|
||||||
Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation;
|
Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation;
|
||||||
QXcbCursor *m_cursor;
|
QXcbCursor *m_cursor;
|
||||||
qreal m_refreshRate = 60.0;
|
qreal m_refreshRate = 60.0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user