aboutsummaryrefslogtreecommitdiffstats
path: root/src/gamma-linux-drm.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/gamma-linux-drm.c108
1 files changed, 94 insertions, 14 deletions
diff --git a/src/gamma-linux-drm.c b/src/gamma-linux-drm.c
index 7a324be..688e678 100644
--- a/src/gamma-linux-drm.c
+++ b/src/gamma-linux-drm.c
@@ -65,6 +65,16 @@ typedef struct libgamma_drm_card_data
*/
drmModeRes* res;
+ /**
+ * Resources for open connectors
+ */
+ drmModeConnector** connectors;
+
+ /**
+ * Resources for open encoders
+ */
+ drmModeEncoder** encoders;
+
} libgamma_drm_card_data_t;
@@ -289,13 +299,38 @@ int libgamma_linux_drm_partition_initialise(libgamma_partition_state_t* restrict
/**
+ * Release all connectors and encoders
+ *
+ * @param this The graphics card data
+ */
+static void release_connectors_and_encoders(libgamma_drm_card_data_t* restrict this)
+{
+ size_t i, n;
+ if (this->encoders != NULL)
+ for (i = 0, n = (size_t)(this->res->count_connectors); i < n; i++)
+ if (this->encoders[i] != NULL)
+ drmModeFreeEncoder(this->encoders[i]);
+ free(this->encoders);
+ this->encoders = NULL;
+
+ if (this->connectors != NULL)
+ for (i = 0, n = (size_t)(this->res->count_connectors); i < n; i++)
+ if (this->connectors[i] != NULL)
+ drmModeFreeConnector(this->connectors[i]);
+ free(this->connectors);
+ this->connectors = NULL;
+}
+
+
+/**
* Release all resources held by a partition state
*
* @param this The partition state
*/
void libgamma_linux_drm_partition_destroy(libgamma_partition_state_t* restrict this)
{
- libgamma_drm_card_data_t* data = this->data;
+ libgamma_drm_card_data_t* restrict data = this->data;
+ release_connectors_and_encoders(data);
if (data->res != NULL)
drmModeFreeResources(data->res);
if (data->fd >= 0)
@@ -331,7 +366,7 @@ int libgamma_linux_drm_partition_restore(libgamma_partition_state_t* restrict th
int libgamma_linux_drm_crtc_initialise(libgamma_crtc_state_t* restrict this,
libgamma_partition_state_t* restrict partition, size_t crtc)
{
- libgamma_drm_card_data_t* card;
+ libgamma_drm_card_data_t* restrict card;
uint32_t crtc_id;
if (crtc >= partition->crtcs_available)
@@ -370,6 +405,46 @@ int libgamma_linux_drm_crtc_restore(libgamma_crtc_state_t* restrict this)
/**
+ * Find the connector that a CRTC belongs to
+ *
+ * @param this The CRTC state
+ * @param error Output of the error value to store of error report fields for data that requires the connector
+'* @return The CRTC's conncetor, `NULL` on error
+ */
+static drmModeConnector* find_connector(libgamma_crtc_state_t* restrict this, int* error)
+{
+ uint32_t crtc_id = (uint32_t)(size_t)(this->data);
+ libgamma_drm_card_data_t* restrict card = this->partition->data;
+ size_t i, n = (size_t)(card->res->count_connectors);
+ /* Open connectors and encoders if not already opened. */
+ if (card->connectors == NULL)
+ {
+ /* We use calloc so all non-loaded elements are `NULL` after an error. */
+ if ((card->connectors = calloc(n, sizeof(drmModeConnector*))) == NULL)
+ goto fail;
+ if ((card->encoders = calloc(n, sizeof(drmModeEncoder*))) == NULL)
+ goto fail;
+ for (i = 0; i < n; i++)
+ if (((card->connectors[i] = drmModeGetConnector(card->fd, card->res->connectors[i])) == NULL) ||
+ ((card->encoders[i] = drmModeGetEncoder(card->fd, card->connectors[i]->encoder_id)) == NULL))
+ goto fail;
+ }
+ /* Find connector. */
+ *error = 0;
+ for (i = 0; i < n; i++)
+ if (card->encoders[i]->crtc_id == crtc_id)
+ return card->connectors[i];
+ *error = LIBGAMMA_CONNECTOR_UNKNOWN;
+ return NULL;
+
+ fail:
+ *error = errno;
+ release_connectors_and_encoders(card);
+ return NULL;
+}
+
+
+/**
* Get the size of the gamma ramps for a CRTC
*
* @param out Instance of a data structure to fill with the information about the CRTC
@@ -378,9 +453,9 @@ int libgamma_linux_drm_crtc_restore(libgamma_crtc_state_t* restrict this)
*/
static int get_gamma_ramp_size(libgamma_crtc_information_t* restrict out, const libgamma_crtc_state_t* restrict crtc)
{
- libgamma_drm_card_data_t* card = crtc->partition->data;
+ libgamma_drm_card_data_t* restrict card = crtc->partition->data;
uint32_t crtc_id = card->res->crtcs[crtc->crtc];
- drmModeCrtc* crtc_info;
+ drmModeCrtc* restrict crtc_info;
errno = 0;
crtc_info = drmModeGetCrtc(card->fd, crtc_id);
out->gamma_size_error = crtc_info == NULL ? errno : 0;
@@ -408,11 +483,6 @@ static int read_connector_data(libgamma_crtc_information_t* restrict out, const
{
const char* connector_name_base = NULL;
- if (connector == NULL)
- return out->width_mm_error = out->height_mm_error = out->connector_type = out->subpixel_order_error =
- out->active_error = out->connector_name_error = LIBGAMMA_CONNECTOR_UNKNOWN;
-
-
/* Get some information that does not require too much work. */
if ((fields & (CRTC_INFO_WIDTH_MM | CRTC_INFO_HEIGHT_MM | CRTC_INFO_CONNECTOR_TYPE |
CRTC_INFO_ACTIVE | CRTC_INFO_SUBPIXEL_ORDER)))
@@ -509,9 +579,11 @@ int libgamma_linux_drm_get_crtc_information(libgamma_crtc_information_t* restric
{
#define _E(FIELD) ((fields & FIELD) ? LIBGAMMA_CRTC_INFO_NOT_SUPPORTED : 0)
int e = 0;
+ drmModeConnector* connector;
int require_connector;
int free_edid;
- drmModeConnector* connector;
+ int error;
+
/* Wipe all error indicators. */
memset(this, 0, sizeof(libgamma_crtc_information_t));
@@ -529,11 +601,19 @@ int libgamma_linux_drm_get_crtc_information(libgamma_crtc_information_t* restric
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;
+ if (require_connector)
+ {
+ if ((connector = find_connector(crtc, &error)) == NULL)
+ e |= this->width_mm_error = this->height_mm_error = this->connector_type = this->subpixel_order_error =
+ this->active_error = this->connector_name_error = error;
+ else
+ e |= read_connector_data(this, connector, fields);
+ }
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);
@@ -561,14 +641,14 @@ int libgamma_linux_drm_get_crtc_information(libgamma_crtc_information_t* restric
int libgamma_linux_drm_crtc_get_gamma_ramps(libgamma_crtc_state_t* restrict this,
libgamma_gamma_ramps_t* restrict ramps)
{
- libgamma_drm_card_data_t* card = this->partition->data;
+ libgamma_drm_card_data_t* restrict card = this->partition->data;
int r;
#ifdef DEBUG
if ((ramps->red_size != ramps->green_size) ||
(ramps->red_size != ramps->blue_size))
return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE;
#endif
- r = drmModeCrtcGetGamma(card->fd, (uint32_t)(this->crtc), (uint32_t)(ramps->red_size),
+ r = drmModeCrtcGetGamma(card->fd, (uint32_t)(size_t)(this->data), (uint32_t)(ramps->red_size),
ramps->red, ramps->green, ramps->blue);
return r ? LIBGAMMA_GAMMA_RAMP_READ_FAILED : 0;
}
@@ -585,7 +665,7 @@ int libgamma_linux_drm_crtc_get_gamma_ramps(libgamma_crtc_state_t* restrict this
int libgamma_linux_drm_crtc_set_gamma_ramps(libgamma_crtc_state_t* restrict this,
libgamma_gamma_ramps_t ramps)
{
- libgamma_drm_card_data_t* card = this->partition->data;
+ libgamma_drm_card_data_t* restrict card = this->partition->data;
int r;
#ifdef DEBUG
if ((ramps.red_size != ramps.green_size) ||