diff options
author | Mattias Andrée <maandree@operamail.com> | 2014-05-31 07:32:09 +0200 |
---|---|---|
committer | Mattias Andrée <maandree@operamail.com> | 2014-05-31 07:32:09 +0200 |
commit | bdeb7f77f16b1e482904866ff21e43f8bfc01bb0 (patch) | |
tree | e5587a577db53a58ea52fd2579fa0cbb89007491 /src/gamma-linux-drm.c | |
parent | split out error identification for failure of open from libgamma_linux_drm_partition_initialise (diff) | |
download | libgamma-bdeb7f77f16b1e482904866ff21e43f8bfc01bb0.tar.gz libgamma-bdeb7f77f16b1e482904866ff21e43f8bfc01bb0.tar.bz2 libgamma-bdeb7f77f16b1e482904866ff21e43f8bfc01bb0.tar.xz |
move files around
Signed-off-by: Mattias Andrée <maandree@operamail.com>
Diffstat (limited to 'src/gamma-linux-drm.c')
-rw-r--r-- | src/gamma-linux-drm.c | 831 |
1 files changed, 0 insertions, 831 deletions
diff --git a/src/gamma-linux-drm.c b/src/gamma-linux-drm.c deleted file mode 100644 index 36ba442..0000000 --- a/src/gamma-linux-drm.c +++ /dev/null @@ -1,831 +0,0 @@ -/** - * libgamma — Display server abstraction layer for gamma ramp adjustments - * Copyright © 2014 Mattias Andrée (maandree@member.fsf.org) - * - * This library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this library. If not, see <http://www.gnu.org/licenses/>. - */ -#ifndef HAVE_LIBGAMMA_METHOD_LINUX_DRM -# error Compiling gamma-linux-drm.c without HAVE_LIBGAMMA_METHOD_LINUX_DRM -#endif - -#define _GNU_SOURCE - -#include "gamma-linux-drm.h" - -#include "libgamma-error.h" -#include "edid.h" - -#include <limits.h> -#include <stdlib.h> -#include <errno.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <grp.h> -#include <unistd.h> -#include <stdio.h> -#include <string.h> -#include <inttypes.h> - -#include <xf86drm.h> -#include <xf86drmMode.h> - -#ifndef O_CLOEXEC -# define O_CLOEXEC 02000000 -#endif -#ifndef NGROUPS_MAX -# define NGROUPS_MAX 65536 -#endif -#ifndef PATH_MAX -# define PATH_MAX 4096 -#endif - - - -/** - * Graphics card data for the Direct Rendering Manager adjustment method. - */ -typedef struct libgamma_drm_card_data -{ - /** - * File descriptor for the connection to the graphics card. - */ - int fd; - - /** - * The graphics card's mode resources. - */ - drmModeRes* res; - - /** - * Resources for open connectors. - */ - drmModeConnector** connectors; - - /** - * Resources for open encoders. - */ - drmModeEncoder** encoders; - -} libgamma_drm_card_data_t; - - - -/** - * Return the capabilities of the adjustment method. - * - * @param this The data structure to fill with the method's capabilities. - */ -void libgamma_linux_drm_method_capabilities(libgamma_method_capabilities_t* restrict this) -{ - this->crtc_information = LIBGAMMA_CRTC_INFO_EDID - | LIBGAMMA_CRTC_INFO_WIDTH_MM - | LIBGAMMA_CRTC_INFO_HEIGHT_MM - | LIBGAMMA_CRTC_INFO_WIDTH_MM_EDID - | LIBGAMMA_CRTC_INFO_HEIGHT_MM_EDID - | LIBGAMMA_CRTC_INFO_GAMMA_SIZE - | LIBGAMMA_CRTC_INFO_GAMMA_DEPTH - | LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER - | LIBGAMMA_CRTC_INFO_ACTIVE - | LIBGAMMA_CRTC_INFO_CONNECTOR_NAME - | LIBGAMMA_CRTC_INFO_CONNECTOR_TYPE - | LIBGAMMA_CRTC_INFO_GAMMA; - this->default_site_known = 1; - this->multiple_sites = 0; - this->multiple_partitions = 1; - this->multiple_crtcs = 1; - this->partitions_are_graphics_cards = 1; - this->site_restore = 0; - this->partition_restore = 0; - this->crtc_restore = 0; - this->identical_gamma_sizes = 1; - this->fixed_gamma_size = 0; - this->fixed_gamma_depth = 1; - this->real = 1; - this->fake = 0; -} - - -/** - * Initialise an allocated site state. - * - * @param this The site state to initialise. - * @param site The site identifier, unless it is `NULL` it must a - * `free`:able. One the state is destroyed the library - * will attempt to free it. There you should not free - * it yourself, and it must not be a string constant - * or allocate on the stack. Note however that it will - * not be free:d if this function fails. - * @return Zero on success, otherwise (negative) the value of an - * error identifier provided by this library. - */ -int libgamma_linux_drm_site_initialise(libgamma_site_state_t* restrict this, - char* restrict site) -{ - char pathname[PATH_MAX]; - struct stat _attr; - - if (site != NULL) - return LIBGAMMA_NO_SUCH_SITE; - - /* Count the number of available graphics cards by - * stat:ing there existence in an API filesystem. */ - this->partitions_available = 0; - for (;;) - { - snprintf(pathname, sizeof(pathname) / sizeof(char), - DRM_DEV_NAME, DRM_DIR_NAME, (int)(this->partitions_available)); - if (stat(pathname, &_attr)) - break; - if (this->partitions_available++ > INT_MAX) - return LIBGAMMA_IMPOSSIBLE_AMOUNT; - } - return 0; -} - - -/** - * Release all resources held by a site state. - * - * @param this The site state. - */ -void libgamma_linux_drm_site_destroy(libgamma_site_state_t* restrict this) -{ - (void) this; -} - - -/** - * Restore the gamma ramps all CRTC:s with a site to the system settings. - * - * @param this The site state. - * @return Zero on success, otherwise (negative) the value of an - * error identifier provided by this library. - */ -int libgamma_linux_drm_site_restore(libgamma_site_state_t* restrict this) -{ - (void) this; - return errno = ENOTSUP, LIBGAMMA_ERRNO_SET; -} - - -/** - * Figure out why `open` failed for a graphics card - * - * @param pathname The pathname of the error card - * @return The error code to report - */ -static int figure_out_card_open_error(const char* pathname) -{ - if ((errno == ENXIO) || (errno == ENODEV)) - return LIBGAMMA_NO_SUCH_PARTITION; - - if (errno == EACCES) - { - gid_t supplemental_groups[NGROUPS_MAX]; - struct group* group; - int i, n; - struct stat attr; - int r; - - - r = stat(pathname, &attr); - -#define __test(R, W) ((attr.st_mode & (R | W)) == (R | W)) - if (r) - return errno == EACCES ? LIBGAMMA_NO_SUCH_PARTITION : LIBGAMMA_ERRNO_SET; - - if ((attr.st_uid == geteuid() && __test(S_IRUSR, S_IWUSR)) || - (attr.st_gid == getegid() && __test(S_IRGRP, S_IWGRP)) || - __test(S_IROTH, S_IWOTH)) - return LIBGAMMA_DEVICE_ACCESS_FAILED; - - if (attr.st_gid == 0 /* root group */ || __test(S_IRGRP, S_IWGRP)) - return LIBGAMMA_DEVICE_RESTRICTED; - - - n = getgroups(NGROUPS_MAX, supplemental_groups); - if (n < 0) - return LIBGAMMA_ERRNO_SET; - - for (i = 0; i < n; i++) - if (supplemental_groups[i] == attr.st_gid) - break; - - if (i != n) - return LIBGAMMA_DEVICE_ACCESS_FAILED; - - errno = 0; - group = getgrgid(attr.st_gid); /* TODO: Not thread-safe. */ - libgamma_group_gid = attr.st_gid; - libgamma_group_name = group != NULL ? group->gr_name : NULL; - return LIBGAMMA_DEVICE_REQUIRE_GROUP; -#undef __test - } - - return LIBGAMMA_ERRNO_SET; -} - - -/** - * Initialise an allocated partition state. - * - * @param this The partition state to initialise. - * @param site The site state for the site that the partition belongs to. - * @param partition The the index of the partition within the site. - * @return Zero on success, otherwise (negative) the value of an - * error identifier provided by this library. - */ -int libgamma_linux_drm_partition_initialise(libgamma_partition_state_t* restrict this, - libgamma_site_state_t* restrict site, size_t partition) -{ - int rc = 0; - libgamma_drm_card_data_t* restrict data; - char pathname[PATH_MAX]; - - (void) site; - - /* Check for partition index overflow. */ - if (partition > INT_MAX) - return LIBGAMMA_NO_SUCH_PARTITION; - - /* Allocate and initialise graphics card data. */ - this->data = NULL; - data = malloc(sizeof(libgamma_drm_card_data_t)); - if (data == NULL) - return LIBGAMMA_ERRNO_SET; - data->fd = -1; - data->res = NULL; - - /* Get the pathname for the graphics card. */ - snprintf(pathname, sizeof(pathname) / sizeof(char), - DRM_DEV_NAME, DRM_DIR_NAME, (int)partition); - - /* Acquire access to the graphics card. */ - data->fd = open(pathname, O_RDWR | O_CLOEXEC); - if (data->fd < 0) - { - rc = figure_out_card_open_error(pathname); - goto fail_data; - } - - /* Acquire mode resources. */ - data->res = drmModeGetResources(data->fd); - if (data->res == NULL) - { - rc = LIBGAMMA_ACQUIRING_MODE_RESOURCES_FAILED; - goto fail_fd; - } - - /* Get the number of CRTC:s that are available in the partition. */ - if (data->res->count_crtcs < 0) - { - rc = LIBGAMMA_NEGATIVE_CRTC_COUNT; - goto fail_res; - } - this->crtcs_available = (size_t)(data->res->count_crtcs); - return 0; - - fail_res: - drmModeFreeResources(data->res); - fail_fd: - close(data->fd); - fail_data: - free(data); - return rc; -} - - -/** - * 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* restrict data = this->data; - release_connectors_and_encoders(data); - if (data->res != NULL) - drmModeFreeResources(data->res); - if (data->fd >= 0) - close(data->fd); - free(data); -} - - -/** - * Restore the gamma ramps all CRTC:s with a partition to the system settings. - * - * @param this The partition state. - * @return Zero on success, otherwise (negative) the value of an - * error identifier provided by this library. - */ -int libgamma_linux_drm_partition_restore(libgamma_partition_state_t* restrict this) -{ - (void) this; - return errno = ENOTSUP, LIBGAMMA_ERRNO_SET; -} - - - -/** - * Initialise an allocated CRTC state. - * - * @param this The CRTC state to initialise. - * @param partition The partition state for the partition that the CRTC belongs to. - * @param crtc The the index of the CRTC within the site. - * @return Zero on success, otherwise (negative) the value of an - * error identifier provided by this library. - */ -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* restrict card; - uint32_t crtc_id; - - if (crtc >= partition->crtcs_available) - return LIBGAMMA_NO_SUCH_CRTC; - - card = partition->data; - crtc_id = card->res->crtcs[crtc]; - this->data = (void*)(size_t)crtc_id; - return 0; -} - - -/** - * Release all resources held by a CRTC state. - * - * @param this The CRTC state. - */ -void libgamma_linux_drm_crtc_destroy(libgamma_crtc_state_t* restrict this) -{ - (void) this; -} - - -/** - * Restore the gamma ramps for a CRTC to the system settings for that CRTC. - * - * @param this The CRTC state. - * @return Zero on success, otherwise (negative) the value of an - * error identifier provided by this library. - */ -int libgamma_linux_drm_crtc_restore(libgamma_crtc_state_t* restrict this) -{ - (void) this; - return errno = ENOTSUP, LIBGAMMA_ERRNO_SET; -} - - -/** - * 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* restrict 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. - * @param crtc The state of the CRTC whose information should be read. - * @return The value stored in `out->gamma_size_error`. - */ -static int get_gamma_ramp_size(libgamma_crtc_information_t* restrict out, const libgamma_crtc_state_t* restrict crtc) -{ - libgamma_drm_card_data_t* restrict card = crtc->partition->data; - uint32_t crtc_id = card->res->crtcs[crtc->crtc]; - drmModeCrtc* restrict crtc_info; - errno = 0; - crtc_info = drmModeGetCrtc(card->fd, crtc_id); - out->gamma_size_error = crtc_info == NULL ? errno : 0; - if (out->gamma_size_error == 0) - { - out->red_gamma_size = (size_t)(crtc_info->gamma_size); - out->green_gamma_size = (size_t)(crtc_info->gamma_size); - out->blue_gamma_size = (size_t)(crtc_info->gamma_size); - out->gamma_size_error = crtc_info->gamma_size < 2 ? LIBGAMMA_SINGLETON_GAMMA_RAMP : 0; - drmModeFreeCrtc(crtc_info); - } - return out->gamma_size_error; -} - - -/** - * Get the a monitor's subpixel order - * - * @param out Instance of a data structure to fill with the information about the CRTC. - * @param connector The connector. - */ -static void get_subpixel_order(libgamma_crtc_information_t* restrict out, - const drmModeConnector* restrict connector) -{ -#define __select(value) \ - case DRM_MODE_SUBPIXEL_##value: \ - out->subpixel_order = LIBGAMMA_SUBPIXEL_ORDER_##value; \ - break - - switch (connector->subpixel) - { - __select (UNKNOWN); - __select (HORIZONTAL_RGB); - __select (HORIZONTAL_BGR); - __select (VERTICAL_RGB); - __select (VERTICAL_BGR); - __select (NONE); - default: - out->subpixel_order_error = LIBGAMMA_SUBPIXEL_ORDER_NOT_RECOGNISED; - break; - } - -#undef __select -} - - -/** - * Get a connector's type - * - * @param out Instance of a data structure to fill with the information about the CRTC. - * @param connector The connector. - * @param connector_name_base Output for the basename of the connector. - */ -static void get_connector_type(libgamma_crtc_information_t* restrict out, - const drmModeConnector* restrict connector, - const char** restrict connector_name_base) -{ -#define __select(type, name) \ - case DRM_MODE_CONNECTOR_##type: \ - out->connector_type = LIBGAMMA_CONNECTOR_TYPE_##type; \ - *connector_name_base = name; \ - break - - switch (connector->connector_type) - { -#ifndef DRM_MODE_CONNECTOR_VIRTUAL -# define DRM_MODE_CONNECTOR_VIRTUAL 15 -#endif -#ifndef DRM_MODE_CONNECTOR_DSI -# define DRM_MODE_CONNECTOR_DSI 16 -#endif - __select (Unknown, "Unknown" ); - __select (VGA, "VGA" ); - __select (DVII, "DVI-I" ); - __select (DVID, "DVI-D" ); - __select (DVIA, "DVI-A" ); - __select (Composite, "Composite"); - __select (SVIDEO, "SVIDEO" ); - __select (LVDS, "LVDS" ); - __select (Component, "Component"); - __select (9PinDIN, "DIN" ); - __select (DisplayPort, "DP" ); - __select (HDMIA, "HDMI-A" ); - __select (HDMIB, "HDMI-B" ); - __select (TV, "TV" ); - __select (eDP, "eDP" ); - __select (VIRTUAL, "VIRTUAL" ); - __select (DSI, "DSI" ); - default: - out->connector_type_error = LIBGAMMA_CONNECTOR_TYPE_NOT_RECOGNISED; - out->connector_name_error = LIBGAMMA_CONNECTOR_TYPE_NOT_RECOGNISED; - break; - } - -#undef __select -} - - -/** - * Read information from the CRTC's conncetor. - * - * @param crtc The state of the CRTC whose information should be read. - * @param out Instance of a data structure to fill with the information about the CRTC. - * @param connector The CRTC's connector. - * @param fields OR:ed identifiers for the information about the CRTC that should be read. - * @return Non-zero if at least on error occured. - */ -static int read_connector_data(libgamma_crtc_state_t* restrict crtc, libgamma_crtc_information_t* restrict out, - const drmModeConnector* restrict connector, int32_t fields) -{ - const char* connector_name_base = NULL; - - /* Get some information that does not require too much work. */ - if ((fields & (LIBGAMMA_CRTC_INFO_WIDTH_MM | LIBGAMMA_CRTC_INFO_HEIGHT_MM | LIBGAMMA_CRTC_INFO_CONNECTOR_TYPE | - LIBGAMMA_CRTC_INFO_ACTIVE | LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER))) - { - /* Get whether or not a monitor is plugged in. */ - out->active = connector->connection == DRM_MODE_CONNECTED; - out->active_error = connector->connection == DRM_MODE_UNKNOWNCONNECTION ? LIBGAMMA_STATE_UNKNOWN : 0; - if (out->active == 0) - { - if ((fields & (LIBGAMMA_CRTC_INFO_WIDTH_MM | LIBGAMMA_CRTC_INFO_HEIGHT_MM | LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER))) - out->width_mm_error = out->height_mm_error = out->subpixel_order_error = LIBGAMMA_NOT_CONNECTED; - goto not_connected; - } - - /* Get viewport dimension. */ - out->width_mm = connector->mmWidth; - out->height_mm = connector->mmHeight; - - /* Get subpixel order. */ - get_subpixel_order(out, connector); - - not_connected: - - /* Get connector type. */ - get_connector_type(out, connector, &connector_name_base); - } - - /* Get the connector's name. */ - if ((fields & LIBGAMMA_CRTC_INFO_CONNECTOR_NAME) && (out->connector_name_error == 0)) - { - libgamma_drm_card_data_t* restrict card = crtc->partition->data; - uint32_t type = connector->connector_type; - size_t i, n = (size_t)(card->res->count_connectors), c = 0; - - out->connector_name = malloc((strlen(connector_name_base) + 12) * sizeof(char)); - if (out->connector_name == NULL) - return (out->connector_name_error = errno); - - for (i = 0; (i < n) && (card->connectors[i] != connector); i++) - if (card->connectors[i]->connector_type == type) - c++; - sprintf(out->connector_name, "%s-" PRIu32, connector_name_base, (uint32_t)(c + 1)); - } - - /* Did something go wrong? */ - return out->subpixel_order_error | out->active_error | out->connector_name_error; -} - - -/** - * Get the extended display identification data for a monitor. - * - * @param crtc The CRTC state. - * @param out Instance of a data structure to fill with the information about the CRTC. - * @param connector The CRTC's connector. - * @reutnr Non-zero on error. - */ -static int get_edid(libgamma_crtc_state_t* restrict crtc, - libgamma_crtc_information_t* restrict out, drmModeConnector* connector) -{ - libgamma_drm_card_data_t* restrict card = crtc->partition->data; - int prop_n = connector->count_props; - int prop_i; - drmModePropertyRes* restrict prop; - drmModePropertyBlobRes* restrict blob; - - for (prop_i = 0; prop_i < prop_n; prop_i++) - { - prop = drmModeGetProperty(card->fd, connector->props[prop_i]); - if (prop == NULL) - continue; - if (!strcmp("EDID", prop->name)) - { - blob = drmModeGetPropertyBlob(card->fd, (uint32_t)(connector->prop_values[prop_i])); - if (blob == NULL) - { - drmModeFreeProperty(prop); - return out->edid_error = LIBGAMMA_PROPERTY_VALUE_QUERY_FAILED; - } - if (blob->data != NULL) - { - out->edid_length = blob->length; - out->edid = malloc(out->edid_length * sizeof(unsigned char)); - if (out->edid == NULL) - out->edid_error = errno; - else - memcpy(out->edid, blob->data, (size_t)(out->edid_length) * sizeof(char)); - drmModeFreePropertyBlob(blob); - return out->edid == NULL; - } - drmModeFreePropertyBlob(blob); - } - drmModeFreeProperty(prop); - } - return out->edid_error = LIBGAMMA_EDID_NOT_FOUND; -} - - -/** - * Read information about 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. - * @param fields OR:ed identifiers for the information about the CRTC that should be read. - * @return Zero on success, -1 on error. On error refer to the error reports in `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; - drmModeConnector* restrict connector; - int require_connector; - int free_edid; - int error; - - - /* 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 & LIBGAMMA_CRTC_INFO_EDID) == 0; - - /* Figure out what fields we need to get the data for to get the data for other fields. */ - if ((fields & (LIBGAMMA_CRTC_INFO_WIDTH_MM_EDID | LIBGAMMA_CRTC_INFO_HEIGHT_MM_EDID | LIBGAMMA_CRTC_INFO_GAMMA))) - fields |= LIBGAMMA_CRTC_INFO_EDID; - if ((fields & LIBGAMMA_CRTC_INFO_CONNECTOR_NAME)) - fields |= LIBGAMMA_CRTC_INFO_CONNECTOR_TYPE; - if (LIBGAMMA_CRTC_INFO_EDID | LIBGAMMA_CRTC_INFO_WIDTH_MM | LIBGAMMA_CRTC_INFO_HEIGHT_MM | LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER) - fields |= LIBGAMMA_CRTC_INFO_ACTIVE; - - /* Figure out whether we require the connector to get all information we want. */ - require_connector = fields & (LIBGAMMA_CRTC_INFO_ACTIVE | LIBGAMMA_CRTC_INFO_CONNECTOR_TYPE); - - if (require_connector == 0) - goto cont; - 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 - = this->edid_error = this->gamma_error - = this->width_mm_edid_error = this->height_mm_edid_error = error; - goto cont; - } - e |= read_connector_data(crtc, this, connector, fields); - if ((fields & LIBGAMMA_CRTC_INFO_EDID) == 0) - goto cont; - if (this->active_error || (this->active == 0)) - { - e |= this->edid_error = this->gamma_error - = this->width_mm_edid_error = this->height_mm_edid_error - = LIBGAMMA_NOT_CONNECTED; - goto cont; - } - e |= get_edid(crtc, this, connector); - if (this->edid == NULL) - { - this->gamma_error = this->width_mm_edid_error = this->height_mm_edid_error = this->edid_error; - goto cont; - } - if ((fields & (LIBGAMMA_CRTC_INFO_WIDTH_MM_EDID | LIBGAMMA_CRTC_INFO_HEIGHT_MM_EDID | LIBGAMMA_CRTC_INFO_GAMMA))) - e |= libgamma_parse_edid(this, fields); - cont: - e |= (fields & LIBGAMMA_CRTC_INFO_GAMMA_SIZE) ? get_gamma_ramp_size(this, crtc) : 0; - this->gamma_depth = 16; - e |= this->gamma_support_error = _E(LIBGAMMA_CRTC_INFO_GAMMA_SUPPORT); - - /* Free the EDID after us. */ - if (free_edid) - { - free(this->edid); - this->edid = NULL; - } - - return e ? -1 : 0; -#undef _E -} - - -/** - * Get current the gamma ramps for a CRTC, 16-bit gamma-depth version. - * - * @param this The CRTC state. - * @param ramps The gamma ramps to fill with the current values. - * @return Zero on success, otherwise (negative) the value of an - * error identifier provided by this library. - */ -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* 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)(size_t)(this->data), (uint32_t)(ramps->red_size), - ramps->red, ramps->green, ramps->blue); - return r ? LIBGAMMA_GAMMA_RAMP_READ_FAILED : 0; -} - - -/** - * Set the gamma ramps for a CRTC, 16-bit gamma-depth version. - * - * @param this The CRTC state. - * @param ramps The gamma ramps to apply. - * @return Zero on success, otherwise (negative) the value of an - * error identifier provided by this library. - */ -int libgamma_linux_drm_crtc_set_gamma_ramps(libgamma_crtc_state_t* restrict this, - libgamma_gamma_ramps_t ramps) -{ - 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 = drmModeCrtcSetGamma(card->fd, (uint32_t)(size_t)(this->data), - (uint32_t)(ramps.red_size), ramps.red, ramps.green, ramps.blue); - if (r) - switch (errno) - { - case EACCES: - case EAGAIN: - case EIO: - /* Permission denied errors must be ignored, because we do not - * have permission to do this while a display server is active. - * We are also checking for some other error codes just in case. */ - case EBUSY: - case EINPROGRESS: - /* It is hard to find documentation for DRM (in fact all of this is - * just based on the functions names and some testing,) perhaps we - * could get this if we are updating to fast. */ - break; - case EBADF: - case ENODEV: - case ENXIO: - /* XXX: I have not actually tested removing my graphics card or, - * monitor but I imagine either of these is what would happen. */ - return LIBGAMMA_GRAPHICS_CARD_REMOVED; - - default: - return LIBGAMMA_ERRNO_SET; - } - return 0; -} - |