aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gamma-linux-drm.c105
-rw-r--r--src/libgamma-error.h7
2 files changed, 111 insertions, 1 deletions
diff --git a/src/gamma-linux-drm.c b/src/gamma-linux-drm.c
index 19bcc27..13ad91f 100644
--- a/src/gamma-linux-drm.c
+++ b/src/gamma-linux-drm.c
@@ -33,6 +33,7 @@
#include <grp.h>
#include <unistd.h>
#include <stdio.h>
+#include <string.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
@@ -83,6 +84,7 @@ void libgamma_linux_drm_method_capabilities(libgamma_method_capabilities_t* rest
| CRTC_INFO_GAMMA_SIZE
| CRTC_INFO_GAMMA_DEPTH
| CRTC_INFO_SUBPIXEL_ORDER
+ | CRTC_INFO_ACTIVE
| CRTC_INFO_CONNECTOR_NAME
| CRTC_INFO_CONNECTOR_TYPE
| CRTC_INFO_GAMMA;
@@ -367,6 +369,68 @@ int libgamma_linux_drm_crtc_restore(libgamma_crtc_state_t* restrict this)
}
+/**
+ * Get the size of the gamma ramps for a CRTC
+ *
+ * @param this Instance of a data structure to fill with the information about the CRTC
+ * @param crtc The state of the CRTC whose information should be read
+ * @return The value stored in `this->gamma_size_error`
+ */
+static int get_gamma_ramp_size(libgamma_crtc_information_t* restrict this, libgamma_crtc_state_t* restrict crtc)
+{
+ libgamma_drm_card_data_t* card = crtc->partition->data;
+ uint32_t crtc_id = card->res->crtcs[crtc->crtc];
+ drmModeCrtc* crtc_info;
+ errno = 0;
+ crtc_info = drmModeGetCrtc(card->fd, crtc_id);
+ this->gamma_size_error = crtc_info == NULL ? errno : 0;
+ if (this->gamma_size_error == 0)
+ {
+ this->red_gamma_size = (size_t)(crtc_info->gamma_size);
+ this->green_gamma_size = (size_t)(crtc_info->gamma_size);
+ this->blue_gamma_size = (size_t)(crtc_info->gamma_size);
+ this->gamma_size_error = crtc_info->gamma_size < 2 ? LIBGAMMA_SINGLETON_GAMMA_RAMP : 0;
+ drmModeFreeCrtc(crtc_info);
+ }
+ return this->gamma_size_error;
+}
+
+
+static int read_connector_data(libgamma_crtc_information_t* restrict this,
+ drmModeConnector* connector, int32_t fields)
+{
+ if (connector == NULL)
+ {
+ this->width_mm_error = this->height_mm_error = this->connector_type = this->active =
+ this->active_error = this->connector_name = LIBGAMMA_CONNECTOR_UNKNOWN;
+ return LIBGAMMA_CONNECTOR_UNKNOWN;
+ }
+
+
+ if ((fields & (CRTC_INFO_WIDTH_MM | CRTC_INFO_HEIGHT_MM | CRTC_INFO_CONNECTOR_TYPE | CRTC_INFO_ACTIVE)))
+ {
+ this->width_mm = connector->mmWidth;
+ this->height_mm = connector->mmHeight;
+ this->connector_type = (int)(connector->connector_type); /* TODO: needs abstraction */
+ this->active = connector->connection == DRM_MODE_CONNECTED;
+ this->active_error = connector->connection == DRM_MODE_UNKNOWNCONNECTION ? LIBGAMMA_STATE_UNKNOWN : 0;
+ }
+
+ if ((fields & CRTC_INFO_CONNECTOR_NAME))
+ {
+ static const char* TYPE_NAMES[] = /* FIXME: What names does Linux itself use? */
+ {
+ "Unknown", "VGA", "DVII", "DVID", "DVIA", "Composite", "SVIDEO", "LVDS", "Component",
+ "9PinDIN", "DisplayPort", "HDMIA", "HDMIB", "TV", "eDP", "VIRTUAL", "DSI"
+ };
+ this->connector_name = (size_t)(this->connector_type) < sizeof(TYPE_NAMES) / sizeof(char*)
+ ? TYPE_NAMES[(size_t)(this->connector_type)] : "Unrecognised" /*TODO:error*/;
+ /* FIXME : add index */
+ }
+
+ return 0;
+}
+
/**
* Read information about a CRTC
@@ -379,6 +443,47 @@ int libgamma_linux_drm_crtc_restore(libgamma_crtc_state_t* restrict this)
int libgamma_linux_drm_get_crtc_information(libgamma_crtc_information_t* restrict this,
libgamma_crtc_state_t* restrict crtc, int32_t fields)
{
+#define _E(FIELD) ((fields & FIELD) ? LIBGAMMA_CRTC_INFO_NOT_SUPPORTED : 0)
+ int e = 0;
+ int require_connector;
+ int free_edid;
+ drmModeConnector* connector;
+
+ /* Wipe all error indicators. */
+ memset(this, 0, sizeof(libgamma_crtc_information_t));
+
+ /* We need to free the EDID after us if it is not explicitly requested. */
+ free_edid = (fields & CRTC_INFO_EDID) == 0;
+
+ /* Figure out what fields we need to get the data for to get the data for other fields. */
+ if ((fields & (CRTC_INFO_WIDTH_MM_EDID | CRTC_INFO_HEIGHT_MM_EDID | CRTC_INFO_GAMMA)))
+ fields |= CRTC_INFO_EDID;
+ if ((fields & CRTC_INFO_CONNECTOR_NAME))
+ fields |= CRTC_INFO_CONNECTOR_TYPE;
+
+ /* Figure out whether we require the connector to get all information we want. */
+ require_connector = fields & (CRTC_INFO_WIDTH_MM | CRTC_INFO_HEIGHT_MM |
+ CRTC_INFO_SUBPIXEL_ORDER/*(?)*/ | CRTC_INFO_CONNECTOR_TYPE);
+
+ e |= this->edid_error = _E(CRTC_INFO_EDID); /* TODO */
+ e |= this->width_mm_edid_error = _E(CRTC_INFO_WIDTH_MM_EDID); /* TODO */
+ e |= this->height_mm_edid_error = _E(CRTC_INFO_HEIGHT_MM_EDID); /* TODO */
+ e |= this->gamma_error = _E(CRTC_INFO_GAMMA); /* TODO */
+ e |= require_connector ? read_connector_data(this, connector, fields) : 0;
+ e |= this->subpixel_order_error = _E(CRTC_INFO_SUBPIXEL_ORDER); /* TODO */
+ e |= (fields & CRTC_INFO_GAMMA_SIZE) ? get_gamma_ramp_size(this, crtc) : 0;
+ this->gamma_depth = 16;
+ e |= this->gamma_support_error = _E(CRTC_INFO_GAMMA_SUPPORT);
+
+ /* Free the EDID after us. */
+ if (free_edid)
+ {
+ free(this->edid);
+ this->edid = NULL;
+ }
+
+ return e ? -1 : 0;
+#undef _E
}
diff --git a/src/libgamma-error.h b/src/libgamma-error.h
index be1e5d9..5091d46 100644
--- a/src/libgamma-error.h
+++ b/src/libgamma-error.h
@@ -113,7 +113,7 @@ extern const char* libgamma_group_name;
#define LIBGAMMA_WRONG_GAMMA_RAMP_SIZE (-14)
/**
- * The adjustment method reported that the gamma ramps size is 1 or 0
+ * The adjustment method reported that the gamma ramps size is 1, or perhaps even zero or negative
*/
#define LIBGAMMA_SINGLETON_GAMMA_RAMP (-15)
@@ -159,6 +159,11 @@ extern const char* libgamma_group_name;
*/
#define LIBGAMMA_GRAPHICS_CARD_REMOVED (-23)
+/**
+ * The state of the requested information is unknown
+ */
+#define LIBGAMMA_STATE_UNKNOWN (-24)
+
#endif