diff options
171 files changed, 4559 insertions, 4178 deletions
@@ -23,10 +23,6 @@ OS = linux include mk/$(OS).mk -HDR_METHODS = -CPPFLAGS_METHODS = -METHODS_PARAMS = - QUARTZ_CORE_GRAPHICS_METHOD = $(QUARTZ_CG_METHOD) include mk/method-x-randr=$(X_RANDR_METHOD).mk include mk/method-x-vidmode=$(X_VIDMODE_METHOD).mk @@ -35,6 +31,20 @@ include mk/method-w32-gdi=$(W32_GDI_METHOD).mk include mk/method-quartz-cg=$(QUARTZ_CORE_GRAPHICS_METHOD).mk include mk/method-dummy=$(DUMMY_METHOD).mk +# Need to do it this way since += is not in the POSIX make +HDR_METHODS = $(HDR_X_RANDR) $(HDR_X_VIDMODE) $(HDR_LINUX_DRM)\ + $(HDR_W32_GDI) $(HDR_QUARTZ_GC) $(HDR_DUMMY) +OBJ_METHODS = $(OBJ_X_RANDR) $(OBJ_X_VIDMODE) $(OBJ_LINUX_DRM)\ + $(OBJ_W32_GDI) $(OBJ_QUARTZ_GC) $(OBJ_DUMMY) +METHODS_PARAMS = $(PARAMS_X_RANDR) $(PARAMS_X_VIDMODE) $(PARAMS_LINUX_DRM)\ + $(PARAMS_W32_GDI) $(PARAMS_QUARTZ_GC) $(PARAMS_DUMMY) +CPPFLAGS_METHODS = $(CPPFLAGS_X_RANDR) $(CPPFLAGS_X_VIDMODE) $(CPPFLAGS_LINUX_DRM)\ + $(CPPFLAGS_W32_GDI) $(CPPFLAGS_QUARTZ_GC) $(CPPFLAGS_DUMMY) +CFLAGS_METHODS = $(CFLAGS_X_RANDR) $(CFLAGS_X_VIDMODE) $(CFLAGS_LINUX_DRM)\ + $(CFLAGS_W32_GDI) $(CFLAGS_QUARTZ_GC) $(CFLAGS_DUMMY) +LDFLAGS_METHODS = $(LDFLAGS_X_RANDR) $(LDFLAGS_X_VIDMODE) $(LDFLAGS_LINUX_DRM)\ + $(LDFLAGS_W32_GDI) $(LDFLAGS_QUARTZ_GC) $(LDFLAGS_DUMMY) + OBJ_PUBLIC =\ libgamma_behex_edid.o\ @@ -117,7 +127,8 @@ OBJ_PUBLIC =\ libgamma_value_of_connector_type.o\ libgamma_value_of_error.o\ libgamma_value_of_method.o\ - libgamma_value_of_subpixel_order.o + libgamma_value_of_subpixel_order.o\ + legacy.o OBJ_INTERNAL =\ libgamma_internal_allocated_any_ramp.o\ @@ -125,9 +136,9 @@ OBJ_INTERNAL =\ libgamma_internal_translated_ramp_get_.o\ libgamma_internal_translated_ramp_set_.o\ libgamma_internal_translate_from_64.o\ - libgamma_internal_translate_to_64.o\ + libgamma_internal_translate_to_64.o -OBJ = $(OBJ_PUBLIC) $(OBJ_INTERNAL) +OBJ = $(OBJ_PUBLIC) $(OBJ_INTERNAL) $(OBJ_METHODS) LOBJ = $(OBJ:.o=.lo) HDR =\ @@ -1,10 +1,14 @@ /* See LICENSE file for copyright and license details. */ #include "libgamma.h" +#include <sys/stat.h> #include <sys/types.h> #include <ctype.h> -#include <fcntl.h> #include <errno.h> +#include <fcntl.h> +#include <grp.h> +#include <inttypes.h> +#include <limits.h> #include <stddef.h> #include <stdint.h> #include <stdio.h> @@ -20,6 +24,19 @@ #endif +#ifdef __linux__ +# ifndef O_CLOEXEC +# define O_CLOEXEC 02000000 +# endif +# ifndef NGROUPS_MAX +# define NGROUPS_MAX 65536 +# endif +# ifndef PATH_MAX +# define PATH_MAX 4096 +# endif +#endif + + #define LIST_ERRORS(_)\ _(LIBGAMMA_ERRNO_SET, NULL)\ @@ -69,7 +86,7 @@ _(LIBGAMMA_PROPERTY_VALUE_QUERY_FAILED, "Could not query the value of a property")\ _(LIBGAMMA_OUTPUT_INFORMATION_QUERY_FAILED, "Could not query information for output") -#define X(A, B) -1 +#define X(...) -1 # if (LIST_ERRORS(X)) != LIBGAMMA_ERROR_MIN # error There is a mismatch between LIST_ERRORS and LIBGAMMA_ERROR_MIN # endif @@ -113,6 +130,7 @@ # define HAVE_METHOD_QUARTZ_CORE_GRAPHICS 0 #endif +/* CONST, NAME, CNAME, AVAILABLE */ #define LIST_METHODS(_)\ _(LIBGAMMA_METHOD_X_RANDR, randr, x_randr, HAVE_METHOD_X_RANDR)\ _(LIBGAMMA_METHOD_X_VIDMODE, vidmode, x_vidmode, HAVE_METHOD_X_VIDMODE)\ @@ -129,29 +147,33 @@ +/* CONST, NAME, DRM_MODE_CONNECTOR_SUFFIX */ #define LIST_CONNECTOR_TYPES(_)\ - _(LIBGAMMA_CONNECTOR_TYPE_Unknown, "Unknown")\ - _(LIBGAMMA_CONNECTOR_TYPE_VGA, "VGA")\ - _(LIBGAMMA_CONNECTOR_TYPE_DVI, "DVI")\ - _(LIBGAMMA_CONNECTOR_TYPE_DVII, "DVI-I")\ - _(LIBGAMMA_CONNECTOR_TYPE_DVID, "DVI-D")\ - _(LIBGAMMA_CONNECTOR_TYPE_DVIA, "DVI-A")\ - _(LIBGAMMA_CONNECTOR_TYPE_Composite, "Composite")\ - _(LIBGAMMA_CONNECTOR_TYPE_SVIDEO, "S-video")\ - _(LIBGAMMA_CONNECTOR_TYPE_LVDS, "LVDS")\ - _(LIBGAMMA_CONNECTOR_TYPE_Component, "Component")\ - _(LIBGAMMA_CONNECTOR_TYPE_9PinDIN, "9 pin DIN")\ - _(LIBGAMMA_CONNECTOR_TYPE_DisplayPort, "DisplayPort")\ - _(LIBGAMMA_CONNECTOR_TYPE_HDMI, "HDMI")\ - _(LIBGAMMA_CONNECTOR_TYPE_HDMIA, "HDMI-A")\ - _(LIBGAMMA_CONNECTOR_TYPE_HDMIB, "HDMI-B")\ - _(LIBGAMMA_CONNECTOR_TYPE_TV, "TV")\ - _(LIBGAMMA_CONNECTOR_TYPE_eDP, "eDP")\ - _(LIBGAMMA_CONNECTOR_TYPE_VIRTUAL, "Virtual")\ - _(LIBGAMMA_CONNECTOR_TYPE_DSI, "DSI")\ - _(LIBGAMMA_CONNECTOR_TYPE_LFP, "LFP") - -#define X(A, B) +1 + _(LIBGAMMA_CONNECTOR_TYPE_Unknown, "Unknown", Unknown)\ + _(LIBGAMMA_CONNECTOR_TYPE_VGA, "VGA", VGA)\ + _(LIBGAMMA_CONNECTOR_TYPE_DVI, "DVI", DVI)\ + _(LIBGAMMA_CONNECTOR_TYPE_DVII, "DVI-I", DVII)\ + _(LIBGAMMA_CONNECTOR_TYPE_DVID, "DVI-D", DVID)\ + _(LIBGAMMA_CONNECTOR_TYPE_DVIA, "DVI-A", DVIA)\ + _(LIBGAMMA_CONNECTOR_TYPE_Composite, "Composite", Composite)\ + _(LIBGAMMA_CONNECTOR_TYPE_SVIDEO, "S-Video", SVIDEO)\ + _(LIBGAMMA_CONNECTOR_TYPE_LVDS, "LVDS", LVDS)\ + _(LIBGAMMA_CONNECTOR_TYPE_Component, "Component", Component)\ + _(LIBGAMMA_CONNECTOR_TYPE_9PinDIN, "9 pin DIN", 9PinDIN)\ + _(LIBGAMMA_CONNECTOR_TYPE_DisplayPort, "DisplayPort", DisplayPort)\ + _(LIBGAMMA_CONNECTOR_TYPE_HDMI, "HDMI", HDMI)\ + _(LIBGAMMA_CONNECTOR_TYPE_HDMIA, "HDMI-A", HDMIA)\ + _(LIBGAMMA_CONNECTOR_TYPE_HDMIB, "HDMI-B", HDMIB)\ + _(LIBGAMMA_CONNECTOR_TYPE_TV, "TV", TV)\ + _(LIBGAMMA_CONNECTOR_TYPE_eDP, "eDP", eDP)\ + _(LIBGAMMA_CONNECTOR_TYPE_VIRTUAL, "Virtual", VIRTUAL)\ + _(LIBGAMMA_CONNECTOR_TYPE_DSI, "DSI", DSI)\ + _(LIBGAMMA_CONNECTOR_TYPE_LFP, "LFP", LFP)\ + _(LIBGAMMA_CONNECTOR_TYPE_DPI, "DPI", DPI)\ + _(LIBGAMMA_CONNECTOR_TYPE_WRITEBACK, "Writeback", WRITEBACK)\ + _(LIBGAMMA_CONNECTOR_TYPE_SPI, "SPI", SPI) + +#define X(...) +1 # if (LIST_CONNECTOR_TYPES(X)) != LIBGAMMA_CONNECTOR_TYPE_COUNT # error There is a mismatch between LIST_CONNECTOR_TYPES and LIBGAMMA_CONNECTOR_TYPE_COUNT # endif @@ -159,15 +181,16 @@ +/* CONST, NAME, DRM_MODE_SUBPIXEL_SUFFIX/XCB_RENDER_SUB_PIXEL_SUFFIX */ #define LIST_SUBPIXEL_ORDERS(_)\ - _(LIBGAMMA_SUBPIXEL_ORDER_UNKNOWN, "Unknown")\ - _(LIBGAMMA_SUBPIXEL_ORDER_NONE, "None")\ - _(LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_RGB, "Horizontal RGB")\ - _(LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_BGR, "Horizontal BGR")\ - _(LIBGAMMA_SUBPIXEL_ORDER_VERTICAL_RGB, "Vertical RGB")\ - _(LIBGAMMA_SUBPIXEL_ORDER_VERTICAL_BGR, "Vertical BGR") - -#define X(A, B) +1 + _(LIBGAMMA_SUBPIXEL_ORDER_UNKNOWN, "Unknown", UNKNOWN)\ + _(LIBGAMMA_SUBPIXEL_ORDER_NONE, "None", NONE)\ + _(LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_RGB, "Horizontal RGB", HORIZONTAL_RGB)\ + _(LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_BGR, "Horizontal BGR", HORIZONTAL_BGR)\ + _(LIBGAMMA_SUBPIXEL_ORDER_VERTICAL_RGB, "Vertical RGB", VERTICAL_RGB)\ + _(LIBGAMMA_SUBPIXEL_ORDER_VERTICAL_BGR, "Vertical BGR", VERTICAL_BGR) + +#define X(...) +1 # if (LIST_SUBPIXEL_ORDERS(X)) != LIBGAMMA_SUBPIXEL_ORDER_COUNT # error There is a mismatch between LIST_SUBPIXEL_ORDERS and LIBGAMMA_SUBPIXEL_ORDER_COUNT # endif @@ -220,6 +243,7 @@ typedef union gamma_ramps_any { * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) typedef int get_ramps_any_fun(libgamma_crtc_state_t *restrict, gamma_ramps_any_t *restrict); /** @@ -230,7 +254,8 @@ typedef int get_ramps_any_fun(libgamma_crtc_state_t *restrict, gamma_ramps_any_t * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -typedef int set_ramps_any_fun(libgamma_crtc_state_t *restrict, gamma_ramps_any_t); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) +typedef int set_ramps_any_fun(libgamma_crtc_state_t *restrict, const gamma_ramps_any_t *restrict); @@ -285,6 +310,7 @@ typedef int set_ramps_any_fun(libgamma_crtc_state_t *restrict, gamma_ramps_any_t * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_internal_translated_ramp_get_(libgamma_crtc_state_t *restrict, gamma_ramps_any_t *restrict, signed, signed, get_ramps_any_fun *); @@ -303,7 +329,8 @@ int libgamma_internal_translated_ramp_get_(libgamma_crtc_state_t *restrict, gamm * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -int libgamma_internal_translated_ramp_set_(libgamma_crtc_state_t *restrict, gamma_ramps_any_t, +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) +int libgamma_internal_translated_ramp_set_(libgamma_crtc_state_t *restrict, const gamma_ramps_any_t *restrict, signed, signed, set_ramps_any_fun *); /** @@ -314,7 +341,8 @@ int libgamma_internal_translated_ramp_set_(libgamma_crtc_state_t *restrict, gamm * @param out Output array * @param in Input gamma ramps */ -void libgamma_internal_translate_to_64(signed, size_t, uint64_t *restrict, gamma_ramps_any_t); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) +void libgamma_internal_translate_to_64(signed, size_t, uint64_t *restrict, const gamma_ramps_any_t *restrict); /** * Undo the actions of `libgamma_internal_translate_to_64` @@ -324,7 +352,8 @@ void libgamma_internal_translate_to_64(signed, size_t, uint64_t *restrict, gamma * @param out Output gamma ramps * @param in Input array, may be modified */ -void libgamma_internal_translate_from_64(signed, size_t, gamma_ramps_any_t, uint64_t *restrict); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) +void libgamma_internal_translate_from_64(signed, size_t, gamma_ramps_any_t *restrict, const uint64_t *restrict); /** * Allocate and initalise a gamma ramp with any depth @@ -337,7 +366,8 @@ void libgamma_internal_translate_from_64(signed, size_t, gamma_ramps_any_t, uint * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -int libgamma_internal_allocated_any_ramp(gamma_ramps_any_t *restrict, gamma_ramps_any_t, signed, size_t *restrict); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) +int libgamma_internal_allocated_any_ramp(gamma_ramps_any_t *restrict, const gamma_ramps_any_t *restrict, signed, size_t *restrict); /** @@ -349,4 +379,5 @@ int libgamma_internal_allocated_any_ramp(gamma_ramps_any_t *restrict, gamma_ramp * fields that do not have to do with EDID are ignored * @return Non-zero on error */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_internal_parse_edid(libgamma_crtc_information_t *restrict, int32_t); @@ -1,6 +1,6 @@ PREFIX = /usr MANPREFIX = $(PREFIX)/share/man -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE CFLAGS = -std=c11 -O2 LDFLAGS = -s diff --git a/gamma-dummy.c.gpp b/gamma-dummy.c.gpp deleted file mode 100644 index 4cc758d..0000000 --- a/gamma-dummy.c.gpp +++ /dev/null @@ -1,993 +0,0 @@ -/* -*- c -*- */ -/* See LICENSE file for copyright and license details. */ -#ifndef HAVE_LIBGAMMA_METHOD_DUMMY -# error Compiling gamma-dummy.c without HAVE_LIBGAMMA_METHOD_DUMMY -#endif - -#include "gamma-dummy.h" - -#include "libgamma-error.h" -#include "libgamma-method.h" -#include "libgamma-facade.h" -#include "edid.h" -#include "gamma-helper.h" - -#include <errno.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - - - -/** - * Configuration set for the dummy adjustment method - */ -typedef struct libgamma_dummy_configurations { - /** - * The method's capabilities - * - * Some fields are ignored: - * - real - * - fake - */ - libgamma_method_capabilities_t capabilities; - - /** - * Template for CRTC:s information - * - * Some fields are ignored: - * - width_mm_edid - * - width_mm_edid_error - * - height_mm_edid - * - height_mm_edid_error - * - gamma_red - * - gamma_green - * - gamma_blue - * - gamma_error - */ - libgamma_crtc_information_t crtc_info_template; - - /** - * The adjustment method to use - */ - int real_method; - - /** - * The number of sites on the system - */ - size_t site_count; - - /** - * The number of paritions on a site before it has been configured - */ - size_t default_partition_count; - - /** - * The number of CRTC:s on a paritions before it has been configured - */ - size_t default_crtc_count; - - /** - * Whether the sites should be inherited from the real method - */ - unsigned inherit_sites : 1; - - /** - * Whether the partitions should be inherited from the real method - */ - unsigned inherit_partition_count : 1; - - /** - * Whether the CRTC:s should be inherited from the real method - */ - unsigned inherit_crtc_count : 1; - - /** - * When a site has been created, stall until the partition count has - * been configured - */ - unsigned stall_for_partition_count : 1; - - /** - * When a parition has been created, stall until the CRTC count has - * been configured - */ - unsigned stall_for_crtc_count : 1; - - /** - * Methods should stall until the system has been configured - * unless $LIBGAMMA_DUMMY_STALL is not true - */ - unsigned stalled_start : 1; - - /** - * Whether to print what is going on in the phony system - */ - unsigned verbose : 1; - -} libgamma_dummy_configurations_t; - - -/** - * Dummy adjustment method internal data for a CRTC - */ -typedef struct libgamma_dummy_crtc { - /** - * The gamma ramp for the red channel - */ - void *restrict gamma_red; - - /** - * The gamma ramp for the green channel - */ - void *restrict gamma_green; - - /** - * The gamma ramp for the blue channel - */ - void *restrict gamma_blue; - - /** - * Information about the CRTC and monitor - * - * Some fields are ignored: - * - width_mm_edid - * - width_mm_edid_error - * - height_mm_edid - * - height_mm_edid_error - * - gamma_red - * - gamma_green - * - gamma_blue - * - gamma_error - */ - libgamma_crtc_information_t info; - - /** - * Partition state that contains this information - */ - libgamma_crtc_state_t *state; - -} libgamma_dummy_crtc_t; - - -/** - * Dummy adjustment method internal data for a partition - */ -typedef struct libgamma_dummy_partition { - /** - * The CRTC:s on the system - */ - libgamma_dummy_crtc_t *crtcs; - - /** - * The number of CRTC:s on the system - */ - size_t crtc_count; - - /** - * Partition state that contains this information - */ - libgamma_partition_state_t *state; - -} libgamma_dummy_partition_t; - - -/** - * Dummy adjustment method internal data for a site - */ -typedef struct libgamma_dummy_site { - /** - * The partitions on the system - */ - libgamma_dummy_partition_t *partitions; - - /** - * The number of partitions on the system - */ - size_t partition_count; - - /** - * Site state that contains this information - */ - libgamma_site_state_t *state; - -} libgamma_dummy_site_t; - - - -/** - * Restore the gamma ramps for a CRTC to the system settings for that CRTC - * and ignore the method's capabilities - * - * @param this The CRTC data - * @return Zero on success, otherwise (negative) the value of an - * error identifier provided by this library - */ -static int libgamma_dummy_crtc_restore_forced(libgamma_dummy_crtc_t *restrict data); - - - -/** - * Configurations for the dummy adjustment method. - */ -static libgamma_dummy_configurations_t libgamma_dummy_configurations = { - .capabilities = { - .crtc_information = (1 << LIBGAMMA_CRTC_INFO_COUNT) - 1, - .default_site_known = 1, - .multiple_sites = 1, - .multiple_partitions = 1, - .multiple_crtcs = 1, - .partitions_are_graphics_cards = 1, - .site_restore = 1, - .partition_restore = 1, - .crtc_restore = 1, - .identical_gamma_sizes = 0, - .fixed_gamma_size = 0, - .fixed_gamma_depth = 0 - }, - .crtc_info_template = { - .edid = NULL, - .edid_length = 0, - .edid_error = LIBGAMMA_EDID_NOT_FOUND, - .width_mm = 400, - .width_mm_error = 0, - .height_mm = 300, - .height_mm_error = 0, - .red_gamma_size = 1024, - .green_gamma_size = 2048, - .blue_gamma_size = 512, - .gamma_size_error = 0, - .gamma_depth = 64, - .gamma_depth_error = 0, - .gamma_support = 1, - .gamma_support_error = 0, - .subpixel_order = LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_RGB, - .subpixel_order_error = 0, - .active = 1, - .active_error = 0, - .connector_name = NULL, - .connector_name_error = LIBGAMMA_CONNECTOR_TYPE_NOT_RECOGNISED, - .connector_type = LIBGAMMA_CONNECTOR_TYPE_Unknown, - .connector_type_error = 0 - }, - .real_method = LIBGAMMA_METHOD_DUMMY, - .site_count = 2, - .default_partition_count = 2, - .default_crtc_count = 2, - .inherit_sites = 1, - .inherit_partition_count = 1, - .inherit_crtc_count = 1, - .stall_for_partition_count = 0, - .stall_for_crtc_count = 0, - .stalled_start = 1, - .verbose = 0 -}; - - - -/** - * Return the capabilities of the adjustment method - * - * @param this The data structure to fill with the method's capabilities - */ -void -libgamma_dummy_method_capabilities(libgamma_method_capabilities_t *restrict this) -{ - int real_method = libgamma_dummy_configurations.real_method; - *this = libgamma_dummy_configurations.capabilities; - this->real = real_method != LIBGAMMA_METHOD_DUMMY; - this->fake = this->real; - this->auto_restore = real_method == LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS; -} - - -/** - * 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. Once 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_dummy_site_initialise(libgamma_site_state_t *restrict this, char *restrict site) -{ - libgamma_dummy_site_t *data = NULL; - size_t i, sites, crtcs; - - sites = libgamma_dummy_configurations.site_count; - if (!libgamma_dummy_configurations.capabilities.multiple_sites) - sites = !!sites; - this->data = NULL; - - if (site && *site && (atoll(site) < 0 || sites <= (unsigned long long)atoll(site))) - return LIBGAMMA_NO_SUCH_SITE; - - data = malloc(sizeof(libgamma_dummy_site_t)); - if (!data) - goto fail; - - this->data = data; - data->state = this; - - data->partition_count = libgamma_dummy_configurations.default_partition_count; - if (!libgamma_dummy_configurations.capabilities.multiple_partitions) - data->partition_count = !!data->partition_count; - - crtcs = libgamma_dummy_configurations.default_crtc_count; - if (!libgamma_dummy_configurations.capabilities.multiple_crtcs) - crtcs = !!crtcs; - - data->partitions = malloc(data->partition_count * sizeof(libgamma_dummy_partition_t)); - if (!data->partitions) - goto fail; - - for (i = 0; i < data->partition_count; i++) - data->partitions[i].crtc_count = crtcs; - - this->partitions_available = data->partition_count; - - return 0; - -fail: - free(data); - this->data = NULL; - return LIBGAMMA_ERRNO_SET; -} - - -/** - * Release all resources held by a site state - * - * @param this The site state - */ -void -libgamma_dummy_site_destroy(libgamma_site_state_t *restrict this) -{ - libgamma_dummy_site_t *data = this->data; - if (!data) - return; - - free(data->partitions); - free(data); -} - - -/** - * 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_dummy_site_restore(libgamma_site_state_t *restrict this) -{ - libgamma_dummy_site_t *data = this->data; - size_t i, j; - - if (!libgamma_dummy_configurations.capabilities.site_restore) { - errno = ENOTSUP; - return LIBGAMMA_ERRNO_SET; - } - - for (j = 0; j < data->partition_count; j++) - for (i = 0; i < data->partitions[j].crtc_count; i++) - if (libgamma_dummy_crtc_restore_forced(data->partitions[j].crtcs + i) < 0) - return -1; - - return 0; -} - - - -/** - * 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_dummy_partition_initialise(libgamma_partition_state_t *restrict this, - libgamma_site_state_t *restrict site, size_t partition) -{ - libgamma_crtc_information_t template = libgamma_dummy_configurations.crtc_info_template; - libgamma_dummy_site_t *site_data = site->data; - libgamma_dummy_partition_t *data = &site_data->partitions[partition]; - libgamma_dummy_crtc_t *crtc_data; - size_t i, n; - - this->data = NULL; - - if (partition >= site_data->partition_count) - return LIBGAMMA_NO_SUCH_PARTITION; - - this->data = data; - data->state = this; - - data->crtcs = calloc(data->crtc_count, sizeof(libgamma_dummy_crtc_t)); - if (!data->crtcs) - goto fail; - for (i = 0; i < data->crtc_count; i++) { - crtc_data = data->crtcs + i; - crtc_data->info = template; - - /* Duplicate strings */ - if (crtc_data->info.edid) { - crtc_data->info.edid = malloc(crtc_data->info.edid_length * sizeof(char)); - if (!crtc_data->info.edid) - goto fail; - memcpy(crtc_data->info.edid, template.edid, crtc_data->info.edid_length * sizeof(char)); - } - if (crtc_data->info.connector_name) { - n = strlen(crtc_data->info.connector_name); - crtc_data->info.connector_name = malloc((n + 1) * sizeof(char)); - if (crtc_data->info.connector_name == NULL) - goto fail; - memcpy(crtc_data->info.connector_name, template.connector_name, (n + 1) * sizeof(char)); - } - } - - this->crtcs_available = data->crtc_count; - - return 0; - -fail: - for (i = 0; i < data->crtc_count; i++) { - free(data->crtcs[i].info.edid); - free(data->crtcs[i].info.connector_name); - } - free(data->crtcs); - data->crtcs = NULL; - return LIBGAMMA_ERRNO_SET; -} - - -/** - * Release all resources held by a partition state - * - * @param this The partition state - */ -void -libgamma_dummy_partition_destroy(libgamma_partition_state_t *restrict this) -{ - libgamma_dummy_partition_t *data = this->data; - size_t i; - - if (data) { - for (i = 0; i < data->crtc_count; i++) { - free(data->crtcs[i].info.edid); - free(data->crtcs[i].info.connector_name); - } - free(data->crtcs); - data->crtcs = NULL; - } -} - - -/** - * 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_dummy_partition_restore(libgamma_partition_state_t *restrict this) -{ - libgamma_dummy_partition_t *data = this->data; - size_t i; - - if (!libgamma_dummy_configurations.capabilities.partition_restore) { - errno = ENOTSUP; - return LIBGAMMA_ERRNO_SET; - } - - for (i = 0; i < data->crtc_count; i++) - if (libgamma_dummy_crtc_restore_forced(data->crtcs + i) < 0) - return -1; - - return 0; -} - - - -/** - * 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_dummy_crtc_initialise(libgamma_crtc_state_t *restrict this, - libgamma_partition_state_t *restrict partition, size_t crtc) -{ - libgamma_dummy_partition_t *partition_data = partition->data; - libgamma_dummy_crtc_t *data = &partition_data->crtcs[crtc]; - size_t stop_size; - - this->data = NULL; - - if (crtc >= partition_data->crtc_count) - return LIBGAMMA_NO_SUCH_CRTC; - - this->data = data; - data->state = this; - - if (data->info.gamma_depth == -1) - stop_size = sizeof(float); - else if (data->info.gamma_depth == -2) - stop_size = sizeof(double); - else - stop_size = (size_t)data->info.gamma_depth / 8; - - data->gamma_red = malloc(data->info.red_gamma_size * stop_size); - if (!data->gamma_red) - goto fail; - data->gamma_green = malloc(data->info.green_gamma_size * stop_size); - if (!data->gamma_green) - goto fail; - data->gamma_blue = malloc(data->info.blue_gamma_size * stop_size); - if (!data->gamma_blue) - goto fail; - - return libgamma_dummy_crtc_restore_forced(data); - -fail: - free(data->gamma_red), data->gamma_red = NULL; - free(data->gamma_green), data->gamma_green = NULL; - free(data->gamma_blue), data->gamma_blue = NULL; - return LIBGAMMA_ERRNO_SET; -} - - -/** - * Release all resources held by a CRTC state - * - * @param this The CRTC state - */ -void -libgamma_dummy_crtc_destroy(libgamma_crtc_state_t *restrict this) -{ - libgamma_dummy_crtc_t *data = this->data; - if (data) { - free(data->gamma_red), data->gamma_red = NULL; - free(data->gamma_green), data->gamma_green = NULL; - free(data->gamma_blue), data->gamma_blue = NULL; - } -} - - -/** - * 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_dummy_crtc_restore(libgamma_crtc_state_t *restrict this) -{ - if (!libgamma_dummy_configurations.capabilities.crtc_restore) { - errno = ENOTSUP; - return LIBGAMMA_ERRNO_SET; - } - return libgamma_dummy_crtc_restore_forced(this->data); -} - - -/** - * Restore the gamma ramps for a CRTC to the system settings for that CRTC - * and ignore the method's capabilities - * - * @param this The CRTC data - * @return Zero on success, otherwise (negative) the value of an - * error identifier provided by this library - */ -static int -libgamma_dummy_crtc_restore_forced(libgamma_dummy_crtc_t *restrict data) -{ - size_t rn = data->info. red_gamma_size; - size_t gn = data->info.green_gamma_size; - size_t bn = data->info. blue_gamma_size; - size_t i; - - if (!data->gamma_red) - return 0; - -#define __reset_ramps(TYPE, MAX)\ - do {\ - TYPE *red = data->gamma_red;\ - TYPE *green = data->gamma_green;\ - TYPE *blue = data->gamma_blue;\ - for (i = 0; i < rn; i++) red [i] = (TYPE)((double)(MAX) * ((double)i / (double)(rn - 1)));\ - for (i = 0; i < gn; i++) green[i] = (TYPE)((double)(MAX) * ((double)i / (double)(gn - 1)));\ - for (i = 0; i < bn; i++) blue [i] = (TYPE)((double)(MAX) * ((double)i / (double)(bn - 1)));\ - } while (0) - - if (data->info.gamma_depth == 8) __reset_ramps(uint8_t, INT8_MAX); - else if (data->info.gamma_depth == 16) __reset_ramps(uint16_t, INT16_MAX); - else if (data->info.gamma_depth == 32) __reset_ramps(uint32_t, INT32_MAX); - else if (data->info.gamma_depth == 64) __reset_ramps(uint64_t, INT64_MAX); - else if (data->info.gamma_depth == -1) __reset_ramps(float, 1); - else __reset_ramps(double, 1); - -#undef __reset_ramps - - return 0; -} - - - -/** - * 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_dummy_get_crtc_information(libgamma_crtc_information_t *restrict this, - libgamma_crtc_state_t *restrict crtc, int32_t fields) -{ - libgamma_dummy_crtc_t *restrict data = crtc->data; - int supported = libgamma_dummy_configurations.capabilities.crtc_information; - int e = 0; - size_t n; - - /* Copy over information */ - *this = data->info; - - /* Duplicate strings */ - if (this->edid) { - this->edid = malloc(this->edid_length * sizeof(char)); - if (!this->edid) - this->edid_error = errno; - memcpy(this->edid, data->info.edid, this->edid_length * sizeof(char)); - } - if (this->connector_name) { - n = strlen(this->connector_name); - this->connector_name = malloc((n + 1) * sizeof(char)); - if (!this->connector_name) - this->connector_name_error = errno; - memcpy(this->connector_name, data->info.connector_name, (n + 1) * sizeof(char)); - } - - /* Parse EDID */ - if (this->edid_error) - this->width_mm_edid_error = this->height_mm_edid_error = this->gamma_error = this->edid_error; - else if (fields & (LIBGAMMA_CRTC_INFO_MACRO_EDID ^ LIBGAMMA_CRTC_INFO_EDID)) - e |= libgamma_internal_parse_edid(this, fields); - - /* Test errors */ -#define _E(FIELD, VAR)\ - ((fields & FIELD) ? ((supported & FIELD) ? VAR : (VAR = LIBGAMMA_CRTC_INFO_NOT_SUPPORTED)) : 0) - e |= _E(LIBGAMMA_CRTC_INFO_EDID, this->edid_error); - e |= _E(LIBGAMMA_CRTC_INFO_WIDTH_MM, this->width_mm_error); - e |= _E(LIBGAMMA_CRTC_INFO_HEIGHT_MM, this->height_mm_error); - e |= _E(LIBGAMMA_CRTC_INFO_GAMMA_SIZE, this->gamma_size_error); - e |= _E(LIBGAMMA_CRTC_INFO_GAMMA_DEPTH, this->gamma_depth_error); - e |= _E(LIBGAMMA_CRTC_INFO_GAMMA_SUPPORT, this->gamma_support_error); - e |= _E(LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER, this->subpixel_order_error); - e |= _E(LIBGAMMA_CRTC_INFO_ACTIVE, this->active_error); - e |= _E(LIBGAMMA_CRTC_INFO_CONNECTOR_NAME, this->connector_name_error); - e |= _E(LIBGAMMA_CRTC_INFO_CONNECTOR_TYPE, this->connector_type_error); - - if ((fields & LIBGAMMA_CRTC_INFO_WIDTH_MM_EDID) && !(supported & LIBGAMMA_CRTC_INFO_WIDTH_MM_EDID)) - e |= this->width_mm_edid_error = LIBGAMMA_CRTC_INFO_NOT_SUPPORTED; - if ((fields & LIBGAMMA_CRTC_INFO_HEIGHT_MM_EDID) && !(supported & LIBGAMMA_CRTC_INFO_HEIGHT_MM_EDID)) - e |= this->height_mm_edid_error = LIBGAMMA_CRTC_INFO_NOT_SUPPORTED; - if ((fields & LIBGAMMA_CRTC_INFO_GAMMA) && !(supported & LIBGAMMA_CRTC_INFO_GAMMA)) - e |= this->gamma_error = LIBGAMMA_CRTC_INFO_NOT_SUPPORTED; -#undef _E - - return e ? -1 : 0; -} - - -/** - * Get the current gamma ramps for a CRTC - * - * @param 1 The data type for the ramp stop elements - * @param 2 The `ramp*` pattern for the ramp structure and function to call. - * @param 3 Either of `bit8`, `bit16`, `bit32`, `bit64`, `float_single`, `float_double`; - * rather self-explanatory - * @param 4 The number of bits in the gamma depth, -1 for single precision float, - * (`float`) and -2 for double percition float (`double`) - * @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 - */ -$>libgamma_dummy_crtc_get_gamma_ramps () -$>{ -int -libgamma_dummy_crtc_get_gamma_${2}(libgamma_crtc_state_t *restrict this, libgamma_gamma_${2}_t *restrict ramps) -{ - libgamma_dummy_crtc_t *data = this->data; - gamma_ramps_any_t ramps_; - ${1}* r_ramp = data->gamma_red; - ${1}* g_ramp = data->gamma_green; - ${1}* b_ramp = data->gamma_blue; - size_t rn = data->info.red_gamma_size; - size_t gn = data->info.green_gamma_size; - size_t bn = data->info.blue_gamma_size; - size_t i; - -#ifdef DEBUG - /* Check gamma ramp sizes */ - if (libgamma_dummy_configurations.capabilities.identical_gamma_sizes) - if (ramps->red_size != ramps->green_size || ramps->red_size != ramps->blue_size) - return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; - if (ramps->red_size != rn || ramps->green_size != gn || ramps->blue_size != bn) - return LIBGAMMA_WRONG_GAMMA_RAMP_SIZE; -#endif - - if (!data->info.gamma_support) - return LIBGAMMA_GAMMA_RAMP_READ_FAILED; - -#define __trans(DEPTH, SUFFIX)\ - do {\ - if (data->info.gamma_depth == DEPTH) {\ - ramps_.${3} = *ramps;\ - return libgamma_internal_translated_ramp_get(this, &ramps_, ${4}, DEPTH, libgamma_crtc_get_gamma_ramps ## SUFFIX);\ - }\ - } while (0) - -$>if [ ! ${4} = 8 ]; then - __trans(8, 8); -$>fi -$>if [ ! ${4} = 16 ]; then - __trans(16, 16); -$>fi -$>if [ ! ${4} = 32 ]; then - __trans(32, 32); -$>fi -$>if [ ! ${4} = 64 ]; then - __trans(64, 64); -$>fi -$>if [ ! ${4} = -1 ]; then - __trans(-1, f); -$>fi -$>if [ ! ${4} = -2 ]; then - __trans(-2, d); -$>fi - -#undef __trans - - for (i = 0; i < rn; i++) ramps->red[i] = r_ramp[i]; - for (i = 0; i < gn; i++) ramps->green[i] = g_ramp[i]; - for (i = 0; i < bn; i++) ramps->blue[i] = b_ramp[i]; - - return 0; -} -$>} - - -/** - * Set the gamma ramps for a CRTC - * - * @param 1 The data type for the ramp stop elements - * @param 2 The `ramp*` pattern for the ramp structure and function to call. - * @param 3 Either of `bit8`, `bit16`, `bit32`, `bit64`, `float_single`, `float_double`; - * rather self-explanatory - * @param 4 The number of bits in the gamma depth, -1 for single precision float, - * (`float`) and -2 for double percition float (`double`) - * @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 - */ -$>libgamma_dummy_crtc_set_gamma_ramps () -$>{ -int -libgamma_dummy_crtc_set_gamma_${2}(libgamma_crtc_state_t *restrict this, libgamma_gamma_${2}_t ramps) -{ - libgamma_dummy_crtc_t *data = this->data; - gamma_ramps_any_t ramps_; - ${1} *r_ramp = data->gamma_red; - ${1} *g_ramp = data->gamma_green; - ${1} *b_ramp = data->gamma_blue; - size_t rn = data->info.red_gamma_size; - size_t gn = data->info.green_gamma_size; - size_t bn = data->info.blue_gamma_size; - size_t i; - -#ifdef DEBUG - /* Check gamma ramp sizes */ - if (libgamma_dummy_configurations.capabilities.identical_gamma_sizes) - if (ramps.red_size != ramps.green_size || ramps.red_size != ramps.blue_size) - return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; - if (ramps.red_size != rn || ramps.green_size != gn || ramps.blue_size != bn) - return LIBGAMMA_WRONG_GAMMA_RAMP_SIZE; -#endif - - if (!data->info.gamma_support) - return LIBGAMMA_GAMMA_RAMP_READ_FAILED; - -#define __trans(DEPTH, SUFFIX)\ - do {\ - if (data->info.gamma_depth == DEPTH) {\ - ramps_.${3} = ramps;\ - return libgamma_internal_translated_ramp_set(this, ramps_, ${4}, DEPTH, libgamma_crtc_set_gamma_ramps ## SUFFIX);\ - }\ - } while (0) - -$>if [ ! ${4} = 8 ]; then - __trans(8, 8); -$>fi -$>if [ ! ${4} = 16 ]; then - __trans(16, 16); -$>fi -$>if [ ! ${4} = 32 ]; then - __trans(32, 32); -$>fi -$>if [ ! ${4} = 64 ]; then - __trans(64, 64); -$>fi -$>if [ ! ${4} = -1 ]; then - __trans(-1, f); -$>fi -$>if [ ! ${4} = -2 ]; then - __trans(-2, d); -$>fi - -#undef __trans - - for (i = 0; i < rn; i++) r_ramp[i] = ramps.red[i]; - for (i = 0; i < gn; i++) g_ramp[i] = ramps.green[i]; - for (i = 0; i < bn; i++) b_ramp[i] = ramps.blue[i]; - - return 0; -} -$>} - - - -/** - * Get the current gamma ramps for a CRTC, 8-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 - */ -$>libgamma_dummy_crtc_get_gamma_ramps uint8_t ramps8 bits8 8 - - -/** - * Set the gamma ramps for a CRTC, 8-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 - */ -$>libgamma_dummy_crtc_set_gamma_ramps uint8_t ramps8 bits8 8 - - - -/** - * Get the current 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 - */ -$>libgamma_dummy_crtc_get_gamma_ramps uint16_t ramps16 bits16 16 - - -/** - * 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 - */ -$>libgamma_dummy_crtc_set_gamma_ramps uint16_t ramps16 bits16 16 - - - -/** - * Get the current gamma ramps for a CRTC, 32-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 - */ -$>libgamma_dummy_crtc_get_gamma_ramps uint32_t ramps32 bits32 32 - - -/** - * Set the gamma ramps for a CRTC, 32-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 - */ -$>libgamma_dummy_crtc_set_gamma_ramps uint32_t ramps32 bits32 32 - - - -/** - * Get the current gamma ramps for a CRTC, 64-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 - */ -$>libgamma_dummy_crtc_get_gamma_ramps uint64_t ramps64 bits64 64 - - -/** - * Set the gamma ramps for a CRTC, 64-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 - */ -$>libgamma_dummy_crtc_set_gamma_ramps uint64_t ramps64 bits64 64 - - - -/** - * Get the current gamma ramps for a CRTC, `float` 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 - */ -$>libgamma_dummy_crtc_get_gamma_ramps float rampsf float_single -1 - - -/** - * Set the gamma ramps for a CRTC, `float` 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 - */ -$>libgamma_dummy_crtc_set_gamma_ramps float rampsf float_single -1 - - - -/** - * Get the current gamma ramps for a CRTC, `double` 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 - */ -$>libgamma_dummy_crtc_get_gamma_ramps double rampsd float_double -2 - - -/** - * Set the gamma ramps for a CRTC, `double` 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 - */ -$>libgamma_dummy_crtc_set_gamma_ramps double rampsd float_double -2 diff --git a/gamma-linux-drm.c b/gamma-linux-drm.c deleted file mode 100644 index 25a5861..0000000 --- a/gamma-linux-drm.c +++ /dev/null @@ -1,902 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#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) -{ - /* Support for all information except gamma ramp support */ - this->crtc_information = LIBGAMMA_CRTC_INFO_MACRO_EDID - | LIBGAMMA_CRTC_INFO_MACRO_VIEWPORT - | LIBGAMMA_CRTC_INFO_MACRO_RAMP - | LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER - | LIBGAMMA_CRTC_INFO_ACTIVE - | LIBGAMMA_CRTC_INFO_MACRO_CONNECTOR; - /* DRM supports multiple partitions and CRTC:s but not sites */ - this->default_site_known = 1; - this->multiple_sites = 0; - this->multiple_partitions = 1; - this->multiple_crtcs = 1; - /* Partitions are graphics cards in DRM */ - this->partitions_are_graphics_cards = 1; - /* Linux does not have system restore capabilities */ - this->site_restore = 0; - this->partition_restore = 0; - this->crtc_restore = 0; - /* Gamma ramp sizes are identical but not fixed */ - this->identical_gamma_sizes = 1; - this->fixed_gamma_size = 0; - /* Gamma ramp depths are fixed */ - this->fixed_gamma_depth = 1; - /* DRM is a real non-faked adjustment method */ - this->real = 1; - this->fake = 0; - /* Gamma ramp adjustments are persistent */ - this->auto_restore = 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. Once 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) - return LIBGAMMA_NO_SUCH_SITE; - - /* Count the number of available graphics cards by - `stat`:ing their existence in an API filesystem */ - this->partitions_available = 0; - for (;;) { - /* Construct pathname of graphics card device */ - snprintf(pathname, sizeof(pathname) / sizeof(char), - DRM_DEV_NAME, DRM_DIR_NAME, (int)(this->partitions_available)); - /* `stat` the graphics card's existence */ - if (stat(pathname, &_attr)) - break; - /* Move on to next graphics card */ - 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; - errno = ENOTSUP; - return 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) -{ - gid_t supplemental_groups[NGROUPS_MAX]; - struct group *group; - struct stat attr; - int i, n; - - - /* Check which the device exists */ - if (errno == ENXIO || errno == ENODEV) - return LIBGAMMA_NO_SUCH_PARTITION; - - - /* If we did not get access permission, figure out why */ - - if (errno != EACCES) { - /* If we could not figure out what went - * wrong, just return the error we got */ - return LIBGAMMA_ERRNO_SET; - } - -#define __test(R, W) ((attr.st_mode & ((R) | (W))) == ((R) | (W))) - - /* Get permission requirement for the file */ - if (stat(pathname, &attr)) - return errno == EACCES ? LIBGAMMA_NO_SUCH_PARTITION : LIBGAMMA_ERRNO_SET; - - /* Test owner's, group's and others' permissions */ - 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; - - /* The group should be "video", but perhaps - it is "root" to restrict users */ - if (!attr.st_gid /* root group */ || __test(S_IRGRP, S_IWGRP)) - return LIBGAMMA_DEVICE_RESTRICTED; - - - /* Get the user's supplemental group membership list */ - n = getgroups(NGROUPS_MAX, supplemental_groups); - if (n < 0) - return LIBGAMMA_ERRNO_SET; - - /* Test whether any of the supplemental - group should be satisfactory */ - for (i = 0; i < n; i++) - if (supplemental_groups[i] == attr.st_gid) - break; - - /* If one of the supplemental groups should be satisfactory, - then we do not know anything more than that access failed */ - if (i != n) - return LIBGAMMA_DEVICE_ACCESS_FAILED; - - /* Otherwise, try to get the name of the group that is - required and report the missing group membership */ - { - static __thread char buf[1024]; /* My output of `sysconf(_SC_GETGR_R_SIZE_MAX)`. */ - struct group _grp; - - errno = getgrgid_r(attr.st_gid, &_grp, buf, sizeof(buf) / sizeof(char), &group); - if (errno == ERANGE) - { - /* The lenght of the group's name is absurdly long, degrade to thread-unsafe. */ - errno = 0; - group = getgrgid(attr.st_gid); - } - else if (errno) - return LIBGAMMA_ERRNO_SET; - } - - libgamma_group_gid = attr.st_gid; - libgamma_group_name = group ? group->gr_name : NULL; - return LIBGAMMA_DEVICE_REQUIRE_GROUP; -#undef __test -} - - -/** - * 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) - return LIBGAMMA_ERRNO_SET; - data->fd = -1; - data->res = NULL; - data->encoders = NULL; - data->connectors = 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) { - 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; - this->data = data; - 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; - - /* Release individual encoders */ - if (this->encoders) - for (i = 0, n = (size_t)(this->res->count_connectors); i < n; i++) - if (this->encoders[i]) - drmModeFreeEncoder(this->encoders[i]); - /* Release encoder array */ - free(this->encoders); - this->encoders = NULL; - - /* Release individual connectors */ - if (this->connectors) - for (i = 0, n = (size_t)(this->res->count_connectors); i < n; i++) - if (this->connectors[i]) - drmModeFreeConnector(this->connectors[i]); - /* Release connector array */ - 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) - 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; - errno = ENOTSUP; - return 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 = partition->data; - - if (crtc >= partition->crtcs_available) - return LIBGAMMA_NO_SUCH_CRTC; - this->data = (void*)(size_t)card->res->crtcs[crtc]; - 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; - errno = ENOTSUP; - return 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) { - /* Allocate connector and encoder arrays; we use `calloc` - so all non-loaded elements are `NULL` after an error */ - card->connectors = calloc(n, sizeof(drmModeConnector *)); - if (!card->connectors) - goto fail; - card->encoders = calloc(n, sizeof(drmModeEncoder *)); - if (!card->encoders) - goto fail; - /* Fill connector and encoder arrays */ - for (i = 0; i < n; i++) { - /* Get connector */ - card->connectors[i] = drmModeGetConnector(card->fd, card->res->connectors[i]); - if (!card->connectors[i]) - goto fail; - /* Get encoder if the connector is enabled. If it is disabled it - will not have an encoder, which is indicated by the encoder - ID being 0. In such case, leave the encoder to be `NULL`. */ - if (card->connectors[i]->encoder_id) { - card->encoders[i] = drmModeGetEncoder(card->fd, card->connectors[i]->encoder_id); - if (!card->encoders[i]) - goto fail; - } - } - } - /* No error has occurred yet */ - *error = 0; - /* Find connector */ - for (i = 0; i < n; i++) - if (card->encoders[i] && card->connectors[i] && card->encoders[i]->crtc_id == crtc_id) - return card->connectors[i]; - /* We did not find the connector */ - *error = LIBGAMMA_CONNECTOR_UNKNOWN; - return NULL; - -fail: - /* Report the error that got us here, release - resouces and exit with `NULL` for failure */ - *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; - /* Get CRTC information */ - errno = 0; - crtc_info = drmModeGetCrtc(card->fd, crtc_id); - out->gamma_size_error = crtc_info ? 0 : errno; - /* Get gamma ramp size */ - if (!out->gamma_size_error) { - /* Store gamma ramp size */ - out->red_gamma_size = out->green_gamma_size = out->blue_gamma_size = (size_t)crtc_info->gamma_size; - /* Sanity check gamma ramp size */ - out->gamma_size_error = crtc_info->gamma_size < 2 ? LIBGAMMA_SINGLETON_GAMMA_RAMP : 0; - /* Release CRTC information */ - 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 - - /* These may not have been included by <xf86drmMode.h>, - but they should be available. Becuase we define them - outself, it is best to test them last. */ -#ifndef DRM_MODE_CONNECTOR_VIRTUAL -# define DRM_MODE_CONNECTOR_VIRTUAL 15 -#endif -#ifndef DRM_MODE_CONNECTOR_DSI -# define DRM_MODE_CONNECTOR_DSI 16 -#endif - - /* Translate connector type from DRM to libgamma - and store connector basename */ - switch (connector->connector_type) { - __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; - libgamma_drm_card_data_t *restrict card; - uint32_t type; - size_t i, n, c; - - /* Get some information that does not require too much work */ - if (fields & (LIBGAMMA_CRTC_INFO_MACRO_ACTIVE | LIBGAMMA_CRTC_INFO_MACRO_CONNECTOR)) { - /* 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) { - if (fields & (LIBGAMMA_CRTC_INFO_MACRO_VIEWPORT | 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) { - card = crtc->partition->data; - type = connector->connector_type; - n = (size_t)card->res->count_connectors; - - /* Allocate memory for the name of the connector */ - out->connector_name = malloc((strlen(connector_name_base) + 12) * sizeof(char)); - if (!out->connector_name) - return (out->connector_name_error = errno); - - /* Get the number of connectors with the same type on the same graphics card */ - for (i = c = 0; i < n && card->connectors[i] != connector; i++) - if (card->connectors[i]->connector_type == type) - c++; - - /* Construct and store connect name that is unique to the graphics card */ - 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; - - /* Test all properies on the connector */ - for (prop_i = 0; prop_i < prop_n; prop_i++) { - /* Get output property */ - prop = drmModeGetProperty(card->fd, connector->props[prop_i]); - if (!prop) - continue; - /* Is this property the EDID? */ - if (!strcmp(prop->name, "EDID")) { - /* Get the property value */ - blob = drmModeGetPropertyBlob(card->fd, (uint32_t)connector->prop_values[prop_i]); - if (!blob) { - drmModeFreeProperty(prop); - return (out->edid_error = LIBGAMMA_PROPERTY_VALUE_QUERY_FAILED); - } - if (blob->data) { - /* Get and store the length of the EDID */ - out->edid_length = blob->length; - /* Allocate memory for a copy of the EDID that is under our memory control */ - out->edid = malloc(out->edid_length * sizeof(unsigned char)); - if (!out->edid) { - out->edid_error = errno; - } else { - /* Copy the EDID so we can free resources that got us here */ - memcpy(out->edid, blob->data, (size_t)out->edid_length * sizeof(char)); - } - /* Free the propriety value and the propery */ - drmModeFreePropertyBlob(blob); - drmModeFreeProperty(prop); - /* Were we successful? */ - return !out->edid; - } - /* Free the propriety value */ - drmModeFreePropertyBlob(blob); - } - /* Free the propriety */ - drmModeFreeProperty(prop); - } - /* If we get here, we did not find a EDID */ - 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, require_connector, free_edid, error; - drmModeConnector *restrict 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 & LIBGAMMA_CRTC_INFO_EDID); - - /* Figure out whether we require the connector to get all information we want */ - require_connector = fields & (LIBGAMMA_CRTC_INFO_MACRO_ACTIVE | LIBGAMMA_CRTC_INFO_MACRO_CONNECTOR); - - /* If we are not interested in the connector or monitor, jump */ - if (!require_connector) - goto cont; - /* Find connector. */ - connector = find_connector(crtc, &error); - if (!connector) { - /* Store reported error in affected fields */ - e |= this->width_mm_error = this->height_mm_error - = this->connector_type_error = 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; - } - - /* Read connector data and monitor data, excluding EDID */ - e |= read_connector_data(crtc, this, connector, fields); - - /* If we do not want any EDID information, jump */ - if (!(fields & LIBGAMMA_CRTC_INFO_MACRO_EDID)) - goto cont; - /* If there is not monitor that report error in EDID related fields */ - if (this->active_error || !this->active) { - e |= this->edid_error = this->gamma_error - = this->width_mm_edid_error = this->height_mm_edid_error - = LIBGAMMA_NOT_CONNECTED; - goto cont; - } - /* Get EDID */ - e |= get_edid(crtc, this, connector); - if (!this->edid) { - this->gamma_error = this->width_mm_edid_error = this->height_mm_edid_error = this->edid_error; - goto cont; - } - /* Parse EDID */ - if (fields & (LIBGAMMA_CRTC_INFO_MACRO_EDID ^ LIBGAMMA_CRTC_INFO_EDID)) - e |= libgamma_internal_parse_edid(this, fields); - -cont: - /* Get gamma ramp size */ - e |= (fields & LIBGAMMA_CRTC_INFO_GAMMA_SIZE) ? get_gamma_ramp_size(this, crtc) : 0; - /* Store gamma ramp depth */ - this->gamma_depth = 16; - /* DRM does not support quering gamma ramp support */ - 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 the current 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_ramps16(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps16_t *restrict ramps) -{ - libgamma_drm_card_data_t *restrict card = this->partition->data; - int r; -#ifdef DEBUG - /* Gamma ramp sizes are identical but not fixed */ - if (ramps->red_size != ramps->green_size || ramps->red_size != ramps->blue_size) - return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; -#endif - /* Read current gamma ramps */ - 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_ramps16(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps16_t ramps) -{ - libgamma_drm_card_data_t *restrict card = this->partition->data; - int r; -#ifdef DEBUG - /* Gamma ramp sizes are identical but not fixed */ - if (ramps.red_size != ramps.green_size || ramps.red_size != ramps.blue_size) - return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; -#endif - - /* Apply gamma ramps */ - r = drmModeCrtcSetGamma(card->fd, (uint32_t)(size_t)this->data, - (uint32_t)ramps.red_size, ramps.red, ramps.green, ramps.blue); - /* Check for errors */ - 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: - /* TODO: 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; -} diff --git a/gamma-quartz-cg.c b/gamma-quartz-cg.c deleted file mode 100644 index b0e3a29..0000000 --- a/gamma-quartz-cg.c +++ /dev/null @@ -1,359 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#ifndef HAVE_LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS -# error Compiling gamma-quartz-cg.c without HAVE_LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS -#endif - -#include "gamma-quartz-cg.h" - -#include "libgamma-error.h" - -#ifdef FAKE_LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS -# include "fake-quartz-cg.h" -#else -# include <ApplicationServices/ApplicationServices.h> -# include <CoreGraphics/CGDirectDisplay.h> -# define close_fake_quartz_cg() /* For compatibility with "fake-quartz-cg.h" */ -#endif - -#include <stdlib.h> -#include <errno.h> - - -/** - * Return the capabilities of the adjustment method - * - * @param this The data structure to fill with the method's capabilities - */ -void -libgamma_quartz_cg_method_capabilities(libgamma_method_capabilities_t* restrict this) -{ - /* Gamma ramps size and depth can be queried */ - this->crtc_information = LIBGAMMA_CRTC_INFO_GAMMA_SIZE | LIBGAMMA_CRTC_INFO_GAMMA_DEPTH; - /* Quartz/CoreGraphics does not support sites or partitions */ - this->default_site_known = 1; - this->multiple_sites = 0; - this->multiple_partitions = 0; - /* Quartz/CoreGraphics does support CRTC:s */ - this->multiple_crtcs = 1; - /* Partitions are not supported... */ - this->partitions_are_graphics_cards = 0; - /* CoreGraphics have support for system restore */ - this->site_restore = 1; - this->partition_restore = 1; - /* But not for individual CRTC:s */ - this->crtc_restore = 0; - /* Gamma ramp sizes are identifical but not fixed */ - this->identical_gamma_sizes = 1; - this->fixed_gamma_size = 0; - /* Gamma ramp depths are fixed */ - this->fixed_gamma_depth = 1; - /* Quartz/CoreGraphics is a real adjustment method that can be faked */ -#ifdef FAKE_LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS - /* It is considered real but fake if it is translated to X RandR */ - this->fake = 1; -# ifdef HAVE_LIBGAMMA_METHOD_X_RANDR - this->real = 1; -# else - this->real = 0; -# endif -#else - /* It is real and not fake if we are running on Mac OS X */ - this->fake = 0; - this->real = 1; -#endif - /* Gamma ramp adjustments are non-persistent */ - this->auto_restore = 1; -} - - -/** - * 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. Once 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_quartz_cg_site_initialise(libgamma_site_state_t *restrict this, char *restrict site) -{ - this->partitions_available = 1; - return site ? 0 : LIBGAMMA_NO_SUCH_SITE; -} - - -/** - * Release all resources held by a site state - * - * @param this The site state - */ -void -libgamma_quartz_cg_site_destroy(libgamma_site_state_t *restrict this) -{ - (void) this; - close_fake_quartz_cg(); -} - - -/** - * 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_quartz_cg_site_restore(libgamma_site_state_t *restrict this) -{ - (void) this; - CGDisplayRestoreColorSyncSettings(); - return 0; -} - - - -/** - * 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_quartz_cg_partition_initialise(libgamma_partition_state_t *restrict this, - libgamma_site_state_t *restrict site, size_t partition) -{ - CGDirectDisplayID *crtcs, *crtcs_old; - uint32_t cap = 4, n; - - (void) site; - - this->data = NULL; - - if (partition) - return LIBGAMMA_NO_SUCH_PARTITION; - - /* Allocate array of CRTC ID:s */ - crtcs = malloc((size_t)cap * sizeof(CGDirectDisplayID)); - if (!crtcs) - return LIBGAMMA_ERRNO_SET; - - /* It is not possible to ask CoreGraphics how many CRTC:s are - * available. We have to ask it to give us a ID:s of a number - * of CRTC:s and ask for more if we got as many as we asked for. */ - for (;;) { - /* Ask for CRTC ID:s */ - if (CGGetOnlineDisplayList(cap, crtcs, &n) != kCGErrorSuccess) - return free(crtcs), LIBGAMMA_LIST_CRTCS_FAILED; - /* If we did not get as many as we asked for then we have all */ - if (n < cap) - break; - /* Increase the number CRTC ID:s to ask for */ - if (cap > SIZE_MAX / 2) /* We could also test ~0, but it is still too many */ - return free(crtcs), LIBGAMMA_IMPOSSIBLE_AMOUNT; - cap <<= 1; - /* Grow the array of CRTC ID:s so that it can fit all we are asking for */ - crtcs = realloc(crtcs_old = crtcs, (size_t)cap * sizeof(CGDirectDisplayID)); - if (!crtcs) { - free(crtcs_old); - return LIBGAMMA_ERRNO_SET; - } - } - - /* Store CRTC ID:s and CRTC count */ - this->data = crtcs; - this->crtcs_available = (size_t)n; - return 0; -} - - -/** - * Release all resources held by a partition state - * - * @param this The partition state - */ -void -libgamma_quartz_cg_partition_destroy(libgamma_partition_state_t *restrict this) -{ - free(this->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_quartz_cg_partition_restore(libgamma_partition_state_t *restrict this) -{ - return libgamma_quartz_cg_site_restore(this->site); -} - - - -/** - * 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_quartz_cg_crtc_initialise(libgamma_crtc_state_t *restrict this, - libgamma_partition_state_t *restrict partition, size_t crtc) -{ - (void) this; - return crtc < partition->crtcs_available ? 0 : LIBGAMMA_NO_SUCH_CRTC; -} - - -/** - * Release all resources held by a CRTC state - * - * @param this The CRTC state - */ -void -libgamma_quartz_cg_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_quartz_cg_crtc_restore(libgamma_crtc_state_t *restrict this) -{ - (void) this; - errno = ENOTSUP; - return LIBGAMMA_ERRNO_SET; -} - - - -/** - * 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_quartz_cg_get_crtc_information(libgamma_crtc_information_t *restrict this, - libgamma_crtc_state_t *restrict crtc, int32_t fields) -{ -#define SUPPORTED_FIELDS (LIBGAMMA_CRTC_INFO_GAMMA_SIZE | LIBGAMMA_CRTC_INFO_GAMMA_DEPTH) -#define _E(FIELD) ((fields & FIELD) ? LIBGAMMA_CRTC_INFO_NOT_SUPPORTED : 0) - - CGDirectDisplayID *restrict crtcs; - size_t gamma_size; - - /* Quartz/CoreGraphics does not support EDID or monitor dimensions */ - this->edid_error = _E(LIBGAMMA_CRTC_INFO_EDID); - this->width_mm_error = _E(LIBGAMMA_CRTC_INFO_WIDTH_MM); - this->height_mm_error = _E(LIBGAMMA_CRTC_INFO_HEIGHT_MM); - this->width_mm_edid_error = _E(LIBGAMMA_CRTC_INFO_WIDTH_MM_EDID); - this->height_mm_edid_error = _E(LIBGAMMA_CRTC_INFO_HEIGHT_MM_EDID); - /* Quartz/CoreGraphics does support gamma ramp size query - The gamma ramps are identical but not fixed, and the query can fail */ - this->gamma_size_error = 0; - if ((fields & LIBGAMMA_CRTC_INFO_GAMMA_SIZE)) { - crtcs = crtc->partition->data; - gamma_size = CGDisplayGammaTableCapacity(crtcs[crtc->crtc]); - this->red_gamma_size = this->green_gamma_size = this->blue_gamma_size = (size_t)gamma_size; - this->gamma_size_error = gamma_size < 2 ? LIBGAMMA_SINGLETON_GAMMA_RAMP : 0; - } - /* Quartz/CoreGraphics uses `float` ramps */ - this->gamma_depth = -1; - this->gamma_depth_error = 0; - /* Quartz/CoreGraphics does not support gamma ramp support queries */ - this->gamma_support_error = _E(LIBGAMMA_CRTC_INFO_GAMMA_SUPPORT); - /* Quartz/CoreGraphics does not support EDID or connector information */ - this->subpixel_order_error = _E(LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER); - this->active_error = _E(LIBGAMMA_CRTC_INFO_ACTIVE); - this->connector_name_error = _E(LIBGAMMA_CRTC_INFO_CONNECTOR_NAME); - this->connector_type_error = _E(LIBGAMMA_CRTC_INFO_CONNECTOR_TYPE); - this->gamma_error = _E(LIBGAMMA_CRTC_INFO_GAMMA); - - /* We failed if gamma ramp size query failed or if an unsupport field was queried */ - return (this->gamma_size_error || (fields & ~SUPPORTED_FIELDS)) ? -1 : 0; - -#undef _E -#undef SUPPORTED_FIELDS -} - - -/** - * Get the current gamma ramps for a CRTC, `float` 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_quartz_cg_crtc_get_gamma_rampsf(libgamma_crtc_state_t *restrict this, libgamma_gamma_rampsf_t *restrict ramps) -{ - CGDirectDisplayID *restrict crtcs = this->partition->data; - CGDirectDisplayID crtc_id = crtcs[this->crtc]; - uint32_t gamma_size_out; - CGError r; -#ifdef DEBUG - /* Gamma ramps sizes are identical but not fixed */ - if (ramps->red_size != ramps->green_size || ramps->red_size != ramps->blue_size) - return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; -#endif - /* Read current gamma ramps */ - r = CGGetDisplayTransferByTable(crtc_id, (uint32_t)ramps->red_size, ramps->red, ramps->green, ramps->blue, &gamma_size_out); - if (r != kCGErrorSuccess) - return LIBGAMMA_GAMMA_RAMP_READ_FAILED; - /* I hope that it will not actually ever change, - but it does return the the gamma ramp size despite - that it can be queried without querying for more */ - if (gamma_size_out != ramps->red_size) - return LIBGAMMA_GAMMA_RAMP_SIZE_CHANGED; - return 0; -} - - -/** - * Set the gamma ramps for a CRTC, `float` 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_quartz_cg_crtc_set_gamma_rampsf(libgamma_crtc_state_t *restrict this, libgamma_gamma_rampsf_t ramps) -{ - CGDirectDisplayID *restrict crtcs = this->partition->data; - CGDirectDisplayID crtc_id = crtcs[this->crtc]; - CGError r; -#ifdef DEBUG - /* Gamma ramps sizes are identical but not fixed */ - if (ramps.red_size != ramps.green_size || ramps.red_size != ramps.blue_size) - return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; -#endif - /* Apply gamma ramps */ - r = CGSetDisplayTransferByTable(crtc_id, (uint32_t)ramps.red_size, ramps.red, ramps.green, ramps.blue); - return r == kCGErrorSuccess ? 0 : LIBGAMMA_GAMMA_RAMP_WRITE_FAILED; -} diff --git a/gamma-w32-gdi.c b/gamma-w32-gdi.c deleted file mode 100644 index e93b53d..0000000 --- a/gamma-w32-gdi.c +++ /dev/null @@ -1,360 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#ifndef HAVE_LIBGAMMA_METHOD_W32_GDI -# error Compiling gamma-w32-gdi.c without HAVE_LIBGAMMA_METHOD_W32_GDI -#endif - -#include "gamma-w32-gdi.h" - -#include "libgamma-error.h" - -#ifndef WINVER -# define WINVER 0x0500 -#endif -#ifdef FAKE_LIBGAMMA_METHOD_W32_GDI -# include "fake-w32-gdi.h" -#else -# include <windows.h> -# include <wingdi.h> -#endif - -#include <errno.h> - - -/** - * The gamma ramp size that devices will always have in Windows GDI - * - * @see http://msdn.microsoft.com/en-us/library/windows/desktop/dd372194(v=vs.85).aspx - */ -#define GAMMA_RAMP_SIZE 256 - - -/** - * Return the capabilities of the adjustment method - * - * @param this The data structure to fill with the method's capabilities - */ -void -libgamma_w32_gdi_method_capabilities(libgamma_method_capabilities_t *restrict this) -{ - /* Gamma ramps size, depth and support can be queried */ - this->crtc_information = LIBGAMMA_CRTC_INFO_GAMMA_SIZE | LIBGAMMA_CRTC_INFO_GAMMA_DEPTH; - /* Windows GDI does not support sites or partitions */ - this->default_site_known = 1; - this->multiple_sites = 0; - this->multiple_partitions = 0; - /* Windows GDI does support CRTC:s */ - this->multiple_crtcs = 1; - /* Partitions are not supported... */ - this->partitions_are_graphics_cards = 0; - /* Windows GDI does not have system restore capabilities */ - this->site_restore = 0; - this->partition_restore = 0; - this->crtc_restore = 0; - /* Ramps sizes are fixed and identical and ramp depth is too */ - this->identical_gamma_sizes = 1; - this->fixed_gamma_size = 1; - this->fixed_gamma_depth = 1; - /* Windows GDI is a real adjustment method that can be faked */ -#ifdef FAKE_LIBGAMMA_METHOD_W32_GDI - /* It is considered real but fake if it is translated to X RandR */ - this->fake = 1; -# ifdef HAVE_LIBGAMMA_METHOD_X_RANDR - this->real = 1; -# else - this->real = 0; -# endif -#else - /* It is real and not fake if we are running on Windows */ - this->fake = 0; - this->real = 1; -#endif - /* Gamma ramp adjustments are persistent */ - this->auto_restore = 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. Once 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_w32_gdi_site_initialise(libgamma_site_state_t *restrict this, char* restrict site) -{ - this->partitions_available = 1; - return !site ? 0 : LIBGAMMA_NO_SUCH_SITE; -} - - -/** - * Release all resources held by a site state - * - * @param this The site state - */ -void -libgamma_w32_gdi_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_w32_gdi_site_restore(libgamma_site_state_t *restrict this) -{ - (void) this; - errno = ENOTSUP; - 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_w32_gdi_partition_initialise(libgamma_partition_state_t *restrict this, - libgamma_site_state_t *restrict site, size_t partition) -{ - DWORD n = 0; - DISPLAY_DEVICE display; - - (void) site; - - if (partition) - return LIBGAMMA_NO_SUCH_PARTITION; - - /* Count CRTC:s by iteration over all possible identifiers - until we reach on that does not exist */ - display.cb = sizeof(DISPLAY_DEVICE); - while (EnumDisplayDevices(NULL, n, &display, 0)) - if (n++ == UINT32_MAX) - return LIBGAMMA_IMPOSSIBLE_AMOUNT; - this->crtcs_available = (size_t)n; - return 0; -} - - -/** - * Release all resources held by a partition state - * - * @param this The partition state - */ -void -libgamma_w32_gdi_partition_destroy(libgamma_partition_state_t *restrict this) -{ - (void) this; -} - - -/** - * 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_w32_gdi_partition_restore(libgamma_partition_state_t *restrict this) -{ - (void) this; - errno = ENOTSUP; - return 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_w32_gdi_crtc_initialise(libgamma_crtc_state_t *restrict this, - libgamma_partition_state_t *restrict partition, size_t crtc) -{ - DISPLAY_DEVICE display; - HDC context; - - (void) partition; - - this->data = NULL; - - /* Windows's API mandates this... */ - display.cb = sizeof(DISPLAY_DEVICE); - /* Get identifier for selected CRTC */ - if (!EnumDisplayDevices(NULL, (DWORD)crtc, &display, 0)) - return LIBGAMMA_NO_SUCH_CRTC; - /* Check that the connector is enabled, - * newer versions of Windows will always pass. - * (According to w32's documentation, but that - * that is a load of crap) */ - if (!(display.StateFlags & DISPLAY_DEVICE_ACTIVE)) - return LIBGAMMA_CONNECTOR_DISABLED; - /* Acquire CRTC connection. */ - context = CreateDC(TEXT("DISPLAY"), display.DeviceName, NULL, NULL); - if (!context) - return LIBGAMMA_OPEN_CRTC_FAILED; - this->data = context; - return 0; -} - - -/** - * Release all resources held by a CRTC state - * - * @param this The CRTC state - */ -void -libgamma_w32_gdi_crtc_destroy(libgamma_crtc_state_t *restrict this) -{ - if (this->data) - ReleaseDC(NULL, this->data); -} - - -/** - * 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_w32_gdi_crtc_restore(libgamma_crtc_state_t *restrict this) -{ - (void) this; - errno = ENOTSUP; - return LIBGAMMA_ERRNO_SET; -} - - - -/** - * 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_w32_gdi_get_crtc_information(libgamma_crtc_information_t *restrict this, - libgamma_crtc_state_t *restrict crtc, int32_t fields) -{ -#define KNOWN_FIELDS (LIBGAMMA_CRTC_INFO_GAMMA_SIZE | LIBGAMMA_CRTC_INFO_GAMMA_DEPTH) -#define _E(FIELD) ((fields & FIELD) ? LIBGAMMA_CRTC_INFO_NOT_SUPPORTED : 0) - - (void) crtc; - - /* Windows GDI does not support EDID or monitor dimensions */ - this->edid_error = _E(LIBGAMMA_CRTC_INFO_EDID); - this->width_mm_error = _E(LIBGAMMA_CRTC_INFO_WIDTH_MM); - this->height_mm_error = _E(LIBGAMMA_CRTC_INFO_HEIGHT_MM); - this->width_mm_edid_error = _E(LIBGAMMA_CRTC_INFO_WIDTH_MM_EDID); - this->height_mm_edid_error = _E(LIBGAMMA_CRTC_INFO_HEIGHT_MM_EDID); - /* Windows GDI have fixed gamma ramp sizes */ - this->red_gamma_size = GAMMA_RAMP_SIZE; - this->green_gamma_size = GAMMA_RAMP_SIZE; - this->blue_gamma_size = GAMMA_RAMP_SIZE; - this->gamma_size_error = 0; - /* Windows GDI have fixed gamma ramp depth */ - this->gamma_depth = 16; - this->gamma_depth_error = 0; - /* It is possible to query Windows GDI whether the device - have gamma ramp support. It cannot fail. However, I think - the result is incorrect if multiple monitors are active, - so we cannot include this. */ - /* - if ((fields & LIBGAMMA_CRTC_INFO_GAMMA_SUPPORT)) - this->gamma_support = GetDeviceCaps(crtc->data, COLORMGMTCAPS) == CM_GAMMA_RAMP; - this->gamma_support_error = 0; - */ - this->gamma_support_error = _E(LIBGAMMA_CRTC_INFO_GAMMA_SUPPORT); - /* Windows GDI does not support EDID or connector information */ - this->subpixel_order_error = _E(LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER); - this->active_error = _E(LIBGAMMA_CRTC_INFO_ACTIVE); - this->connector_name_error = _E(LIBGAMMA_CRTC_INFO_CONNECTOR_NAME); - this->connector_type_error = _E(LIBGAMMA_CRTC_INFO_CONNECTOR_TYPE); - this->gamma_error = _E(LIBGAMMA_CRTC_INFO_GAMMA); - - /* There was a failure if and only if unsupport field was requested. */ - return (fields & ~KNOWN_FIELDS) ? -1 : 0; - -#undef _E -#undef KNOWN_FIELDS -} - - -/** - * Get the current 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_w32_gdi_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps16_t *restrict ramps) -{ -#ifdef DEBUG - /* Windows GDI have fixed gamma ramp sizes */ - if (ramps-> red_size != GAMMA_RAMP_SIZE || - ramps->green_size != GAMMA_RAMP_SIZE || - ramps-> blue_size != GAMMA_RAMP_SIZE) - return LIBGAMMA_WRONG_GAMMA_RAMP_SIZE; -#endif - /* Read current gamma ramps */ - if (!GetDeviceGammaRamp(this->data, ramps->red)) - return LIBGAMMA_GAMMA_RAMP_READ_FAILED; - return 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_w32_gdi_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps16_t ramps) -{ -#ifdef DEBUG - /* Windows GDI have fixed gamma ramp sizes */ - if (ramps. red_size != GAMMA_RAMP_SIZE || - ramps.green_size != GAMMA_RAMP_SIZE || - ramps. blue_size != GAMMA_RAMP_SIZE) - return LIBGAMMA_WRONG_GAMMA_RAMP_SIZE; -#endif - /* Apply gamma ramps */ - if (!SetDeviceGammaRamp(this->data, ramps.red)) - return LIBGAMMA_GAMMA_RAMP_WRITE_FAILED; - return 0; -} diff --git a/gamma-x-randr.c b/gamma-x-randr.c deleted file mode 100644 index 95d730c..0000000 --- a/gamma-x-randr.c +++ /dev/null @@ -1,985 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#ifndef HAVE_LIBGAMMA_METHOD_X_RANDR -# error Compiling gamma-x-randr.c without HAVE_LIBGAMMA_METHOD_X_RANDR -#endif - -#include "gamma-x-randr.h" - -#include "libgamma-error.h" -#include "edid.h" - -#include <stdlib.h> -#include <errno.h> -#include <string.h> -#include <stdint.h> -#ifdef DEBUG -# include <stdio.h> -#endif - -#include <xcb/xcb.h> -#include <xcb/randr.h> - - -/** - * The major version of RandR the library expects - */ -#define RANDR_VERSION_MAJOR 1 - -/** - * The minor version of RandR the library expects - */ -#define RANDR_VERSION_MINOR 3 - - - -/** - * Data structure for partition data - */ -typedef struct libgamma_x_randr_partition_data { - /** - * Mapping from CRTC indices to CRTC identifiers - */ - xcb_randr_crtc_t *crtcs; - - /** - * Mapping from output indices to output identifiers - */ - xcb_randr_output_t *outputs; - - /** - * The number of outputs available - */ - size_t outputs_count; - - /** - * Mapping from CRTC indices to output indices. - * CRTC's without an output (should be impossible) - * have the value `SIZE_MAX` which is impossible - * for an existing mapping - */ - size_t *crtc_to_output; - - /** - * Screen configuration timestamp - */ - xcb_timestamp_t config_timestamp; - -} libgamma_x_randr_partition_data_t; - - - -/** - * Translate an xcb error into a libgamma error - * - * @param error_code The xcb error - * @param default_error The libgamma error to use if the xcb error is not recognised - * @return The libgamma error - */ -static int -translate_error_(int error_code, int default_error) -{ - switch (error_code) { - case XCB_CONN_ERROR: return errno = ECONNABORTED, LIBGAMMA_ERRNO_SET; - case XCB_CONN_CLOSED_EXT_NOTSUPPORTED: return errno = ENOPROTOOPT, LIBGAMMA_ERRNO_SET; - case XCB_CONN_CLOSED_MEM_INSUFFICIENT: return errno = ENOMEM, LIBGAMMA_ERRNO_SET; - case XCB_CONN_CLOSED_REQ_LEN_EXCEED: return errno = EMSGSIZE, LIBGAMMA_ERRNO_SET; - case XCB_CONN_CLOSED_PARSE_ERR: return LIBGAMMA_NO_SUCH_SITE; - case XCB_CONN_CLOSED_INVALID_SCREEN: return LIBGAMMA_NO_SUCH_PARTITION; - case XCB_CONN_CLOSED_FDPASSING_FAILED: return errno = EIO, LIBGAMMA_ERRNO_SET; - default: - return default_error; - } -} - - -/** - * Translate an xcb error into a libgamma error - * - * @param error_code The xcb error - * @param default_error The libgamma error to use if the xcb error is not recognised - * @param return_errno Whether an `errno` value may be returned - * @return The libgamma error - */ -static int -translate_error(int error_code, int default_error, int return_errno) -{ - int r = translate_error_(error_code, default_error); - return (return_errno && r > 0) ? errno : r; -} - - -/** - * Return the capabilities of the adjustment method - * - * @param this The data structure to fill with the method's capabilities - */ -void -libgamma_x_randr_method_capabilities(libgamma_method_capabilities_t *restrict this) -{ - char *display = getenv("DISPLAY"); - /* Support for all information except active status and gamma ramp support. - Active status can be queried but it is not guaranteed produces an up to date result. */ - this->crtc_information = LIBGAMMA_CRTC_INFO_MACRO_EDID - | LIBGAMMA_CRTC_INFO_MACRO_VIEWPORT - | LIBGAMMA_CRTC_INFO_MACRO_RAMP - | LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER - | LIBGAMMA_CRTC_INFO_MACRO_CONNECTOR; - /* X RandR supports multiple sites, partitions and CRTC:s */ - this->default_site_known = display && *display; - this->multiple_sites = 1; - this->multiple_partitions = 1; - this->multiple_crtcs = 1; - /* Partitions are screens and not graphics cards in X */ - this->partitions_are_graphics_cards = 0; - /* X does not have system restore capabilities */ - this->site_restore = 0; - this->partition_restore = 0; - this->crtc_restore = 0; - /* Gamma ramp sizes are identical but not fixed */ - this->identical_gamma_sizes = 1; - this->fixed_gamma_size = 0; - /* Gamma ramp depths are fixed */ - this->fixed_gamma_depth = 1; - /* X RandR is a real non-faked adjustment method */ - this->real = 1; - this->fake = 0; - /* Gamma ramp adjustments are persistent */ - this->auto_restore = 0; -} - - -/* xcb violates the rule to never return struct:s */ -#ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Waggregate-return" -#endif - - -/** - * 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. Once 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_x_randr_site_initialise(libgamma_site_state_t *restrict this, char *restrict site) -{ - xcb_generic_error_t *error = NULL; - xcb_connection_t *restrict connection; - xcb_randr_query_version_cookie_t cookie; - xcb_randr_query_version_reply_t *restrict reply; - const xcb_setup_t *restrict setup; - xcb_screen_iterator_t iter; - - /* Connect to the display server */ - this->data = connection = xcb_connect(site, NULL); - if (!connection || xcb_connection_has_error(connection)) - return LIBGAMMA_OPEN_SITE_FAILED; - - /* Query the version of the X RandR extension protocol */ - cookie = xcb_randr_query_version(connection, RANDR_VERSION_MAJOR, RANDR_VERSION_MINOR); - reply = xcb_randr_query_version_reply(connection, cookie, &error); - - /* Check for version query failure */ - if (error || !reply) { - /* Release resources */ - free(reply); - /* If `xcb_connect` failed, both `error` and `reply` will be `NULL`. - * TODO: Can both be `NULL` for any other reason? */ - if (!error && !reply) - return LIBGAMMA_OPEN_SITE_FAILED; - xcb_disconnect(connection); - /* Translate and report error. */ - if (error != NULL) - return translate_error(error->error_code, LIBGAMMA_PROTOCOL_VERSION_QUERY_FAILED, 0); - return LIBGAMMA_PROTOCOL_VERSION_QUERY_FAILED; - } - - /* Check protocol compatibility, - we require 1.3 but 2.x may not be backwards compatible */ - if (reply->major_version != RANDR_VERSION_MAJOR || reply->minor_version < RANDR_VERSION_MINOR) { -#ifdef DEBUG - /* Print used protocol */ - fprintf(stderr, "libgamma: RandR protocol version: %u.%u", reply->major_version, reply->minor_version); -#endif - /* Release resources */ - free(reply); - xcb_disconnect(connection); - /* Report error */ - return LIBGAMMA_PROTOCOL_VERSION_NOT_SUPPORTED; - } - - /* We do not longer need to know the version of the protocol */ - free(reply); - - /* Get available screens */ - setup = xcb_get_setup(connection); - if (!setup) { - xcb_disconnect(connection); - return LIBGAMMA_LIST_PARTITIONS_FAILED; - } - iter = xcb_setup_roots_iterator(setup); - /* Get the number of available screens */ - this->partitions_available = (size_t)iter.rem; - - /* Sanity check the number of available screens. */ - return iter.rem >= ? 0 : LIBGAMMA_NEGATIVE_PARTITION_COUNT; -} - - -/** - * Release all resources held by a site state - * - * @param this The site state - */ -void -libgamma_x_randr_site_destroy(libgamma_site_state_t *restrict this) -{ - xcb_disconnect((xcb_connection_t *)this->data); -} - - -/** - * 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_x_randr_site_restore(libgamma_site_state_t *restrict this) -{ - (void) this; - errno = ENOTSUP; - return LIBGAMMA_ERRNO_SET; -} - - -/** - * Duplicate a memory area - * - * @param ptr The memory area - * @param bytes The size, in bytes, of the memory area - * @return A duplication of the memory, `NULL` if zero-length or on error - */ -static inline void * -memdup(void *restrict ptr, size_t bytes) -{ - char *restrict rc; - if (!bytes) - return NULL; - rc = malloc(bytes); - if (!rc) - return NULL; - memcpy(rc, ptr, bytes); - return rc; -} - - -/** - * 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_x_randr_partition_initialise(libgamma_partition_state_t *restrict this, - libgamma_site_state_t *restrict site, size_t partition) -{ - int fail_rc = LIBGAMMA_ERRNO_SET; - xcb_connection_t *restrict connection = site->data; - xcb_screen_t *restrict screen = NULL; - xcb_generic_error_t *error = NULL; - const xcb_setup_t *restrict setup; - xcb_screen_iterator_t iter; - xcb_randr_get_screen_resources_current_cookie_t cookie; - xcb_randr_get_screen_resources_current_reply_t *restrict reply; - xcb_randr_crtc_t *restrict crtcs; - xcb_randr_output_t *restrict outputs; - libgamma_x_randr_partition_data_t *restrict data; - xcb_randr_get_output_info_cookie_t out_cookie; - xcb_randr_get_output_info_reply_t *out_reply; - size_t i; - uint16_t j; - - /* Get screen list */ - setup = xcb_get_setup(connection); - if (!setup) - return LIBGAMMA_LIST_PARTITIONS_FAILED; - iter = xcb_setup_roots_iterator(setup); - - /* Get the screen */ - for (i = 0; iter.rem > 0; i++, xcb_screen_next(&iter)) - if (i == partition) { - screen = iter.data; - break; - } - /* Report failure if we did not find the screen */ - if (!iter.rem) - return LIBGAMMA_NO_SUCH_PARTITION; - - /* Check that the screen is not `NULL`. - * (Do not think this can happen, but why not.) */ - if (!screen) - return LIBGAMMA_NULL_PARTITION; - - /* Get the current resources of the screen */ - cookie = xcb_randr_get_screen_resources_current(connection, screen->root); - reply = xcb_randr_get_screen_resources_current_reply(connection, cookie, &error); - if (error) - return translate_error(error->error_code, LIBGAMMA_LIST_CRTCS_FAILED, 0); - - /* Get the number of available CRTC:s */ - this->crtcs_available = reply->num_crtcs; - /* Get the CRTC and output lists */ - crtcs = xcb_randr_get_screen_resources_current_crtcs(reply); - outputs = xcb_randr_get_screen_resources_current_outputs(reply); - if (!crtcs || !outputs) { - free(reply); - return LIBGAMMA_REPLY_VALUE_EXTRACTION_FAILED; - } - - /* Allocate adjustment method dependent data memory area. - We use `calloc` because we want `data`'s pointers to be `NULL` if not allocated at `fail`. */ - data = calloc(1, sizeof(libgamma_x_randr_partition_data_t)); - if (!data) - goto fail; - - /* Copy the CRTC:s, just so we do not have to keep the reply in memory */ - data->crtcs = memdup(crtcs, (size_t)(reply->num_crtcs) * sizeof(xcb_randr_crtc_t)); - if (!data->crtcs && reply->num_crtcs > 0) - goto fail; - - /* Copy the outputs as well */ - data->outputs = memdup(outputs, (size_t)reply->num_outputs * sizeof(xcb_randr_output_t)); - if (!data->outputs && reply->num_outputs > 0) - goto fail; - - /* Get the number of available outputs */ - data->outputs_count = (size_t)reply->num_outputs; - - /* Create mapping table from CRTC indices to output indicies. (injection) */ - data->crtc_to_output = malloc((size_t)reply->num_crtcs * sizeof(size_t)); - if (!data->crtc) - goto fail; - /* All CRTC:s should be mapped, but incase they are not, all unmapped CRTC:s should have - an invalid target, namely `SIZE_MAX`, which is 1 more than the theoretical limit */ - for (i = 0; i < (size_t)reply->num_crtcs; i++) - data->crtc_to_output[i] = SIZE_MAX; - /* Fill the table */ - for (i = 0; i < (size_t)reply->num_outputs; i++) { - /* Query output (target) information */ - out_cookie = xcb_randr_get_output_info(connection, outputs[i], reply->config_timestamp); - out_reply = xcb_randr_get_output_info_reply(connection, out_cookie, &error); - if (error) { - fail_rc = translate_error(error->error_code, LIBGAMMA_OUTPUT_INFORMATION_QUERY_FAILED, 0); - goto fail; - } - - /* Find CRTC (source) */ - for (j = 0; j < reply->num_crtcs; j++) { - if (crtcs[j] == out_reply->crtc) { - data->crtc_to_output[j] = i; - break; - } - } - - /* Release output information */ - free(out_reply); - } - - /* Store the configuration timestamp */ - data->config_timestamp = reply->config_timestamp; - /* Store the adjustment method dependent data */ - this->data = data; - /* Release resources and return successfully */ - free(reply); - return 0; - -fail: - /* Release resources and return with an error */ - if (data) { - free(data->crtcs); - free(data->outputs); - free(data->crtc_to_output); - free(data); - } - free(reply); - return fail_rc; -} - - -/** - * Release all resources held by a partition state - * - * @param this The partition state - */ -void -libgamma_x_randr_partition_destroy(libgamma_partition_state_t *restrict this) -{ - libgamma_x_randr_partition_data_t *restrict data = this->data; - free(data->crtcs); - free(data->outputs); - free(data->crtc_to_output); - 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_x_randr_partition_restore(libgamma_partition_state_t *restrict this) -{ - (void) this; - errno = ENOTSUP; - return 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_x_randr_crtc_initialise(libgamma_crtc_state_t *restrict this, - libgamma_partition_state_t *restrict partition, size_t crtc) -{ - libgamma_x_randr_partition_data_t *restrict screen_data = partition->data; - xcb_randr_crtc_t *restrict crtc_ids = screen_data->crtcs; - this->data = crtc_ids + crtc; - return crtc < partition->crtcs_available ? 0 : LIBGAMMA_NO_SUCH_CRTC; -} - - -/** - * Release all resources held by a CRTC state - * - * @param this The CRTC state - */ -void -libgamma_x_randr_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_x_randr_crtc_restore(libgamma_crtc_state_t *restrict this) -{ - (void) this; - errno = ENOTSUP; - return LIBGAMMA_ERRNO_SET; -} - - - -/** - * Get the gamma ramp size of 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 Non-zero on error - */ -static int -get_gamma_ramp_size(libgamma_crtc_information_t *restrict out, libgamma_crtc_state_t *restrict crtc) -{ - xcb_connection_t *restrict connection = crtc->partition->site->data; - xcb_randr_crtc_t *restrict crtc_id = crtc->data; - xcb_randr_get_crtc_gamma_size_cookie_t cookie; - xcb_randr_get_crtc_gamma_size_reply_t *restrict reply; - xcb_generic_error_t *error; - - /* Query gamma ramp size */ - out->gamma_size_error = 0; - cookie = xcb_randr_get_crtc_gamma_size(connection, *crtc_id); - reply = xcb_randr_get_crtc_gamma_size_reply(connection, cookie, &error); - if (error) { - out->gamma_size_error = translate_error(error->error_code, LIBGAMMA_GAMMA_RAMPS_SIZE_QUERY_FAILED, 1); - return out->gamma_size_error; - } - /* Sanity check gamma ramp size */ - if (reply->size < 2) - out->gamma_size_error = LIBGAMMA_SINGLETON_GAMMA_RAMP; - /* Store gamma ramp size */ - out->red_gamma_size = out->green_gamma_size = out->blue_gamma_size = reply->size; - /* Release resources and return successfulnes */ - free(reply); - return out->gamma_size_error; -} - - -/** - * Read information from the CRTC's output - * - * @param out Instance of a data structure to fill with the information about the CRTC - * @param output The CRTC's output information - * @return Non-zero if at least on error occured - */ -static int -read_output_data(libgamma_crtc_information_t *restrict out, xcb_randr_get_output_info_reply_t *restrict output) -{ -#define __select(value)\ - case XCB_RENDER_SUB_PIXEL_##value: out->subpixel_order = LIBGAMMA_SUBPIXEL_ORDER_##value; break - - switch (output->connection) { - case XCB_RANDR_CONNECTION_CONNECTED: - /* We have a monitor connected, report that and store information that is provided to us */ - out->active = 1; - out->width_mm = output->mm_width; - out->height_mm = output->mm_height; - switch (output->subpixel_order) { - __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; - } - return 0; - - case XCB_RANDR_CONNECTION_UNKNOWN: - /* If we do know whether a monitor is connected report that and assume it is not */ - out->active_error = LIBGAMMA_STATE_UNKNOWN; - /* fall through */ - default: - /* If no monitor is connected, report that on fails that require it */ - out->width_mm_error = LIBGAMMA_NOT_CONNECTED; - out->height_mm_error = LIBGAMMA_NOT_CONNECTED; - out->subpixel_order_error = LIBGAMMA_NOT_CONNECTED; - /* And store that we are not connected */ - out->active = 0; - /* This fuction only failed if we could not figure out whether a monitor is connected */ - return output->connection != XCB_RANDR_CONNECTION_UNKNOWN ? 0 : -1; - } - -#undef __select -} - - -/** - * Determine the connector type from the connector name - * - * @param this The CRTC information to use and extend - * @param Non-zero on error - */ -static int -get_connector_type(libgamma_crtc_information_t *restrict this) -{ - /* Since we require the name of the output of get the type of the connected, - copy any reported error on the output's name to the connector's type, - and report failure if there was an error */ - if ((this->connector_type_error = this->connector_name_error)) - return -1; - -#define __select(name, type)\ - do {\ - if (strstr(this->connector_name, name "-") == this->connector_name) {\ - this->connector_type = LIBGAMMA_CONNECTOR_TYPE_##type\ - return 0;\ - }\ - } while (0) - - /* Check begin on the name of the output to find out what type the connector is of */ - __select ("None", Unknown); - __select ("VGA", VGA); - __select ("DVI-I", DVII); - __select ("DVI-D", DVID); - __select ("DVI-A", DVIA); - __select ("DVI", DVI); - __select ("Composite", Composite); - __select ("S-Video", SVIDEO); - __select ("Component", Component); - __select ("LFP", LFP); - __select ("Proprietary", Unknown); - __select ("HDMI", HDMI); - __select ("DisplayPort", DisplayPort); - -#undef __select - - /* If there was no matching output name pattern report that and exit with an error */ - this->connector_name_error = LIBGAMMA_CONNECTOR_TYPE_NOT_RECOGNISED; - return -1; -} - - -/** - * Get the output name of a CRTC - * - * @param this Instance of a data structure to fill with the information about the CRTC - * @param output The CRTC's output's information - * @return Non-zero on error - */ -static int -get_output_name(libgamma_crtc_information_t *restrict out, xcb_randr_get_output_info_reply_t *restrict output) -{ - char *restrict store; - uint8_t *restrict name; - uint16_t length; - size_t i; - - /* Get the name of the output and the length of that name */ - name = xcb_randr_get_output_info_name(output); - length = output->name_len; /* There is no NUL-termination */ - if (!name) - return out->connector_name_error = LIBGAMMA_REPLY_VALUE_EXTRACTION_FAILED; - - /* Allocate a memory area for a NUL-terminated copy of the name */ - store = out->connector_name = malloc(((size_t)length + 1) * sizeof(char)); - if (!store) { - out->connector_name_error = errno; - return -1; - } - - /* char is guaranteed to be (u)int_least8_t, but it is only guaranteed to be (u)int8_t - * on POSIX, so to be truly portable we will not assume that char is (u)int8_t */ - for (i = 0; i < (size_t)length; i++) - store[i] = (char)name[i]; - store[length] = '\0'; - - return 0; -} - - -/** - * Get the Extended Display Information Data of the monitor connected to the connector of 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 - * @param output The CRTC's output - * @return Non-zero on error - */ -static int -get_edid(libgamma_crtc_information_t *restrict out, libgamma_crtc_state_t *restrict crtc, xcb_randr_output_t output) -{ - xcb_connection_t *restrict connection = crtc->partition->site->data; - xcb_randr_list_output_properties_cookie_t prop_cookie; - xcb_randr_list_output_properties_reply_t *restrict prop_reply; - xcb_atom_t *atoms; - xcb_atom_t *atoms_end; - xcb_generic_error_t *error; - xcb_get_atom_name_cookie_t atom_name_cookie; - xcb_get_atom_name_reply_t *restrict atom_name_reply; - char *restrict atom_name; - int atom_name_len; - xcb_randr_get_output_property_cookie_t atom_cookie; - xcb_randr_get_output_property_reply_t *restrict atom_reply; - unsigned char* restrict atom_data; - int length; - - /* Acquire a list of all properties of the output */ - prop_cookie = xcb_randr_list_output_properties(connection, output); - prop_reply = xcb_randr_list_output_properties_reply(connection, prop_cookie, &error); - if (error) - return out->edid_error = translate_error(error->error_code, LIBGAMMA_LIST_PROPERTIES_FAILED, 1); - - /* Extract the properties form the data structure that holds them, */ - atoms = xcb_randr_list_output_properties_atoms(prop_reply); - /* and get the last one so that we can iterate over them nicely */ - atoms_end = atoms + xcb_randr_list_output_properties_atoms_length(prop_reply); - - if (!atoms) { - free(prop_reply); - return out->edid_error = LIBGAMMA_REPLY_VALUE_EXTRACTION_FAILED; - } - - /* For each property */ - for (; atoms != atoms_end; atoms++) { - /* Acquire the atom name */ - atom_name_cookie = xcb_get_atom_name(connection, *atoms); - atom_name_reply = xcb_get_atom_name_reply(connection, atom_name_cookie, &error); - if (error) - continue; - - /* Extract the atom name from the data structure that holds it */ - atom_name = xcb_get_atom_name_name(atom_name_reply); - /* As well as the length of the name; it is not NUL-termianted */ - atom_name_len = xcb_get_atom_name_name_length(atom_name_reply); - - if (/* Check for errors */ - !atom_name || /* atom_name_len < 1 || */ - /* Check that the length is the expected length for the EDID property */ - atom_name_len != 4 || - /* Check that the property is the EDID property */ - atom_name[0] != 'E' || atom_name[1] != 'D' || atom_name[2] != 'I' || atom_name[3] != 'D') { - free(atom_name_reply); - continue; - } - - /* Acquire the property's value, we know that it is either 128 or 256 byte long */ - atom_cookie = xcb_randr_get_output_property(connection, output, *atoms, XCB_GET_PROPERTY_TYPE_ANY, 0, 256, 0, 0); - atom_reply = xcb_randr_get_output_property_reply(connection, atom_cookie, &error); - /* (*) EDID version 1.0 through 1.4 define it as 128 bytes long, - * but version 2.0 define it as 256 bytes long. However, - * version 2.0 is rare(?) and has been deprecated and replaced - * by version 1.3 (I guess that is with a new version epoch, - * but I do not know.) */ - if (error) { - free(atom_name_reply); - free(prop_reply); - return out->edid_error = LIBGAMMA_PROPERTY_VALUE_QUERY_FAILED; - } - - /* Extract the property's value */ - atom_data = xcb_randr_get_output_property_data(atom_reply); - /* and its actual length */ - length = xcb_randr_get_output_property_data_length(atom_reply); - if (!atom_data || length < 1) { - free(atom_reply); - free(atom_name_reply); - free(prop_reply); - return out->edid_error = LIBGAMMA_REPLY_VALUE_EXTRACTION_FAILED; - } - - /* Store the EDID */ - out->edid_length = (size_t)length; - out->edid = malloc((size_t)length * sizeof(unsigned char)); - if (!out->edid) - out->edid_error = errno; - else - memcpy(out->edid, atom_data, (size_t)length * sizeof(unsigned char)); - - /* Release resouces */ - free(atom_reply); - free(atom_name_reply); - free(prop_reply); - - return out->edid_error; - } - - 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_x_randr_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; - xcb_randr_get_output_info_reply_t *restrict output_info = NULL; - xcb_randr_output_t output; - int free_edid, free_name; - xcb_connection_t *restrict connection; - libgamma_x_randr_partition_data_t *restrict screen_data; - size_t output_index; - xcb_randr_get_output_info_cookie_t cookie; - xcb_generic_error_t *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); - - /* We need to free the output's name after us if it is not explicitly requested */ - free_name = !(fields & LIBGAMMA_CRTC_INFO_CONNECTOR_NAME); - - /* Jump if the output information is not required */ - if (!(fields & (LIBGAMMA_CRTC_INFO_MACRO_ACTIVE | LIBGAMMA_CRTC_INFO_MACRO_CONNECTOR))) - goto cont; - - /* Get connector and connector information */ - connection = crtc->partition->site->data; - screen_data = crtc->partition->data; - output_index = screen_data->crtc_to_output[crtc->crtc]; - /* `SIZE_MAX` is used for CRTC:s that misses mapping to its output (should not happen), - * because `SIZE_MAX - 1` is the highest theoretical possible value */ - if (output_index == SIZE_MAX) { - e |= this->edid_error = this->gamma_error = this->width_mm_edid_error - = this->height_mm_edid_error = this->connector_type_error - = this->connector_name_error = this->subpixel_order_error - = this->width_mm_error = this->height_mm_error - = this->active_error = LIBGAMMA_CONNECTOR_UNKNOWN; - goto cont; - } - /* Get the output */ - output = screen_data->outputs[output_index]; - /* Query output information */ - cookie = xcb_randr_get_output_info(connection, output, screen_data->config_timestamp); - output_info = xcb_randr_get_output_info_reply(connection, cookie, &error); - if (error) { - e |= this->edid_error = this->gamma_error = this->width_mm_edid_error - = this->height_mm_edid_error = this->connector_type_error - = this->connector_name_error = this->subpixel_order_error - = this->width_mm_error = this->height_mm_error - = this->active_error = LIBGAMMA_OUTPUT_INFORMATION_QUERY_FAILED; - goto cont; - } - - /* Get connector name */ - e |= get_output_name(this, output_info); - /* Get connector type */ - if (fields & LIBGAMMA_CRTC_INFO_CONNECTOR_TYPE) - e |= get_connector_type(this); - /* Get additional output data, excluding EDID */ - e |= read_output_data(this, output_info); - if (fields & LIBGAMMA_CRTC_INFO_MACRO_VIEWPORT) - e |= this->width_mm_error | this->height_mm_error; - e |= (fields & LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER) ? this->subpixel_order_error : 0; - - /* If we do not want any EDID information, jump */ - if (!(fields & LIBGAMMA_CRTC_INFO_MACRO_EDID)) - goto cont; - /* If there is not monitor that report error in EDID related fields */ - if (!this->active) { - e |= this->edid_error = this->gamma_error = this->width_mm_edid_error - = this->height_mm_edid_error = LIBGAMMA_NOT_CONNECTED; - goto cont; - } - /* Get EDID */ - e |= get_edid(this, crtc, output); - if (!this->edid) { - this->gamma_error = this->width_mm_edid_error = this->height_mm_edid_error = this->edid_error; - goto cont; - } - /* Parse EDID */ - if ((fields & (LIBGAMMA_CRTC_INFO_MACRO_EDID ^ LIBGAMMA_CRTC_INFO_EDID))) - e |= libgamma_internal_parse_edid(this, fields); - -cont: - /* Get gamma ramp size */ - e |= (fields & LIBGAMMA_CRTC_INFO_GAMMA_SIZE) ? get_gamma_ramp_size(this, crtc) : 0; - /* Store gamma ramp depth. */ - this->gamma_depth = 16; - /* X RandR does not support quering gamma ramp support. */ - 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; - } - /* Free the output name after us */ - if (free_name) { - free(this->connector_name); - this->connector_name = NULL; - } - - free(output_info); - return e ? -1 : 0; - -#undef _E -} - - -/** - * Get the current 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_x_randr_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps16_t *restrict ramps) -{ - xcb_connection_t *restrict connection = this->partition->site->data; - xcb_randr_get_crtc_gamma_cookie_t cookie; - xcb_randr_get_crtc_gamma_reply_t *restrict reply; - xcb_generic_error_t *error; - uint16_t *restrict red; - uint16_t *restrict green; - uint16_t *restrict blue; - -#ifdef DEBUG - /* Gamma ramp sizes are identical but not fixed */ - if (ramps->red_size != ramps->green_size || ramps->red_size != ramps->blue_size) - return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; -#endif - - /* Read current gamma ramps */ - cookie = xcb_randr_get_crtc_gamma(connection, *(xcb_randr_crtc_t *)this->data); - reply = xcb_randr_get_crtc_gamma_reply(connection, cookie, &error); - - /* Check for errors */ - if (error) - return translate_error(error->error_code, LIBGAMMA_GAMMA_RAMP_READ_FAILED, 0); - - /* Get current gamma ramps from response */ - red = xcb_randr_get_crtc_gamma_red(reply); - green = xcb_randr_get_crtc_gamma_green(reply); - blue = xcb_randr_get_crtc_gamma_blue(reply); - /* Copy over the gamma ramps to our memory */ - memcpy(ramps->red, red, ramps->red_size * sizeof(uint16_t)); - memcpy(ramps->green, green, ramps->green_size * sizeof(uint16_t)); - memcpy(ramps->blue, blue, ramps->blue_size * sizeof(uint16_t)); - - free(reply); - return 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_x_randr_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps16_t ramps) -{ - xcb_connection_t *restrict connection = this->partition->site->data; - xcb_void_cookie_t cookie; - xcb_generic_error_t *restrict error; -#ifdef DEBUG - /* Gamma ramp sizes are identical but not fixed */ - if (ramps.red_size != ramps.green_size || ramps.red_size != ramps.blue_size) - return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; -#endif - - /* Apply gamma ramps */ - cookie = xcb_randr_set_crtc_gamma_checked(connection, *(xcb_randr_crtc_t*)this->data, - (uint16_t)ramps.red_size, ramps.red, ramps.green, ramps.blue); - /* Check for errors */ - error = xcb_request_check(connection, cookie); - if (error) - return translate_error(error->error_code, LIBGAMMA_GAMMA_RAMP_WRITE_FAILED, 0); - return 0; -} - - -#ifdef __GNUC__ -# pragma GCC diagnostic pop -#endif diff --git a/gamma-x-vidmode.c b/gamma-x-vidmode.c deleted file mode 100644 index bae9d31..0000000 --- a/gamma-x-vidmode.c +++ /dev/null @@ -1,312 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#ifndef HAVE_LIBGAMMA_METHOD_X_VIDMODE -# error Compiling gamma-x-vidmode.c without HAVE_LIBGAMMA_METHOD_X_VIDMODE -#endif - -#include "gamma-x-vidmode.h" - -#include "libgamma-error.h" - -#include <X11/Xlib.h> -#include <X11/extensions/xf86vmode.h> - -#include <stdlib.h> -#include <errno.h> - - -/** - * Return the capabilities of the adjustment method - * - * @param this The data structure to fill with the method's capabilities - */ -void -libgamma_x_vidmode_method_capabilities(libgamma_method_capabilities_t *restrict this) -{ - char *restrict display = getenv("DISPLAY"); - /* Gamma ramps size and depth can be queried */ - this->crtc_information = LIBGAMMA_CRTC_INFO_GAMMA_SIZE | LIBGAMMA_CRTC_INFO_GAMMA_DEPTH; - /* X VidMode supports multiple sites and partitions but not CRTC:s */ - this->default_site_known = (display && *display) ? 1 : 0; - this->multiple_sites = 1; - this->multiple_partitions = 1; - this->multiple_crtcs = 0; - /* Partitions are screens and not graphics cards in X */ - this->partitions_are_graphics_cards = 0; - /* X does not have system restore capabilities */ - this->site_restore = 0; - this->partition_restore = 0; - this->crtc_restore = 0; - /* Gamma ramp sizes are identical but not fixed */ - this->identical_gamma_sizes = 1; - this->fixed_gamma_size = 0; - /* Gamma ramp depths are fixed */ - this->fixed_gamma_depth = 1; - /* X VidMode is a real non-faked adjustment method */ - this->real = 1; - this->fake = 0; - /* Gamma ramp adjustments are persistent */ - this->auto_restore = 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. Once 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_x_vidmode_site_initialise(libgamma_site_state_t *restrict this, char *restrict site) -{ - /* Connect to the display */ - Display *restrict connection; - int _major, _minor, screens; - this->data = connection = XOpenDisplay(site); - if (!this->data) - return LIBGAMMA_OPEN_SITE_FAILED; - /* Query X VidMode extension protocol version */ - if (!XF86VidModeQueryVersion(connection, &_major, &_minor)) { - XCloseDisplay(connection); - return LIBGAMMA_PROTOCOL_VERSION_QUERY_FAILED; - } - /* Query the number of available screens */ - screens = ScreenCount(connection); - if (screens < 0) { - XCloseDisplay(connection); - return LIBGAMMA_NEGATIVE_PARTITION_COUNT; - } - this->partitions_available = (size_t)screens; - return 0; -} - - -/** - * Release all resources held by a site state - * - * @param this The site state - */ -void -libgamma_x_vidmode_site_destroy(libgamma_site_state_t *restrict this) -{ - XCloseDisplay((Display *)this->data); -} - - -/** - * 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_x_vidmode_site_restore(libgamma_site_state_t *restrict this) -{ - (void) this; - errno = ENOTSUP; - 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_x_vidmode_partition_initialise(libgamma_partition_state_t *restrict this, - libgamma_site_state_t *restrict site, size_t partition) -{ - this->crtcs_available = 1; - return partition < site->partitions_available ? 0 : LIBGAMMA_NO_SUCH_PARTITION; -} - - -/** - * Release all resources held by a partition state - * - * @param this The partition state - */ -void -libgamma_x_vidmode_partition_destroy(libgamma_partition_state_t *restrict this) -{ - (void) this; -} - - -/** - * 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_x_vidmode_partition_restore(libgamma_partition_state_t *restrict this) -{ - (void) this; - errno = ENOTSUP; - return 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_x_vidmode_crtc_initialise(libgamma_crtc_state_t *restrict this, - libgamma_partition_state_t *restrict partition, size_t crtc) -{ - (void) this; - (void) partition; - return !crtc ? 0 : LIBGAMMA_NO_SUCH_CRTC; -} - - -/** - * Release all resources held by a CRTC state - * - * @param this The CRTC state - */ -void -libgamma_x_vidmode_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_x_vidmode_crtc_restore(libgamma_crtc_state_t *restrict this) -{ - (void) this; - errno = ENOTSUP; - return LIBGAMMA_ERRNO_SET; -} - - - -/** - * 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; oOn error refer to the error reports in `this` - */ -int -libgamma_x_vidmode_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) - - Display *restrict connection; - int stops = 0; - - /* X VidMode does not support EDID or monitor dimensions */ - this->edid_error = _E(LIBGAMMA_CRTC_INFO_EDID); - this->width_mm_error = _E(LIBGAMMA_CRTC_INFO_WIDTH_MM); - this->height_mm_error = _E(LIBGAMMA_CRTC_INFO_HEIGHT_MM); - this->width_mm_edid_error = _E(LIBGAMMA_CRTC_INFO_WIDTH_MM_EDID); - this->height_mm_edid_error = _E(LIBGAMMA_CRTC_INFO_HEIGHT_MM_EDID); - this->gamma_size_error = 0; - /* X VidMode does support gamma ramp size query. The gamma - ramps are identical but not fixed, and the query can fail. */ - if ((fields & LIBGAMMA_CRTC_INFO_GAMMA_SIZE)) { - connection = crtc->partition->site->data; - if (!XF86VidModeGetGammaRampSize(connection, (int)crtc->partition->partition, &stops)) - this->gamma_size_error = LIBGAMMA_GAMMA_RAMPS_SIZE_QUERY_FAILED; - else if (stops < 2) - this->gamma_size_error = LIBGAMMA_SINGLETON_GAMMA_RAMP; - this->red_gamma_size = this->green_gamma_size = this->blue_gamma_size = (size_t)stops; - } - /* X VidMode uses 16-bit integer ramps */ - this->gamma_depth = 16; - this->gamma_depth_error = 0; - /* X VidMode does not support gamma ramp support queries */ - this->gamma_support_error = _E(LIBGAMMA_CRTC_INFO_GAMMA_SUPPORT); - /* X VidMode does not support EDID or connector information */ - this->subpixel_order_error = _E(LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER); - this->active_error = _E(LIBGAMMA_CRTC_INFO_ACTIVE); - this->connector_name_error = _E(LIBGAMMA_CRTC_INFO_CONNECTOR_NAME); - this->connector_type_error = _E(LIBGAMMA_CRTC_INFO_CONNECTOR_TYPE); - this->gamma_error = _E(LIBGAMMA_CRTC_INFO_GAMMA); - - /* We failed if gamma ramp size query failed or if an unsupport field was queried. */ - return (this->gamma_size_error || (fields & ~(LIBGAMMA_CRTC_INFO_GAMMA_DEPTH | LIBGAMMA_CRTC_INFO_GAMMA_SIZE))) ? -1 : 0; - -#undef _E -} - - -/** - * Get the current 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_x_vidmode_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps16_t *restrict ramps) -{ -#ifdef DEBUG - /* Gamma ramp sizes are identical but not fixed */ - if (ramps->red_size != ramps->green_size || ramps->red_size != ramps->blue_size) - return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; -#endif - /* Read current gamma ramps */ - if (!XF86VidModeGetGammaRamp((Display *)this->partition->site->data, (int)this->partition->partition, - (int)ramps->red_size, ramps->red, ramps->green, ramps->blue)) - return LIBGAMMA_GAMMA_RAMP_READ_FAILED; - return 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_x_vidmode_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps16_t ramps) -{ -#ifdef DEBUG - /* Gamma ramp sizes are identical but not fixed */ - if (ramps.red_size != ramps.green_size || ramps.red_size != ramps.blue_size) - return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; -#endif - /* Apply gamma ramps */ - if (!XF86VidModeSetGammaRamp((Display *)this->partition->site->data, (int)this->partition->partition, - (int)ramps.red_size, ramps.red, ramps.green, ramps.blue)) - return LIBGAMMA_GAMMA_RAMP_WRITE_FAILED; - return 0; -} diff --git a/get_ramps.h b/get_ramps.h index 8d4c011..5c51242 100644 --- a/get_ramps.h +++ b/get_ramps.h @@ -13,7 +13,7 @@ switch (this->partition->site->method) { #define X(CONST, CNAME, MDEPTH, MRAMPS)\ case CONST:\ if (!(MDEPTH)) {\ - return APPEND_RAMPS(libgamma_dummy_crtc_get_gamma_)(this, ramps);\ + return APPEND_RAMPS(libgamma_dummy_crtc_get_gamma_)(this, (void *)ramps);\ } else if ((DEPTH) == (MDEPTH)) {\ return libgamma_##CNAME##_crtc_get_gamma_##MRAMPS(this, (void *)ramps);\ } else {\ diff --git a/legacy.c b/legacy.c new file mode 100644 index 0000000..d4d1cf1 --- /dev/null +++ b/legacy.c @@ -0,0 +1,54 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + +#undef libgamma_crtc_set_gamma_ramps8 +#undef libgamma_crtc_set_gamma_ramps16 +#undef libgamma_crtc_set_gamma_ramps32 +#undef libgamma_crtc_set_gamma_ramps64 +#undef libgamma_crtc_set_gamma_rampsf +#undef libgamma_crtc_set_gamma_rampsd + + +int libgamma_crtc_set_gamma_ramps8(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps8_t); +int libgamma_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps16_t); +int libgamma_crtc_set_gamma_ramps32(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps32_t); +int libgamma_crtc_set_gamma_ramps64(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps64_t); +int libgamma_crtc_set_gamma_rampsf(libgamma_crtc_state_t *restrict, libgamma_gamma_rampsf_t); +int libgamma_crtc_set_gamma_rampsd(libgamma_crtc_state_t *restrict, libgamma_gamma_rampsd_t); + + +int +libgamma_crtc_set_gamma_ramps8(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps8_t ramps) +{ + return libgamma_crtc_set_gamma_ramps8__new(this, &ramps); +} + +int +libgamma_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps16_t ramps) +{ + return libgamma_crtc_set_gamma_ramps16__new(this, &ramps); +} + +int +libgamma_crtc_set_gamma_ramps32(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps32_t ramps) +{ + return libgamma_crtc_set_gamma_ramps32__new(this, &ramps); +} + +int +libgamma_crtc_set_gamma_ramps64(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps64_t ramps) +{ + return libgamma_crtc_set_gamma_ramps64__new(this, &ramps); +} + +int +libgamma_crtc_set_gamma_rampsf(libgamma_crtc_state_t *restrict this, libgamma_gamma_rampsf_t ramps) +{ + return libgamma_crtc_set_gamma_rampsf__new(this, &ramps); +} + +int +libgamma_crtc_set_gamma_rampsd(libgamma_crtc_state_t *restrict this, libgamma_gamma_rampsd_t ramps) +{ + return libgamma_crtc_set_gamma_rampsd__new(this, &ramps); +} @@ -8,7 +8,7 @@ #include <stdlib.h> -#ifndef __GNUC__ +#ifdef __GNUC__ # define LIBGAMMA_GCC_ONLY__(X) X #else # define LIBGAMMA_GCC_ONLY__(X) @@ -499,9 +499,30 @@ typedef enum libgamma_connector_type { /** * LFP connector * - * (What is this?) + * (TODO What is a LFP connector?) */ - LIBGAMMA_CONNECTOR_TYPE_LFP + LIBGAMMA_CONNECTOR_TYPE_LFP, + + /** + * DPI connector + * + * (TODO What is a DPI connector?) + */ + LIBGAMMA_CONNECTOR_TYPE_DPI, + + /** + * A writeback connector + * + * (TODO What is the difference between Virtual and Writeback?) + */ + LIBGAMMA_CONNECTOR_TYPE_WRITEBACK, + + /** + * SPI connector + * + * (TODO What is an SPI connector?) + */ + LIBGAMMA_CONNECTOR_TYPE_SPI /* DEVELOPERS: Remember to update LIBGAMMA_CONNECTOR_TYPE_COUNT below * and LIST_CONNECTOR_TYPES in common.h when adding methods */ @@ -512,7 +533,7 @@ typedef enum libgamma_connector_type { * The number of values defined in `libgamma_connector_type_t` * in the version of the library the program is compiled against */ -#define LIBGAMMA_CONNECTOR_TYPE_COUNT 20 +#define LIBGAMMA_CONNECTOR_TYPE_COUNT 23 /** * The number of values defined in `libgamma_connector_type_t` @@ -1518,6 +1539,7 @@ typedef double libgamma_gamma_rampsd_fun(double); * @param name The text to add at the beginning * @param error_code The error code, may be an `errno` value */ +LIBGAMMA_GCC_ONLY__(__attribute__((__access__(__read_only__, 1)))) void libgamma_perror(const char *, int); /** @@ -1546,7 +1568,7 @@ const char *libgamma_strerror(int); * description is returned and `errno` is set to `ERANGE`; * `errno` is otherwise unmodified */ -LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__))) +LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__, __access__(__write_only__, 2, 3)))) const char *libgamma_strerror_r(int, char[], size_t); /** @@ -1566,7 +1588,7 @@ const char *libgamma_name_of_error(int); * @return The error code, zero if the name is `NULL` * or does not refer to a `libgamma` error */ -LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__, __pure__))) +LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__, __access__(__read_only__, 1), __pure__))) int libgamma_value_of_error(const char *); /** @@ -1576,6 +1598,7 @@ int libgamma_value_of_error(const char *); * @return The group that the user needs to be a member of * if `LIBGAMMA_DEVICE_REQUIRE_GROUP` is returned */ +LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__))) #ifndef __WIN32__ gid_t libgamma_group_gid_get(void); #else @@ -1604,6 +1627,7 @@ void libgamma_group_gid_set(short); * if the name of the group `libgamma_group_gid` cannot * be determined */ +LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__))) const char *libgamma_group_name_get(void); /** @@ -1613,6 +1637,7 @@ const char *libgamma_group_name_get(void); * @param value The group that the user needs to be a member of if * `LIBGAMMA_DEVICE_REQUIRE_GROUP` is returned, may be `NULL` */ +LIBGAMMA_GCC_ONLY__(__attribute__((__access__(__read_only__, 1)))) void libgamma_group_name_set(const char *); @@ -1661,7 +1686,7 @@ int libgamma_is_method_available(int); * @return The adjustment method; for example `LIBGAMMA_METHOD_X_RANDR` * for "randr" and "LIBGAMMA_METHOD_X_RANDR" */ -LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__, __pure__))) +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__, __access__(__read_only__, 1), __pure__))) int libgamma_value_of_method(const char *); @@ -1670,9 +1695,10 @@ int libgamma_value_of_method(const char *); * Get the name of a connector type, * for example "VGA" for `LIBGAMMA_CONNECTOR_TYPE_VGA` * - * "Unknown" is returned for `LIBGAMMA_CONNECTOR_TYPE_Unknown`, - * "TV" is returned for `LIBGAMMA_CONNECTOR_TYPE_TV`, - * "Virtual" is returned for `LIBGAMMA_CONNECTOR_TYPE_Virtual` + * "Unknown" is returned for `LIBGAMMA_CONNECTOR_TYPE_Unknown`, + * "TV" is returned for `LIBGAMMA_CONNECTOR_TYPE_TV`, + * "Virtual" is returned for `LIBGAMMA_CONNECTOR_TYPE_VIRTUAL`, + * "Writeback" is returned for `LIBGAMMA_CONNECTOR_TYPE_WRITEBACK` * * @param connector The connector type * @return The name connector type, `NULL` if not @@ -1701,7 +1727,7 @@ const char *libgamma_const_of_connector_type(int); * @return The connector type; for example `LIBGAMMA_CONNECTOR_TYPE_VGA` * for "VGA" and "LIBGAMMA_CONNECTOR_TYPE_VGA" */ -LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__, __pure__))) +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__, __access__(__read_only__, 1), __pure__))) int libgamma_value_of_connector_type(const char *); @@ -1740,7 +1766,7 @@ const char *libgamma_const_of_subpixel_order(int); * @return The subpixel order; for example `LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_RGB` * for "Horizontal RGB" and "LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_RGB" */ -LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__, __pure__))) +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__, __access__(__read_only__, 1), __pure__))) int libgamma_value_of_subpixel_order(const char *); @@ -1973,7 +1999,7 @@ void libgamma_gamma_rampsd_free(libgamma_gamma_rampsd_t *restrict); * @return The number of element that have been stored in `methods`, or should * have been stored if the buffer was large enough */ -LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__))) +LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__, __access__(__write_only__, 1, 2)))) size_t libgamma_list_methods(int *restrict, size_t, int); /** @@ -1984,6 +2010,7 @@ size_t libgamma_list_methods(int *restrict, size_t, int); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__access__(__write_only__, 1)))) int libgamma_method_capabilities(libgamma_method_capabilities_t *restrict, int); /** @@ -2006,7 +2033,7 @@ const char *libgamma_method_default_site(int); * default site, `NULL` if there is none, that is, if * the method does not support multiple sites */ -LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__))) +LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__, __const__))) const char *libgamma_method_default_site_variable(int); @@ -2161,7 +2188,7 @@ int libgamma_crtc_restore(libgamma_crtc_state_t *restrict); * @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` */ -LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __access__(__write_only__, 1)))) int libgamma_get_crtc_information(libgamma_crtc_information_t *restrict, libgamma_crtc_state_t *restrict, int32_t); /** @@ -2178,6 +2205,7 @@ void libgamma_crtc_information_destroy(libgamma_crtc_information_t *restrict); * * @param this The CRTC information */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) inline void libgamma_crtc_information_free(libgamma_crtc_information_t *restrict this__) { @@ -2194,7 +2222,7 @@ libgamma_crtc_information_free(libgamma_crtc_information_t *restrict this__) * @return The EDID in lowercase hexadecimal representation * `NULL` on allocation error, `errno` will be set accordingly */ -LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__))) +LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__, __access__(__read_only__, 1, 2)))) char *libgamma_behex_edid_lowercase(const unsigned char *restrict, size_t); /** @@ -2205,7 +2233,7 @@ char *libgamma_behex_edid_lowercase(const unsigned char *restrict, size_t); * @return The EDID in uppercase hexadecimal representation, * NULL` on allocation error, `errno` will be set accordingly */ -LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__))) +LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__, __access__(__read_only__, 1, 2)))) char *libgamma_behex_edid_uppercase(const unsigned char *restrict, size_t); /** @@ -2216,7 +2244,7 @@ char *libgamma_behex_edid_uppercase(const unsigned char *restrict, size_t); * @return :char* The EDID in lowercase hexadecimal representation, * `NULL` on allocation error, `errno` will be set accordingly */ -LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__))) +LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__, __access__(__read_only__, 1, 2)))) inline char * libgamma_behex_edid(const unsigned char *restrict edid__, size_t length__) { @@ -2231,7 +2259,7 @@ libgamma_behex_edid(const unsigned char *restrict edid__, size_t length__) * of `edid` (the input value); `NULL` on allocation error or * if the EDID is malformated, `errno` will be set accordingly */ -LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__, __nonnull__))) +LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__, __nonnull__, __access__(__read_only__, 1)))) unsigned char *libgamma_unhex_edid(const char *restrict); @@ -2244,7 +2272,7 @@ unsigned char *libgamma_unhex_edid(const char *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __access__(__read_only__, 2)))) int libgamma_crtc_get_gamma_ramps8(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps8_t *restrict); /** @@ -2255,8 +2283,10 @@ int libgamma_crtc_get_gamma_ramps8(libgamma_crtc_state_t *restrict, libgamma_gam * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) -int libgamma_crtc_set_gamma_ramps8(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps8_t); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __access__(__read_only__, 2)))) +int libgamma_crtc_set_gamma_ramps8__new(libgamma_crtc_state_t *restrict, const libgamma_gamma_ramps8_t *restrict); +#define libgamma_crtc_set_gamma_ramps8 libgamma_crtc_set_gamma_ramps8__new + /** * Set the gamma ramps for a CRTC, 8-bit gamma-depth function version @@ -2283,7 +2313,7 @@ int libgamma_crtc_set_gamma_ramps8_f(libgamma_crtc_state_t *restrict, libgamma_g * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __hot__))) +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __hot__, __access__(__read_only__, 2)))) int libgamma_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps16_t *restrict); /** @@ -2294,8 +2324,9 @@ int libgamma_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict, libgamma_ga * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __hot__))) -int libgamma_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps16_t); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __hot__, __access__(__read_only__, 2)))) +int libgamma_crtc_set_gamma_ramps16__new(libgamma_crtc_state_t *restrict, const libgamma_gamma_ramps16_t *restrict); +#define libgamma_crtc_set_gamma_ramps16 libgamma_crtc_set_gamma_ramps16__new /** * Set the gamma ramps for a CRTC, 16-bit gamma-depth function version @@ -2322,7 +2353,7 @@ int libgamma_crtc_set_gamma_ramps16_f(libgamma_crtc_state_t *restrict, libgamma_ * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __access__(__read_only__, 2)))) int libgamma_crtc_get_gamma_ramps32(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps32_t *restrict); /** @@ -2333,8 +2364,9 @@ int libgamma_crtc_get_gamma_ramps32(libgamma_crtc_state_t *restrict, libgamma_ga * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) -int libgamma_crtc_set_gamma_ramps32(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps32_t); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __access__(__read_only__, 2)))) +int libgamma_crtc_set_gamma_ramps32__new(libgamma_crtc_state_t *restrict, const libgamma_gamma_ramps32_t *restrict); +#define libgamma_crtc_set_gamma_ramps32 libgamma_crtc_set_gamma_ramps32__new /** * Set the gamma ramps for a CRTC, 32-bit gamma-depth function version @@ -2361,7 +2393,7 @@ int libgamma_crtc_set_gamma_ramps32_f(libgamma_crtc_state_t *restrict, libgamma_ * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __access__(__read_only__, 2)))) int libgamma_crtc_get_gamma_ramps64(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps64_t *restrict); /** @@ -2372,8 +2404,9 @@ int libgamma_crtc_get_gamma_ramps64(libgamma_crtc_state_t *restrict, libgamma_ga * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) -int libgamma_crtc_set_gamma_ramps64(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps64_t); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __access__(__read_only__, 2)))) +int libgamma_crtc_set_gamma_ramps64__new(libgamma_crtc_state_t *restrict, const libgamma_gamma_ramps64_t *restrict); +#define libgamma_crtc_set_gamma_ramps64 libgamma_crtc_set_gamma_ramps64__new /** * Set the gamma ramps for a CRTC, 64-bit gamma-depth function version @@ -2393,26 +2426,27 @@ int libgamma_crtc_set_gamma_ramps64_f(libgamma_crtc_state_t *restrict, libgamma_ /** - * Set the gamma ramps for a CRTC, `float` version + * Get the current gamma ramps for a CRTC, `float` version * * @param this The CRTC state - * @param ramps The gamma ramps to apply + * @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 */ -LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) -int libgamma_crtc_set_gamma_rampsf(libgamma_crtc_state_t *restrict, libgamma_gamma_rampsf_t); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __access__(__read_only__, 2)))) +int libgamma_crtc_get_gamma_rampsf(libgamma_crtc_state_t *restrict, libgamma_gamma_rampsf_t *restrict); /** - * Get the current gamma ramps for a CRTC, `float` version + * Set the gamma ramps for a CRTC, `float` version * * @param this The CRTC state - * @param ramps The gamma ramps to fill with the current values + * @param ramps The gamma ramps to apply * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) -int libgamma_crtc_get_gamma_rampsf(libgamma_crtc_state_t *restrict, libgamma_gamma_rampsf_t *restrict); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __access__(__read_only__, 2)))) +int libgamma_crtc_set_gamma_rampsf__new(libgamma_crtc_state_t *restrict, const libgamma_gamma_rampsf_t *restrict); +#define libgamma_crtc_set_gamma_rampsf libgamma_crtc_set_gamma_rampsf__new /** * Set the gamma ramps for a CRTC, `float` function version @@ -2439,7 +2473,7 @@ int libgamma_crtc_set_gamma_rampsf_f(libgamma_crtc_state_t *restrict, libgamma_g * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __access__(__read_only__, 2)))) int libgamma_crtc_get_gamma_rampsd(libgamma_crtc_state_t *restrict, libgamma_gamma_rampsd_t *restrict); /** @@ -2450,7 +2484,9 @@ int libgamma_crtc_get_gamma_rampsd(libgamma_crtc_state_t *restrict, libgamma_gam * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -int libgamma_crtc_set_gamma_rampsd(libgamma_crtc_state_t *restrict, libgamma_gamma_rampsd_t); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __access__(__read_only__, 2)))) +int libgamma_crtc_set_gamma_rampsd__new(libgamma_crtc_state_t *restrict, const libgamma_gamma_rampsd_t *restrict); +#define libgamma_crtc_set_gamma_rampsd libgamma_crtc_set_gamma_rampsd__new /** * Set the gamma ramps for a CRTC, `double` function version @@ -2469,6 +2505,4 @@ int libgamma_crtc_set_gamma_rampsd_f(libgamma_crtc_state_t *restrict, libgamma_g libgamma_gamma_rampsd_fun *, libgamma_gamma_rampsd_fun *); - -#undef LIBGAMMA_GCC_ONLY__ #endif diff --git a/libgamma_connector_type_count.c b/libgamma_connector_type_count.c index 75934e1..dfd38ec 100644 --- a/libgamma_connector_type_count.c +++ b/libgamma_connector_type_count.c @@ -6,4 +6,4 @@ * The number of values defined in `libgamma_connector_type_t` * in the version of the library the program is linked against */ -extern const int libgamma_connector_type_count; +const int libgamma_connector_type_count = LIBGAMMA_CONNECTOR_TYPE_COUNT; diff --git a/libgamma_const_of_connector_type.c b/libgamma_const_of_connector_type.c index a006b88..5958953 100644 --- a/libgamma_const_of_connector_type.c +++ b/libgamma_const_of_connector_type.c @@ -15,8 +15,9 @@ const char * libgamma_const_of_connector_type(int connector) { switch (connector) { -#define X(CONST, NAME)\ - case CONST: return #CONST; +#define X(CONST, ...)\ + case CONST:\ + return #CONST; LIST_CONNECTOR_TYPES(X) #undef X default: diff --git a/libgamma_const_of_method.c b/libgamma_const_of_method.c index e6fd872..98ffd0e 100644 --- a/libgamma_const_of_method.c +++ b/libgamma_const_of_method.c @@ -14,8 +14,9 @@ const char * libgamma_const_of_method(int method) { switch (method) { -#define X(CONST, NAME, CNAME, ENABLED)\ - case CONST: return #CONST; +#define X(CONST, ...)\ + case CONST:\ + return #CONST; LIST_METHODS(X) #undef X default: diff --git a/libgamma_const_of_subpixel_order.c b/libgamma_const_of_subpixel_order.c index 7f69bea..b320e9d 100644 --- a/libgamma_const_of_subpixel_order.c +++ b/libgamma_const_of_subpixel_order.c @@ -15,8 +15,9 @@ const char * libgamma_const_of_subpixel_order(int order) { switch (order) { -#define X(CONST, NAME)\ - case CONST: return #CONST; +#define X(CONST, ...)\ + case CONST:\ + return #CONST; LIST_SUBPIXEL_ORDERS(X) #undef X default: diff --git a/libgamma_crtc_destroy.c b/libgamma_crtc_destroy.c index 9724e31..61cfe58 100644 --- a/libgamma_crtc_destroy.c +++ b/libgamma_crtc_destroy.c @@ -11,7 +11,7 @@ void libgamma_crtc_destroy(libgamma_crtc_state_t *restrict this) { switch (this->partition->site->method) { -#define X(CONST, CNAME, DEPTH, RAMPS)\ +#define X(CONST, CNAME, ...)\ case CONST:\ libgamma_##CNAME##_crtc_destroy(this);\ break; diff --git a/libgamma_crtc_get_gamma_ramps16.c b/libgamma_crtc_get_gamma_ramps16.c index 388f03f..cb4759b 100644 --- a/libgamma_crtc_get_gamma_ramps16.c +++ b/libgamma_crtc_get_gamma_ramps16.c @@ -14,7 +14,6 @@ int libgamma_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps16_t* restrict ramps) { #define DEPTH 16 -#define RAMPS ramps16 #define TYPE bits16 #define APPEND_RAMPS(X) X##ramps16 #include "get_ramps.h" diff --git a/libgamma_crtc_get_gamma_ramps32.c b/libgamma_crtc_get_gamma_ramps32.c index 32ce2ef..bd0658d 100644 --- a/libgamma_crtc_get_gamma_ramps32.c +++ b/libgamma_crtc_get_gamma_ramps32.c @@ -14,7 +14,6 @@ int libgamma_crtc_get_gamma_ramps32(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps32_t* restrict ramps) { #define DEPTH 32 -#define RAMPS ramps32 #define TYPE bits32 #define APPEND_RAMPS(X) X##ramps32 #include "get_ramps.h" diff --git a/libgamma_crtc_get_gamma_ramps64.c b/libgamma_crtc_get_gamma_ramps64.c index 3db19f9..f49b757 100644 --- a/libgamma_crtc_get_gamma_ramps64.c +++ b/libgamma_crtc_get_gamma_ramps64.c @@ -14,7 +14,6 @@ int libgamma_crtc_get_gamma_ramps64(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps64_t* restrict ramps) { #define DEPTH 64 -#define RAMPS ramps64 #define TYPE bits64 #define APPEND_RAMPS(X) X##ramps64 #include "get_ramps.h" diff --git a/libgamma_crtc_get_gamma_ramps8.c b/libgamma_crtc_get_gamma_ramps8.c index 9e359aa..598603a 100644 --- a/libgamma_crtc_get_gamma_ramps8.c +++ b/libgamma_crtc_get_gamma_ramps8.c @@ -14,7 +14,6 @@ int libgamma_crtc_get_gamma_ramps8(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps8_t* restrict ramps) { #define DEPTH 8 -#define RAMPS ramps8 #define TYPE bits8 #define APPEND_RAMPS(X) X##ramps8 #include "get_ramps.h" diff --git a/libgamma_crtc_get_gamma_rampsd.c b/libgamma_crtc_get_gamma_rampsd.c index e00e86c..ccee0c3 100644 --- a/libgamma_crtc_get_gamma_rampsd.c +++ b/libgamma_crtc_get_gamma_rampsd.c @@ -14,7 +14,6 @@ int libgamma_crtc_get_gamma_rampsd(libgamma_crtc_state_t *restrict this, libgamma_gamma_rampsd_t* restrict ramps) { #define DEPTH -2 -#define RAMPS rampsd #define TYPE float_double #define APPEND_RAMPS(X) X##rampsd #include "get_ramps.h" diff --git a/libgamma_crtc_get_gamma_rampsf.c b/libgamma_crtc_get_gamma_rampsf.c index ee233ca..2496e40 100644 --- a/libgamma_crtc_get_gamma_rampsf.c +++ b/libgamma_crtc_get_gamma_rampsf.c @@ -14,7 +14,6 @@ int libgamma_crtc_get_gamma_rampsf(libgamma_crtc_state_t *restrict this, libgamma_gamma_rampsf_t* restrict ramps) { #define DEPTH -1 -#define RAMPS rampsf #define TYPE float_single #define APPEND_RAMPS(X) X##rampsf #include "get_ramps.h" diff --git a/libgamma_crtc_initialise.c b/libgamma_crtc_initialise.c index 0d010b7..92d6960 100644 --- a/libgamma_crtc_initialise.c +++ b/libgamma_crtc_initialise.c @@ -18,7 +18,7 @@ libgamma_crtc_initialise(libgamma_crtc_state_t *restrict this, libgamma_partitio this->crtc = crtc; switch (partition->site->method) { -#define X(CONST, CNAME, DEPTH, RAMPS)\ +#define X(CONST, CNAME, ...)\ case CONST:\ return libgamma_##CNAME##_crtc_initialise(this, partition, crtc); LIST_AVAILABLE_METHODS(X) diff --git a/libgamma_crtc_restore.c b/libgamma_crtc_restore.c index d2a716f..d6a97c8 100644 --- a/libgamma_crtc_restore.c +++ b/libgamma_crtc_restore.c @@ -13,7 +13,7 @@ int libgamma_crtc_restore(libgamma_crtc_state_t *restrict this) { switch (this->partition->site->method) { -#define X(CONST, CNAME, DEPTH, RAMPS)\ +#define X(CONST, CNAME, ...)\ case CONST:\ return libgamma_##CNAME##_crtc_restore(this); LIST_AVAILABLE_METHODS(X) diff --git a/libgamma_crtc_set_gamma_ramps16.c b/libgamma_crtc_set_gamma_ramps16.c index 2ad0b03..9e4da01 100644 --- a/libgamma_crtc_set_gamma_ramps16.c +++ b/libgamma_crtc_set_gamma_ramps16.c @@ -11,10 +11,9 @@ * error identifier provided by this library */ int -libgamma_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps16_t ramps) +libgamma_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict this, const libgamma_gamma_ramps16_t *restrict ramps) { #define DEPTH 16 -#define RAMPS ramps16 #define TYPE bits16 #define APPEND_RAMPS(X) X##ramps16 #include "set_ramps.h" diff --git a/libgamma_crtc_set_gamma_ramps16_f.c b/libgamma_crtc_set_gamma_ramps16_f.c index 7b12530..dfb17e7 100644 --- a/libgamma_crtc_set_gamma_ramps16_f.c +++ b/libgamma_crtc_set_gamma_ramps16_f.c @@ -18,8 +18,7 @@ int libgamma_crtc_set_gamma_ramps16_f(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps16_fun *red_function, libgamma_gamma_ramps16_fun *green_function, libgamma_gamma_ramps16_fun *blue_function) { -#define TYPE uint16_t -#define RAMPS ramps16 +#define TYPE uint16_t #define APPEND_RAMPS(X) X##ramps16 #include "set_ramps_fun.h" } diff --git a/libgamma_crtc_set_gamma_ramps32.c b/libgamma_crtc_set_gamma_ramps32.c index f042c68..bc8235a 100644 --- a/libgamma_crtc_set_gamma_ramps32.c +++ b/libgamma_crtc_set_gamma_ramps32.c @@ -11,10 +11,9 @@ * error identifier provided by this library */ int -libgamma_crtc_set_gamma_ramps32(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps32_t ramps) +libgamma_crtc_set_gamma_ramps32(libgamma_crtc_state_t *restrict this, const libgamma_gamma_ramps32_t *restrict ramps) { #define DEPTH 32 -#define RAMPS ramps32 #define TYPE bits32 #define APPEND_RAMPS(X) X##ramps32 #include "set_ramps.h" diff --git a/libgamma_crtc_set_gamma_ramps32_f.c b/libgamma_crtc_set_gamma_ramps32_f.c index d0bfef1..ddd304a 100644 --- a/libgamma_crtc_set_gamma_ramps32_f.c +++ b/libgamma_crtc_set_gamma_ramps32_f.c @@ -18,8 +18,7 @@ int libgamma_crtc_set_gamma_ramps32_f(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps32_fun *red_function, libgamma_gamma_ramps32_fun *green_function, libgamma_gamma_ramps32_fun *blue_function) { -#define TYPE uint32_t -#define RAMPS ramps32 +#define TYPE uint32_t #define APPEND_RAMPS(X) X##ramps32 #include "set_ramps_fun.h" } diff --git a/libgamma_crtc_set_gamma_ramps64.c b/libgamma_crtc_set_gamma_ramps64.c index 4314738..a65ff72 100644 --- a/libgamma_crtc_set_gamma_ramps64.c +++ b/libgamma_crtc_set_gamma_ramps64.c @@ -11,10 +11,9 @@ * error identifier provided by this library */ int -libgamma_crtc_set_gamma_ramps64(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps64_t ramps) +libgamma_crtc_set_gamma_ramps64(libgamma_crtc_state_t *restrict this, const libgamma_gamma_ramps64_t *restrict ramps) { #define DEPTH 64 -#define RAMPS ramps64 #define TYPE bits64 #define APPEND_RAMPS(X) X##ramps64 #include "set_ramps.h" diff --git a/libgamma_crtc_set_gamma_ramps64_f.c b/libgamma_crtc_set_gamma_ramps64_f.c index 3a0417d..2d65e12 100644 --- a/libgamma_crtc_set_gamma_ramps64_f.c +++ b/libgamma_crtc_set_gamma_ramps64_f.c @@ -18,8 +18,7 @@ int libgamma_crtc_set_gamma_ramps64_f(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps64_fun *red_function, libgamma_gamma_ramps64_fun *green_function, libgamma_gamma_ramps64_fun *blue_function) { -#define TYPE uint64_t -#define RAMPS ramps64 +#define TYPE uint64_t #define APPEND_RAMPS(X) X##ramps64 #include "set_ramps_fun.h" } diff --git a/libgamma_crtc_set_gamma_ramps8.c b/libgamma_crtc_set_gamma_ramps8.c index b0f041b..a419455 100644 --- a/libgamma_crtc_set_gamma_ramps8.c +++ b/libgamma_crtc_set_gamma_ramps8.c @@ -11,10 +11,9 @@ * error identifier provided by this library */ int -libgamma_crtc_set_gamma_ramps8(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps8_t ramps) +libgamma_crtc_set_gamma_ramps8(libgamma_crtc_state_t *restrict this, const libgamma_gamma_ramps8_t *restrict ramps) { #define DEPTH 8 -#define RAMPS ramps8 #define TYPE bits8 #define APPEND_RAMPS(X) X##ramps8 #include "set_ramps.h" diff --git a/libgamma_crtc_set_gamma_ramps8_f.c b/libgamma_crtc_set_gamma_ramps8_f.c index f33d960..054a45c 100644 --- a/libgamma_crtc_set_gamma_ramps8_f.c +++ b/libgamma_crtc_set_gamma_ramps8_f.c @@ -18,8 +18,7 @@ int libgamma_crtc_set_gamma_ramps8_f(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps8_fun *red_function, libgamma_gamma_ramps8_fun *green_function, libgamma_gamma_ramps8_fun *blue_function) { -#define TYPE uint8_t -#define RAMPS ramps8 +#define TYPE uint8_t #define APPEND_RAMPS(X) X##ramps8 #include "set_ramps_fun.h" } diff --git a/libgamma_crtc_set_gamma_rampsd.c b/libgamma_crtc_set_gamma_rampsd.c index 7d02bdb..5ecc234 100644 --- a/libgamma_crtc_set_gamma_rampsd.c +++ b/libgamma_crtc_set_gamma_rampsd.c @@ -11,10 +11,9 @@ * error identifier provided by this library */ int -libgamma_crtc_set_gamma_rampsd(libgamma_crtc_state_t *restrict this, libgamma_gamma_rampsd_t ramps) +libgamma_crtc_set_gamma_rampsd(libgamma_crtc_state_t *restrict this, const libgamma_gamma_rampsd_t *restrict ramps) { #define DEPTH -2 -#define RAMPS rampsd #define TYPE float_double #define APPEND_RAMPS(X) X##rampsd #include "set_ramps.h" diff --git a/libgamma_crtc_set_gamma_rampsd_f.c b/libgamma_crtc_set_gamma_rampsd_f.c index 7154b60..e00da5f 100644 --- a/libgamma_crtc_set_gamma_rampsd_f.c +++ b/libgamma_crtc_set_gamma_rampsd_f.c @@ -18,8 +18,7 @@ int libgamma_crtc_set_gamma_rampsd_f(libgamma_crtc_state_t *restrict this, libgamma_gamma_rampsd_fun *red_function, libgamma_gamma_rampsd_fun *green_function, libgamma_gamma_rampsd_fun *blue_function) { -#define TYPE double -#define RAMPS rampsd +#define TYPE double #define APPEND_RAMPS(X) X##rampsd #include "set_ramps_fun.h" } diff --git a/libgamma_crtc_set_gamma_rampsf.c b/libgamma_crtc_set_gamma_rampsf.c index a31a007..15f4a39 100644 --- a/libgamma_crtc_set_gamma_rampsf.c +++ b/libgamma_crtc_set_gamma_rampsf.c @@ -11,10 +11,9 @@ * error identifier provided by this library */ int -libgamma_crtc_set_gamma_rampsf(libgamma_crtc_state_t *restrict this, libgamma_gamma_rampsf_t ramps) +libgamma_crtc_set_gamma_rampsf(libgamma_crtc_state_t *restrict this, const libgamma_gamma_rampsf_t *restrict ramps) { #define DEPTH -1 -#define RAMPS rampsf #define TYPE float_single #define APPEND_RAMPS(X) X##rampsf #include "set_ramps.h" diff --git a/libgamma_crtc_set_gamma_rampsf_f.c b/libgamma_crtc_set_gamma_rampsf_f.c index a5a639f..da4db21 100644 --- a/libgamma_crtc_set_gamma_rampsf_f.c +++ b/libgamma_crtc_set_gamma_rampsf_f.c @@ -18,8 +18,7 @@ int libgamma_crtc_set_gamma_rampsf_f(libgamma_crtc_state_t *restrict this, libgamma_gamma_rampsf_fun *red_function, libgamma_gamma_rampsf_fun *green_function, libgamma_gamma_rampsf_fun *blue_function) { -#define TYPE float -#define RAMPS rampsf +#define TYPE float #define APPEND_RAMPS(X) X##rampsf #include "set_ramps_fun.h" } diff --git a/libgamma_dummy_crtc_destroy.c b/libgamma_dummy_crtc_destroy.c new file mode 100644 index 0000000..7464dd4 --- /dev/null +++ b/libgamma_dummy_crtc_destroy.c @@ -0,0 +1,22 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Release all resources held by a CRTC state + * + * @param this The CRTC state + */ +void +libgamma_dummy_crtc_destroy(libgamma_crtc_state_t *restrict this) +{ + libgamma_dummy_crtc_t *data = this->data; + if (data) { + free(data->gamma_red); + data->gamma_red = NULL; + free(data->gamma_green); + data->gamma_green = NULL; + free(data->gamma_blue); + data->gamma_blue = NULL; + } +} diff --git a/libgamma_dummy_crtc_get_gamma_ramps16.c b/libgamma_dummy_crtc_get_gamma_ramps16.c new file mode 100644 index 0000000..7f81225 --- /dev/null +++ b/libgamma_dummy_crtc_get_gamma_ramps16.c @@ -0,0 +1,21 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Get the current 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_dummy_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps16_t *restrict ramps) +{ +#define LIBGAMMA_DUMMY_GET_RAMPS +#define TYPE uint16_t +#define FIELD bits16 +#define DEPTH 16 +#include "method-dummy.h" +} diff --git a/libgamma_dummy_crtc_get_gamma_ramps32.c b/libgamma_dummy_crtc_get_gamma_ramps32.c new file mode 100644 index 0000000..ba3dd92 --- /dev/null +++ b/libgamma_dummy_crtc_get_gamma_ramps32.c @@ -0,0 +1,21 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Get the current gamma ramps for a CRTC, 32-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_dummy_crtc_get_gamma_ramps32(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps32_t *restrict ramps) +{ +#define LIBGAMMA_DUMMY_GET_RAMPS +#define TYPE uint32_t +#define FIELD bits32 +#define DEPTH 32 +#include "method-dummy.h" +} diff --git a/libgamma_dummy_crtc_get_gamma_ramps64.c b/libgamma_dummy_crtc_get_gamma_ramps64.c new file mode 100644 index 0000000..9421b32 --- /dev/null +++ b/libgamma_dummy_crtc_get_gamma_ramps64.c @@ -0,0 +1,21 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Get the current gamma ramps for a CRTC, 64-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_dummy_crtc_get_gamma_ramps64(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps64_t *restrict ramps) +{ +#define LIBGAMMA_DUMMY_GET_RAMPS +#define TYPE uint64_t +#define FIELD bits64 +#define DEPTH 64 +#include "method-dummy.h" +} diff --git a/libgamma_dummy_crtc_get_gamma_ramps8.c b/libgamma_dummy_crtc_get_gamma_ramps8.c new file mode 100644 index 0000000..272c0f0 --- /dev/null +++ b/libgamma_dummy_crtc_get_gamma_ramps8.c @@ -0,0 +1,21 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Get the current gamma ramps for a CRTC, 8-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_dummy_crtc_get_gamma_ramps8(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps8_t *restrict ramps) +{ +#define LIBGAMMA_DUMMY_GET_RAMPS +#define TYPE uint8_t +#define FIELD bits8 +#define DEPTH 8 +#include "method-dummy.h" +} diff --git a/libgamma_dummy_crtc_get_gamma_rampsd.c b/libgamma_dummy_crtc_get_gamma_rampsd.c new file mode 100644 index 0000000..05d3e98 --- /dev/null +++ b/libgamma_dummy_crtc_get_gamma_rampsd.c @@ -0,0 +1,21 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Get the current gamma ramps for a CRTC, `double` 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_dummy_crtc_get_gamma_rampsd(libgamma_crtc_state_t *restrict this, libgamma_gamma_rampsd_t *restrict ramps) +{ +#define LIBGAMMA_DUMMY_GET_RAMPS +#define TYPE double +#define FIELD float_double +#define DEPTH -2 +#include "method-dummy.h" +} diff --git a/libgamma_dummy_crtc_get_gamma_rampsf.c b/libgamma_dummy_crtc_get_gamma_rampsf.c new file mode 100644 index 0000000..2d83235 --- /dev/null +++ b/libgamma_dummy_crtc_get_gamma_rampsf.c @@ -0,0 +1,21 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Get the current gamma ramps for a CRTC, `float` 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_dummy_crtc_get_gamma_rampsf(libgamma_crtc_state_t *restrict this, libgamma_gamma_rampsf_t *restrict ramps) +{ +#define LIBGAMMA_DUMMY_GET_RAMPS +#define TYPE float +#define FIELD float_single +#define DEPTH -1 +#include "method-dummy.h" +} diff --git a/libgamma_dummy_crtc_initialise.c b/libgamma_dummy_crtc_initialise.c new file mode 100644 index 0000000..1ae9161 --- /dev/null +++ b/libgamma_dummy_crtc_initialise.c @@ -0,0 +1,57 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_dummy_crtc_initialise(libgamma_crtc_state_t *restrict this, + libgamma_partition_state_t *restrict partition, size_t crtc) +{ + libgamma_dummy_partition_t *partition_data = partition->data; + libgamma_dummy_crtc_t *data = &partition_data->crtcs[crtc]; + size_t stop_size; + + this->data = NULL; + + if (crtc >= partition_data->crtc_count) + return LIBGAMMA_NO_SUCH_CRTC; + + this->data = data; + data->state = this; + + if (data->info.gamma_depth == -1) + stop_size = sizeof(float); + else if (data->info.gamma_depth == -2) + stop_size = sizeof(double); + else + stop_size = (size_t)data->info.gamma_depth / 8; + + data->gamma_red = malloc(data->info.red_gamma_size * stop_size); + if (!data->gamma_red) + goto fail; + data->gamma_green = malloc(data->info.green_gamma_size * stop_size); + if (!data->gamma_green) + goto fail; + data->gamma_blue = malloc(data->info.blue_gamma_size * stop_size); + if (!data->gamma_blue) + goto fail; + + return libgamma_dummy_internal_crtc_restore_forced(data); + +fail: + free(data->gamma_red); + data->gamma_red = NULL; + free(data->gamma_green); + data->gamma_green = NULL; + free(data->gamma_blue); + data->gamma_blue = NULL; + return LIBGAMMA_ERRNO_SET; +} diff --git a/libgamma_dummy_crtc_restore.c b/libgamma_dummy_crtc_restore.c new file mode 100644 index 0000000..10a5b56 --- /dev/null +++ b/libgamma_dummy_crtc_restore.c @@ -0,0 +1,20 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_dummy_crtc_restore(libgamma_crtc_state_t *restrict this) +{ + if (!libgamma_dummy_internal_configurations.capabilities.crtc_restore) { + errno = ENOTSUP; + return LIBGAMMA_ERRNO_SET; + } + return libgamma_dummy_internal_crtc_restore_forced(this->data); +} diff --git a/libgamma_dummy_crtc_set_gamma_ramps16.c b/libgamma_dummy_crtc_set_gamma_ramps16.c new file mode 100644 index 0000000..1239b3a --- /dev/null +++ b/libgamma_dummy_crtc_set_gamma_ramps16.c @@ -0,0 +1,21 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_dummy_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict this, const libgamma_gamma_ramps16_t *restrict ramps) +{ +#define LIBGAMMA_DUMMY_SET_RAMPS +#define TYPE uint16_t +#define FIELD bits16 +#define DEPTH 16 +#include "method-dummy.h" +} diff --git a/libgamma_dummy_crtc_set_gamma_ramps32.c b/libgamma_dummy_crtc_set_gamma_ramps32.c new file mode 100644 index 0000000..c84880e --- /dev/null +++ b/libgamma_dummy_crtc_set_gamma_ramps32.c @@ -0,0 +1,21 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Set the gamma ramps for a CRTC, 32-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_dummy_crtc_set_gamma_ramps32(libgamma_crtc_state_t *restrict this, const libgamma_gamma_ramps32_t *restrict ramps) +{ +#define LIBGAMMA_DUMMY_SET_RAMPS +#define TYPE uint32_t +#define FIELD bits32 +#define DEPTH 32 +#include "method-dummy.h" +} diff --git a/libgamma_dummy_crtc_set_gamma_ramps64.c b/libgamma_dummy_crtc_set_gamma_ramps64.c new file mode 100644 index 0000000..76c9f3b --- /dev/null +++ b/libgamma_dummy_crtc_set_gamma_ramps64.c @@ -0,0 +1,21 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Set the gamma ramps for a CRTC, 64-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_dummy_crtc_set_gamma_ramps64(libgamma_crtc_state_t *restrict this, const libgamma_gamma_ramps64_t *restrict ramps) +{ +#define LIBGAMMA_DUMMY_SET_RAMPS +#define TYPE uint64_t +#define FIELD bits64 +#define DEPTH 64 +#include "method-dummy.h" +} diff --git a/libgamma_dummy_crtc_set_gamma_ramps8.c b/libgamma_dummy_crtc_set_gamma_ramps8.c new file mode 100644 index 0000000..158bf50 --- /dev/null +++ b/libgamma_dummy_crtc_set_gamma_ramps8.c @@ -0,0 +1,21 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Set the gamma ramps for a CRTC, 8-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_dummy_crtc_set_gamma_ramps8(libgamma_crtc_state_t *restrict this, const libgamma_gamma_ramps8_t *restrict ramps) +{ +#define LIBGAMMA_DUMMY_SET_RAMPS +#define TYPE uint8_t +#define FIELD bits8 +#define DEPTH 8 +#include "method-dummy.h" +} diff --git a/libgamma_dummy_crtc_set_gamma_rampsd.c b/libgamma_dummy_crtc_set_gamma_rampsd.c new file mode 100644 index 0000000..1d67e70 --- /dev/null +++ b/libgamma_dummy_crtc_set_gamma_rampsd.c @@ -0,0 +1,21 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Set the gamma ramps for a CRTC, `double` 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_dummy_crtc_set_gamma_rampsd(libgamma_crtc_state_t *restrict this, const libgamma_gamma_rampsd_t *restrict ramps) +{ +#define LIBGAMMA_DUMMY_SET_RAMPS +#define TYPE double +#define FIELD float_double +#define DEPTH -2 +#include "method-dummy.h" +} diff --git a/libgamma_dummy_crtc_set_gamma_rampsf.c b/libgamma_dummy_crtc_set_gamma_rampsf.c new file mode 100644 index 0000000..e68b37d --- /dev/null +++ b/libgamma_dummy_crtc_set_gamma_rampsf.c @@ -0,0 +1,21 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Set the gamma ramps for a CRTC, `float` 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_dummy_crtc_set_gamma_rampsf(libgamma_crtc_state_t *restrict this, const libgamma_gamma_rampsf_t *restrict ramps) +{ +#define LIBGAMMA_DUMMY_SET_RAMPS +#define TYPE float +#define FIELD float_single +#define DEPTH -1 +#include "method-dummy.h" +} diff --git a/libgamma_dummy_get_crtc_information.c b/libgamma_dummy_get_crtc_information.c new file mode 100644 index 0000000..188afc9 --- /dev/null +++ b/libgamma_dummy_get_crtc_information.c @@ -0,0 +1,69 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_dummy_get_crtc_information(libgamma_crtc_information_t *restrict this, + libgamma_crtc_state_t *restrict crtc, int32_t fields) +{ + libgamma_dummy_crtc_t *restrict data = crtc->data; + int supported = libgamma_dummy_internal_configurations.capabilities.crtc_information; + int e = 0; + size_t n; + + /* Copy over information */ + *this = data->info; + + /* Duplicate strings */ + if (this->edid) { + this->edid = malloc(this->edid_length * sizeof(char)); + if (!this->edid) + this->edid_error = errno; + memcpy(this->edid, data->info.edid, this->edid_length * sizeof(char)); + } + if (this->connector_name) { + n = strlen(this->connector_name); + this->connector_name = malloc((n + 1) * sizeof(char)); + if (!this->connector_name) + this->connector_name_error = errno; + memcpy(this->connector_name, data->info.connector_name, (n + 1) * sizeof(char)); + } + + /* Parse EDID */ + if (this->edid_error) + this->width_mm_edid_error = this->height_mm_edid_error = this->gamma_error = this->edid_error; + else if (fields & (LIBGAMMA_CRTC_INFO_MACRO_EDID ^ LIBGAMMA_CRTC_INFO_EDID)) + e |= libgamma_internal_parse_edid(this, fields); + + /* Test errors */ +#define _E(FIELD, VAR)\ + ((fields & FIELD) ? ((supported & FIELD) ? VAR : (VAR = LIBGAMMA_CRTC_INFO_NOT_SUPPORTED)) : 0) + e |= _E(LIBGAMMA_CRTC_INFO_EDID, this->edid_error); + e |= _E(LIBGAMMA_CRTC_INFO_WIDTH_MM, this->width_mm_error); + e |= _E(LIBGAMMA_CRTC_INFO_HEIGHT_MM, this->height_mm_error); + e |= _E(LIBGAMMA_CRTC_INFO_GAMMA_SIZE, this->gamma_size_error); + e |= _E(LIBGAMMA_CRTC_INFO_GAMMA_DEPTH, this->gamma_depth_error); + e |= _E(LIBGAMMA_CRTC_INFO_GAMMA_SUPPORT, this->gamma_support_error); + e |= _E(LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER, this->subpixel_order_error); + e |= _E(LIBGAMMA_CRTC_INFO_ACTIVE, this->active_error); + e |= _E(LIBGAMMA_CRTC_INFO_CONNECTOR_NAME, this->connector_name_error); + e |= _E(LIBGAMMA_CRTC_INFO_CONNECTOR_TYPE, this->connector_type_error); + + if ((fields & LIBGAMMA_CRTC_INFO_WIDTH_MM_EDID) && !(supported & LIBGAMMA_CRTC_INFO_WIDTH_MM_EDID)) + e |= this->width_mm_edid_error = LIBGAMMA_CRTC_INFO_NOT_SUPPORTED; + if ((fields & LIBGAMMA_CRTC_INFO_HEIGHT_MM_EDID) && !(supported & LIBGAMMA_CRTC_INFO_HEIGHT_MM_EDID)) + e |= this->height_mm_edid_error = LIBGAMMA_CRTC_INFO_NOT_SUPPORTED; + if ((fields & LIBGAMMA_CRTC_INFO_GAMMA) && !(supported & LIBGAMMA_CRTC_INFO_GAMMA)) + e |= this->gamma_error = LIBGAMMA_CRTC_INFO_NOT_SUPPORTED; +#undef _E + + return e ? -1 : 0; +} diff --git a/libgamma_dummy_internal_configurations.c b/libgamma_dummy_internal_configurations.c new file mode 100644 index 0000000..a5ee4a2 --- /dev/null +++ b/libgamma_dummy_internal_configurations.c @@ -0,0 +1,59 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Configurations for the dummy adjustment method + */ +libgamma_dummy_configurations_t libgamma_dummy_internal_configurations = { + .capabilities = { + .crtc_information = (1 << LIBGAMMA_CRTC_INFO_COUNT) - 1, + .default_site_known = 1, + .multiple_sites = 1, + .multiple_partitions = 1, + .multiple_crtcs = 1, + .partitions_are_graphics_cards = 1, + .site_restore = 1, + .partition_restore = 1, + .crtc_restore = 1, + .identical_gamma_sizes = 0, + .fixed_gamma_size = 0, + .fixed_gamma_depth = 0 + }, + .crtc_info_template = { + .edid = NULL, + .edid_length = 0, + .edid_error = LIBGAMMA_EDID_NOT_FOUND, + .width_mm = 400, + .width_mm_error = 0, + .height_mm = 300, + .height_mm_error = 0, + .red_gamma_size = 1024, + .green_gamma_size = 2048, + .blue_gamma_size = 512, + .gamma_size_error = 0, + .gamma_depth = 64, + .gamma_depth_error = 0, + .gamma_support = 1, + .gamma_support_error = 0, + .subpixel_order = LIBGAMMA_SUBPIXEL_ORDER_HORIZONTAL_RGB, + .subpixel_order_error = 0, + .active = 1, + .active_error = 0, + .connector_name = NULL, + .connector_name_error = LIBGAMMA_CONNECTOR_TYPE_NOT_RECOGNISED, + .connector_type = LIBGAMMA_CONNECTOR_TYPE_Unknown, + .connector_type_error = 0 + }, + .real_method = LIBGAMMA_METHOD_DUMMY, + .site_count = 2, + .default_partition_count = 2, + .default_crtc_count = 2, + .inherit_sites = 1, + .inherit_partition_count = 1, + .inherit_crtc_count = 1, + .stall_for_partition_count = 0, + .stall_for_crtc_count = 0, + .stalled_start = 1, + .verbose = 0 +}; diff --git a/libgamma_dummy_internal_crtc_restore_forced.c b/libgamma_dummy_internal_crtc_restore_forced.c new file mode 100644 index 0000000..c05f9bf --- /dev/null +++ b/libgamma_dummy_internal_crtc_restore_forced.c @@ -0,0 +1,44 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Restore the gamma ramps for a CRTC to the system settings for that CRTC + * and ignore the method's capabilities + * + * @param this The CRTC data + * @return Zero on success, otherwise (negative) the value of an + * error identifier provided by this library + */ +int +libgamma_dummy_internal_crtc_restore_forced(libgamma_dummy_crtc_t *restrict data) +{ + size_t rn = data->info. red_gamma_size; + size_t gn = data->info.green_gamma_size; + size_t bn = data->info. blue_gamma_size; + size_t i; + + if (!data->gamma_red) + return 0; + +#define __reset_ramps(TYPE, MAX)\ + do {\ + TYPE *red = data->gamma_red;\ + TYPE *green = data->gamma_green;\ + TYPE *blue = data->gamma_blue;\ + for (i = 0; i < rn; i++) red [i] = (TYPE)((double)(MAX) * ((double)i / (double)(rn - 1)));\ + for (i = 0; i < gn; i++) green[i] = (TYPE)((double)(MAX) * ((double)i / (double)(gn - 1)));\ + for (i = 0; i < bn; i++) blue [i] = (TYPE)((double)(MAX) * ((double)i / (double)(bn - 1)));\ + } while (0) + + if (data->info.gamma_depth == 8) __reset_ramps(uint8_t, INT8_MAX); + else if (data->info.gamma_depth == 16) __reset_ramps(uint16_t, INT16_MAX); + else if (data->info.gamma_depth == 32) __reset_ramps(uint32_t, INT32_MAX); + else if (data->info.gamma_depth == 64) __reset_ramps(uint64_t, INT64_MAX); + else if (data->info.gamma_depth == -1) __reset_ramps(float, 1); + else __reset_ramps(double, 1); + +#undef __reset_ramps + + return 0; +} diff --git a/libgamma_dummy_method_capabilities.c b/libgamma_dummy_method_capabilities.c new file mode 100644 index 0000000..a59dbc8 --- /dev/null +++ b/libgamma_dummy_method_capabilities.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Return the capabilities of the adjustment method + * + * @param this The data structure to fill with the method's capabilities + */ +void +libgamma_dummy_method_capabilities(libgamma_method_capabilities_t *restrict this) +{ + int real_method = libgamma_dummy_internal_configurations.real_method; + *this = libgamma_dummy_internal_configurations.capabilities; + this->real = real_method != LIBGAMMA_METHOD_DUMMY; + this->fake = this->real; + this->auto_restore = real_method == LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS; +} diff --git a/libgamma_dummy_partition_destroy.c b/libgamma_dummy_partition_destroy.c new file mode 100644 index 0000000..279cc61 --- /dev/null +++ b/libgamma_dummy_partition_destroy.c @@ -0,0 +1,24 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Release all resources held by a partition state + * + * @param this The partition state + */ +void +libgamma_dummy_partition_destroy(libgamma_partition_state_t *restrict this) +{ + libgamma_dummy_partition_t *data = this->data; + size_t i; + + if (data) { + for (i = 0; i < data->crtc_count; i++) { + free(data->crtcs[i].info.edid); + free(data->crtcs[i].info.connector_name); + } + free(data->crtcs); + data->crtcs = NULL; + } +} diff --git a/libgamma_dummy_partition_initialise.c b/libgamma_dummy_partition_initialise.c new file mode 100644 index 0000000..093a4d2 --- /dev/null +++ b/libgamma_dummy_partition_initialise.c @@ -0,0 +1,67 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_dummy_partition_initialise(libgamma_partition_state_t *restrict this, + libgamma_site_state_t *restrict site, size_t partition) +{ + libgamma_crtc_information_t template = libgamma_dummy_internal_configurations.crtc_info_template; + libgamma_dummy_site_t *site_data = site->data; + libgamma_dummy_partition_t *data = &site_data->partitions[partition]; + libgamma_dummy_crtc_t *crtc_data; + size_t i, n; + + this->data = NULL; + + if (partition >= site_data->partition_count) + return LIBGAMMA_NO_SUCH_PARTITION; + + this->data = data; + data->state = this; + + data->crtcs = calloc(data->crtc_count, sizeof(libgamma_dummy_crtc_t)); + if (!data->crtcs) + goto fail; + for (i = 0; i < data->crtc_count; i++) { + crtc_data = data->crtcs + i; + crtc_data->info = template; + + /* Duplicate strings */ + if (crtc_data->info.edid) { + crtc_data->info.edid = malloc(crtc_data->info.edid_length * sizeof(char)); + if (!crtc_data->info.edid) + goto fail; + memcpy(crtc_data->info.edid, template.edid, crtc_data->info.edid_length * sizeof(char)); + } + if (crtc_data->info.connector_name) { + n = strlen(crtc_data->info.connector_name); + crtc_data->info.connector_name = malloc((n + 1) * sizeof(char)); + if (!crtc_data->info.connector_name) + goto fail; + memcpy(crtc_data->info.connector_name, template.connector_name, (n + 1) * sizeof(char)); + } + } + + this->crtcs_available = data->crtc_count; + + return 0; + +fail: + for (i = 0; i < data->crtc_count; i++) { + free(data->crtcs[i].info.edid); + free(data->crtcs[i].info.connector_name); + } + free(data->crtcs); + data->crtcs = NULL; + return LIBGAMMA_ERRNO_SET; +} diff --git a/libgamma_dummy_partition_restore.c b/libgamma_dummy_partition_restore.c new file mode 100644 index 0000000..90040c5 --- /dev/null +++ b/libgamma_dummy_partition_restore.c @@ -0,0 +1,28 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_dummy_partition_restore(libgamma_partition_state_t *restrict this) +{ + libgamma_dummy_partition_t *data = this->data; + size_t i; + + if (!libgamma_dummy_internal_configurations.capabilities.partition_restore) { + errno = ENOTSUP; + return LIBGAMMA_ERRNO_SET; + } + + for (i = 0; i < data->crtc_count; i++) + if (libgamma_dummy_internal_crtc_restore_forced(data->crtcs + i) < 0) + return -1; + + return 0; +} diff --git a/libgamma_dummy_site_destroy.c b/libgamma_dummy_site_destroy.c new file mode 100644 index 0000000..7c707ba --- /dev/null +++ b/libgamma_dummy_site_destroy.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Release all resources held by a site state + * + * @param this The site state + */ +void +libgamma_dummy_site_destroy(libgamma_site_state_t *restrict this) +{ + libgamma_dummy_site_t *data = this->data; + if (data) { + free(data->partitions); + free(data); + } +} diff --git a/libgamma_dummy_site_initialise.c b/libgamma_dummy_site_initialise.c new file mode 100644 index 0000000..066f145 --- /dev/null +++ b/libgamma_dummy_site_initialise.c @@ -0,0 +1,62 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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. Once 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_dummy_site_initialise(libgamma_site_state_t *restrict this, char *restrict site) +{ + libgamma_dummy_site_t *data = NULL; + size_t i, sites, crtcs; + + sites = libgamma_dummy_internal_configurations.site_count; + if (!libgamma_dummy_internal_configurations.capabilities.multiple_sites) + sites = !!sites; + this->data = NULL; + + if (site && *site && (atoll(site) < 0 || sites <= (unsigned long long)atoll(site))) + return LIBGAMMA_NO_SUCH_SITE; + + data = malloc(sizeof(libgamma_dummy_site_t)); + if (!data) + goto fail; + + this->data = data; + data->state = this; + + data->partition_count = libgamma_dummy_internal_configurations.default_partition_count; + if (!libgamma_dummy_internal_configurations.capabilities.multiple_partitions) + data->partition_count = !!data->partition_count; + + crtcs = libgamma_dummy_internal_configurations.default_crtc_count; + if (!libgamma_dummy_internal_configurations.capabilities.multiple_crtcs) + crtcs = !!crtcs; + + data->partitions = malloc(data->partition_count * sizeof(libgamma_dummy_partition_t)); + if (!data->partitions) + goto fail; + + for (i = 0; i < data->partition_count; i++) + data->partitions[i].crtc_count = crtcs; + + this->partitions_available = data->partition_count; + + return 0; + +fail: + free(data); + this->data = NULL; + return LIBGAMMA_ERRNO_SET; +} diff --git a/libgamma_dummy_site_restore.c b/libgamma_dummy_site_restore.c new file mode 100644 index 0000000..566a7f3 --- /dev/null +++ b/libgamma_dummy_site_restore.c @@ -0,0 +1,29 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_dummy_site_restore(libgamma_site_state_t *restrict this) +{ + libgamma_dummy_site_t *data = this->data; + size_t i, j; + + if (!libgamma_dummy_internal_configurations.capabilities.site_restore) { + errno = ENOTSUP; + return LIBGAMMA_ERRNO_SET; + } + + for (j = 0; j < data->partition_count; j++) + for (i = 0; i < data->partitions[j].crtc_count; i++) + if (libgamma_dummy_internal_crtc_restore_forced(data->partitions[j].crtcs + i) < 0) + return -1; + + return 0; +} diff --git a/libgamma_get_crtc_information.c b/libgamma_get_crtc_information.c index 023c07f..5c7e2fe 100644 --- a/libgamma_get_crtc_information.c +++ b/libgamma_get_crtc_information.c @@ -2,7 +2,6 @@ #include "common.h" - /** * Read information about a CRTC * @@ -18,7 +17,7 @@ libgamma_get_crtc_information(libgamma_crtc_information_t *restrict this, libgam this->connector_name = NULL; switch (crtc->partition->site->method) { -#define X(CONST, CNAME, DEPTH, RAMPS)\ +#define X(CONST, CNAME, ...)\ case CONST:\ return libgamma_##CNAME##_get_crtc_information(this, crtc, fields); LIST_AVAILABLE_METHODS(X) diff --git a/libgamma_group_gid.c b/libgamma_group_gid.c index b493a0d..54490c3 100644 --- a/libgamma_group_gid.c +++ b/libgamma_group_gid.c @@ -2,7 +2,7 @@ #include "common.h" #ifdef __WIN32__ -#define gid_t short +# define gid_t short #endif diff --git a/libgamma_internal_allocated_any_ramp.c b/libgamma_internal_allocated_any_ramp.c index 7e6953d..28f6ba9 100644 --- a/libgamma_internal_allocated_any_ramp.c +++ b/libgamma_internal_allocated_any_ramp.c @@ -7,11 +7,6 @@ */ #define ANY bits64 -/** - * Concatenation of all ramps - */ -#define ALL red - /** * Allocate and initalise a gamma ramp with any depth @@ -25,11 +20,11 @@ * error identifier provided by this library */ int -libgamma_internal_allocated_any_ramp(gamma_ramps_any_t *restrict ramps_sys, gamma_ramps_any_t ramps, +libgamma_internal_allocated_any_ramp(gamma_ramps_any_t *restrict ramps_sys, const gamma_ramps_any_t *restrict ramps, signed depth, size_t *restrict elements) { /* Calculate the size of the allocation to do */ - size_t d, n = ramps.ANY.red_size + ramps.ANY.green_size + ramps.ANY.blue_size; + size_t d, n = ramps->ANY.red_size + ramps->ANY.green_size + ramps->ANY.blue_size; switch (depth) { case 8: d = sizeof(uint8_t); break; case 16: d = sizeof(uint16_t); break; @@ -42,7 +37,7 @@ libgamma_internal_allocated_any_ramp(gamma_ramps_any_t *restrict ramps_sys, gamm } /* Copy the gamma ramp sizes */ - ramps_sys->ANY = ramps.ANY; + ramps_sys->ANY = ramps->ANY; /* Allocate the new ramps */ #ifdef HAVE_LIBGAMMA_METHOD_LINUX_DRM /* Valgrind complains about us reading uninitialize memory if we just use malloc */ @@ -50,8 +45,8 @@ libgamma_internal_allocated_any_ramp(gamma_ramps_any_t *restrict ramps_sys, gamm #else ramps_sys->ANY.red = malloc(n * d); #endif - ramps_sys->ANY.green = (void *)&((char *)ramps_sys->ANY. red)[ramps.ANY. red_size * d / sizeof(char)]; - ramps_sys->ANY.blue = (void *)&((char *)ramps_sys->ANY.green)[ramps.ANY.green_size * d / sizeof(char)]; + ramps_sys->ANY.green = (void *)&((char *)ramps_sys->ANY. red)[ramps->ANY. red_size * d / sizeof(char)]; + ramps_sys->ANY.blue = (void *)&((char *)ramps_sys->ANY.green)[ramps->ANY.green_size * d / sizeof(char)]; /* Report the total gamma ramp size */ *elements = n; diff --git a/libgamma_internal_translate_from_64.c b/libgamma_internal_translate_from_64.c index b8adbfe..e7203a3 100644 --- a/libgamma_internal_translate_from_64.c +++ b/libgamma_internal_translate_from_64.c @@ -23,19 +23,19 @@ * @param in Input array, may be modified */ void -libgamma_internal_translate_from_64(signed depth, size_t n, gamma_ramps_any_t out, uint64_t *restrict in) +libgamma_internal_translate_from_64(signed depth, size_t n, gamma_ramps_any_t *restrict out, const uint64_t *restrict in) { size_t i; switch (depth) { /* Translate integer */ - case 8: __translate(out.bits8. ALL[i] = (uint8_t)(in[i] / 0x0101010101010101ULL)); - case 16: __translate(out.bits16.ALL[i] = (uint16_t)(in[i] / 0x0001000100010001ULL)); - case 32: __translate(out.bits32.ALL[i] = (uint32_t)(in[i] / 0x0000000100000001ULL)); + case 8: __translate(out->bits8. ALL[i] = (uint8_t)(in[i] / UINT64_C(0x0101010101010101))); + case 16: __translate(out->bits16.ALL[i] = (uint16_t)(in[i] / UINT64_C(0x0001000100010001))); + case 32: __translate(out->bits32.ALL[i] = (uint32_t)(in[i] / UINT64_C(0x0000000100000001))); /* Identity translation */ - case 64: __translate(out.bits64.ALL[i] = in[i]); + case 64: __translate(out->bits64.ALL[i] = in[i]); /* Translate floating point */ - case -1: __translate(out.float_single.ALL[i] = (float)(in[i]) / (float)UINT64_MAX); - case -2: __translate(out.float_double.ALL[i] = (double)(in[i]) / (double)UINT64_MAX); + case -1: __translate(out->float_single.ALL[i] = (float)in[i] / (float)UINT64_MAX); + case -2: __translate(out->float_double.ALL[i] = (double)in[i] / (double)UINT64_MAX); default: /* This is not possible */ abort(); diff --git a/libgamma_internal_translate_to_64.c b/libgamma_internal_translate_to_64.c index 3733186..2c4a316 100644 --- a/libgamma_internal_translate_to_64.c +++ b/libgamma_internal_translate_to_64.c @@ -3,11 +3,6 @@ /** - * Just an arbitrary version - */ -#define ANY bits64 - -/** * Concatenation of all ramps */ #define ALL red @@ -163,19 +158,19 @@ double_to_64(double value) * @param in Input gamma ramps */ void -libgamma_internal_translate_to_64(signed depth, size_t n, uint64_t *restrict out, gamma_ramps_any_t in) +libgamma_internal_translate_to_64(signed depth, size_t n, uint64_t *restrict out, const gamma_ramps_any_t *restrict in) { size_t i; switch (depth) { /* Translate integer */ - case 8: __translate(out[i] = (uint64_t)(in.bits8. ALL[i]) * 0x0101010101010101ULL); - case 16: __translate(out[i] = (uint64_t)(in.bits16.ALL[i]) * 0x0001000100010001ULL); - case 32: __translate(out[i] = (uint64_t)(in.bits32.ALL[i]) * 0x0000000100000001ULL); + case 8: __translate(out[i] = (uint64_t)in->bits8. ALL[i] * UINT64_C(0x0101010101010101)); + case 16: __translate(out[i] = (uint64_t)in->bits16.ALL[i] * UINT64_C(0x0001000100010001)); + case 32: __translate(out[i] = (uint64_t)in->bits32.ALL[i] * UINT64_C(0x0000000100000001)); /* Identity translation */ - case 64: __translate(out[i] = in.bits64.ALL[i]); + case 64: __translate(out[i] = in->bits64.ALL[i]); /* Translate floating point */ - case -1: __translate(out[i] = float_to_64(in.float_single.ALL[i])); - case -2: __translate(out[i] = double_to_64(in.float_double.ALL[i])); + case -1: __translate(out[i] = float_to_64(in->float_single.ALL[i])); + case -2: __translate(out[i] = double_to_64(in->float_double.ALL[i])); default: /* This is not possible */ abort(); diff --git a/libgamma_internal_translated_ramp_get_.c b/libgamma_internal_translated_ramp_get_.c index 1ea4bdc..53ca8a4 100644 --- a/libgamma_internal_translated_ramp_get_.c +++ b/libgamma_internal_translated_ramp_get_.c @@ -33,7 +33,7 @@ libgamma_internal_translated_ramp_get_(libgamma_crtc_state_t *restrict this, gam uint64_t *restrict ramps_full; /* Allocate ramps with proper data type */ - if ((r = libgamma_internal_allocated_any_ramp(&ramps_sys, *ramps, depth_system, &n))) + if ((r = libgamma_internal_allocated_any_ramp(&ramps_sys, ramps, depth_system, &n))) return r; /* Fill the ramps */ @@ -50,11 +50,11 @@ libgamma_internal_translated_ramp_get_(libgamma_crtc_state_t *restrict this, gam } /* Translate ramps to 64-bit integers */ - libgamma_internal_translate_to_64(depth_system, n, ramps_full, ramps_sys); + libgamma_internal_translate_to_64(depth_system, n, ramps_full, &ramps_sys); free(ramps_sys.ANY.red); /* Translate ramps to the user's format */ - libgamma_internal_translate_from_64(depth_user, n, *ramps, ramps_full); + libgamma_internal_translate_from_64(depth_user, n, ramps, ramps_full); free(ramps_full); return 0; } diff --git a/libgamma_internal_translated_ramp_set_.c b/libgamma_internal_translated_ramp_set_.c index 4b4a9af..8099346 100644 --- a/libgamma_internal_translated_ramp_set_.c +++ b/libgamma_internal_translated_ramp_set_.c @@ -24,7 +24,7 @@ * error identifier provided by this library */ int -libgamma_internal_translated_ramp_set_(libgamma_crtc_state_t *restrict this, gamma_ramps_any_t ramps, +libgamma_internal_translated_ramp_set_(libgamma_crtc_state_t *restrict this, const gamma_ramps_any_t *restrict ramps, signed depth_user, signed depth_system, set_ramps_any_fun *fun) { size_t n; @@ -46,11 +46,11 @@ libgamma_internal_translated_ramp_set_(libgamma_crtc_state_t *restrict this, gam /* Translate ramps to 64-bit integers. */ libgamma_internal_translate_to_64(depth_user, n, ramps_full, ramps); /* Translate ramps to the proper format. */ - libgamma_internal_translate_from_64(depth_system, n, ramps_sys, ramps_full); + libgamma_internal_translate_from_64(depth_system, n, &ramps_sys, ramps_full); free(ramps_full); /* Apply the ramps */ - r = fun(this, ramps_sys); + r = fun(this, &ramps_sys); free(ramps_sys.ANY.red); return r; diff --git a/libgamma_is_method_available.c b/libgamma_is_method_available.c index c114295..c821f3b 100644 --- a/libgamma_is_method_available.c +++ b/libgamma_is_method_available.c @@ -15,7 +15,8 @@ libgamma_is_method_available(int method) { switch (method) { #define X(CONST, NAME, CNAME, ENABLED)\ - case CONST: return ENABLED; + case CONST:\ + return ENABLED; LIST_METHODS(X) #undef X default: diff --git a/libgamma_linux_drm_crtc_destroy.c b/libgamma_linux_drm_crtc_destroy.c new file mode 100644 index 0000000..8fc62ee --- /dev/null +++ b/libgamma_linux_drm_crtc_destroy.c @@ -0,0 +1,14 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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; +} diff --git a/libgamma_linux_drm_crtc_get_gamma_ramps16.c b/libgamma_linux_drm_crtc_get_gamma_ramps16.c new file mode 100644 index 0000000..889b934 --- /dev/null +++ b/libgamma_linux_drm_crtc_get_gamma_ramps16.c @@ -0,0 +1,27 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Get the current 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_ramps16(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps16_t *restrict ramps) +{ + libgamma_drm_card_data_t *restrict card = this->partition->data; + int r; +#ifdef DEBUG + /* Gamma ramp sizes are identical but not fixed */ + if (ramps->red_size != ramps->green_size || ramps->red_size != ramps->blue_size) + return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; +#endif + /* Read current gamma ramps */ + 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; +} diff --git a/libgamma_linux_drm_crtc_initialise.c b/libgamma_linux_drm_crtc_initialise.c new file mode 100644 index 0000000..022429b --- /dev/null +++ b/libgamma_linux_drm_crtc_initialise.c @@ -0,0 +1,24 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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 = partition->data; + + if (crtc >= partition->crtcs_available) + return LIBGAMMA_NO_SUCH_CRTC; + this->data = (void*)(size_t)card->res->crtcs[crtc]; + return 0; +} diff --git a/libgamma_linux_drm_crtc_restore.c b/libgamma_linux_drm_crtc_restore.c new file mode 100644 index 0000000..a585e21 --- /dev/null +++ b/libgamma_linux_drm_crtc_restore.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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; + errno = ENOTSUP; + return LIBGAMMA_ERRNO_SET; +} diff --git a/libgamma_linux_drm_crtc_set_gamma_ramps16.c b/libgamma_linux_drm_crtc_set_gamma_ramps16.c new file mode 100644 index 0000000..9691581 --- /dev/null +++ b/libgamma_linux_drm_crtc_set_gamma_ramps16.c @@ -0,0 +1,54 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_ramps16(libgamma_crtc_state_t *restrict this, const libgamma_gamma_ramps16_t *restrict ramps) +{ + libgamma_drm_card_data_t *restrict card = this->partition->data; + int r; +#ifdef DEBUG + /* Gamma ramp sizes are identical but not fixed */ + if (ramps->red_size != ramps->green_size || ramps->red_size != ramps->blue_size) + return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; +#endif + + /* Apply gamma ramps */ + r = drmModeCrtcSetGamma(card->fd, (uint32_t)(size_t)this->data, + (uint32_t)ramps->red_size, ramps->red, ramps->green, ramps->blue); + /* Check for errors */ + 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: + /* TODO: 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; +} diff --git a/libgamma_linux_drm_get_crtc_information.c b/libgamma_linux_drm_get_crtc_information.c new file mode 100644 index 0000000..f7ca7a8 --- /dev/null +++ b/libgamma_linux_drm_get_crtc_information.c @@ -0,0 +1,387 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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) { + /* Allocate connector and encoder arrays; we use `calloc` + so all non-loaded elements are `NULL` after an error */ + card->connectors = calloc(n, sizeof(drmModeConnector *)); + if (!card->connectors) + goto fail; + card->encoders = calloc(n, sizeof(drmModeEncoder *)); + if (!card->encoders) + goto fail; + /* Fill connector and encoder arrays */ + for (i = 0; i < n; i++) { + /* Get connector */ + card->connectors[i] = drmModeGetConnector(card->fd, card->res->connectors[i]); + if (!card->connectors[i]) + goto fail; + /* Get encoder if the connector is enabled. If it is disabled it + will not have an encoder, which is indicated by the encoder + ID being 0. In such case, leave the encoder to be `NULL`. */ + if (card->connectors[i]->encoder_id) { + card->encoders[i] = drmModeGetEncoder(card->fd, card->connectors[i]->encoder_id); + if (!card->encoders[i]) + goto fail; + } + } + } + /* No error has occurred yet */ + *error = 0; + /* Find connector */ + for (i = 0; i < n; i++) + if (card->encoders[i] && card->connectors[i] && card->encoders[i]->crtc_id == crtc_id) + return card->connectors[i]; + /* We did not find the connector */ + *error = LIBGAMMA_CONNECTOR_UNKNOWN; + return NULL; + +fail: + /* Report the error that got us here, release + resouces and exit with `NULL` for failure */ + *error = errno; + libgamma_linux_drm_internal_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; + /* Get CRTC information */ + errno = 0; + crtc_info = drmModeGetCrtc(card->fd, crtc_id); + out->gamma_size_error = crtc_info ? 0 : errno; + /* Get gamma ramp size */ + if (!out->gamma_size_error) { + /* Store gamma ramp size */ + out->red_gamma_size = out->green_gamma_size = out->blue_gamma_size = (size_t)crtc_info->gamma_size; + /* Sanity check gamma ramp size */ + out->gamma_size_error = crtc_info->gamma_size < 2 ? LIBGAMMA_SINGLETON_GAMMA_RAMP : 0; + /* Release CRTC information */ + 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) +{ + switch (connector->subpixel) { +#define X(CONST, NAME, DRM_SUFFIX)\ + case DRM_MODE_SUBPIXEL_##DRM_SUFFIX:\ + out->subpixel_order = CONST;\ + break; + LIST_SUBPIXEL_ORDERS(X) + default: + out->subpixel_order_error = LIBGAMMA_SUBPIXEL_ORDER_NOT_RECOGNISED; + break; +#undef X + } +} + + +/** + * 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) +{ + /* These may not have been included by <xf86drmMode.h>, + but they should be available. Because we define them + ourself, it is best to test them last. */ +#ifndef DRM_MODE_CONNECTOR_VIRTUAL +# define DRM_MODE_CONNECTOR_VIRTUAL 15 +#endif +#ifndef DRM_MODE_CONNECTOR_DSI +# define DRM_MODE_CONNECTOR_DSI 16 +#endif +#ifndef DRM_MODE_CONNECTOR_DPI +# define DRM_MODE_CONNECTOR_DPI 17 +#endif +#ifndef DRM_MODE_CONNECTOR_WRITEBACK +# define DRM_MODE_CONNECTOR_WRITEBACK 18 +#endif +#ifndef DRM_MODE_CONNECTOR_SPI +# define DRM_MODE_CONNECTOR_SPI 19 +#endif + + /* These are not defined */ +#ifndef DRM_MODE_CONNECTOR_DVI +# define DRM_MODE_CONNECTOR_DVI 123000001 +#elif defined(__GNUC__) +# warning DRM_MODE_CONNECTOR_DVI is defined, update fallback definitions +#endif +#ifndef DRM_MODE_CONNECTOR_HDMI +# define DRM_MODE_CONNECTOR_HDMI 123000002 +#elif defined(__GNUC__) +# warning DRM_MODE_CONNECTOR_HDMI is defined, update fallback definitions +#endif +#ifndef DRM_MODE_CONNECTOR_LFP +# define DRM_MODE_CONNECTOR_LFP 123000003 +#elif defined(__GNUC__) +# warning DRM_MODE_CONNECTOR_LFP is defined, update fallback definitions +#endif + + switch (connector->connector_type) { +#define X(CONST, NAME, DRM_SUFFIX)\ + case DRM_MODE_CONNECTOR_##DRM_SUFFIX:\ + out->connector_type = CONST;\ + *connector_name_base = NAME;\ + break; + LIST_CONNECTOR_TYPES(X) +#undef X + default: + out->connector_type_error = LIBGAMMA_CONNECTOR_TYPE_NOT_RECOGNISED; + out->connector_name_error = LIBGAMMA_CONNECTOR_TYPE_NOT_RECOGNISED; + break; + } +} + + +/** + * 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; + libgamma_drm_card_data_t *restrict card; + uint32_t type; + size_t i, n, c; + + /* Get some information that does not require too much work */ + if (fields & (LIBGAMMA_CRTC_INFO_MACRO_ACTIVE | LIBGAMMA_CRTC_INFO_MACRO_CONNECTOR)) { + /* 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) { + if (fields & (LIBGAMMA_CRTC_INFO_MACRO_VIEWPORT | 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) { + card = crtc->partition->data; + type = connector->connector_type; + n = (size_t)card->res->count_connectors; + + /* Allocate memory for the name of the connector */ + out->connector_name = malloc((strlen(connector_name_base) + 12) * sizeof(char)); + if (!out->connector_name) + return (out->connector_name_error = errno); + + /* Get the number of connectors with the same type on the same graphics card */ + for (i = c = 0; i < n && card->connectors[i] != connector; i++) + if (card->connectors[i]->connector_type == type) + c++; + + /* Construct and store connect name that is unique to the graphics card */ + 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; + + /* Test all properies on the connector */ + for (prop_i = 0; prop_i < prop_n; prop_i++) { + /* Get output property */ + prop = drmModeGetProperty(card->fd, connector->props[prop_i]); + if (!prop) + continue; + /* Is this property the EDID? */ + if (!strcmp(prop->name, "EDID")) { + /* Get the property value */ + blob = drmModeGetPropertyBlob(card->fd, (uint32_t)connector->prop_values[prop_i]); + if (!blob) { + drmModeFreeProperty(prop); + return (out->edid_error = LIBGAMMA_PROPERTY_VALUE_QUERY_FAILED); + } + if (blob->data) { + /* Get and store the length of the EDID */ + out->edid_length = blob->length; + /* Allocate memory for a copy of the EDID that is under our memory control */ + out->edid = malloc(out->edid_length * sizeof(unsigned char)); + if (!out->edid) { + out->edid_error = errno; + } else { + /* Copy the EDID so we can free resources that got us here */ + memcpy(out->edid, blob->data, (size_t)out->edid_length * sizeof(char)); + } + /* Free the propriety value and the propery */ + drmModeFreePropertyBlob(blob); + drmModeFreeProperty(prop); + /* Were we successful? */ + return !out->edid; + } + /* Free the propriety value */ + drmModeFreePropertyBlob(blob); + } + /* Free the propriety */ + drmModeFreeProperty(prop); + } + /* If we get here, we did not find a EDID */ + 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, require_connector, free_edid, error; + drmModeConnector *restrict 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 & LIBGAMMA_CRTC_INFO_EDID); + + /* Figure out whether we require the connector to get all information we want */ + require_connector = fields & (LIBGAMMA_CRTC_INFO_MACRO_ACTIVE | LIBGAMMA_CRTC_INFO_MACRO_CONNECTOR); + + /* If we are not interested in the connector or monitor, jump */ + if (!require_connector) + goto cont; + /* Find connector. */ + connector = find_connector(crtc, &error); + if (!connector) { + /* Store reported error in affected fields */ + e |= this->width_mm_error = this->height_mm_error + = this->connector_type_error = 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; + } + + /* Read connector data and monitor data, excluding EDID */ + e |= read_connector_data(crtc, this, connector, fields); + + /* If we do not want any EDID information, jump */ + if (!(fields & LIBGAMMA_CRTC_INFO_MACRO_EDID)) + goto cont; + /* If there is not monitor that report error in EDID related fields */ + if (this->active_error || !this->active) { + e |= this->edid_error = this->gamma_error + = this->width_mm_edid_error = this->height_mm_edid_error + = LIBGAMMA_NOT_CONNECTED; + goto cont; + } + /* Get EDID */ + e |= get_edid(crtc, this, connector); + if (!this->edid) { + this->gamma_error = this->width_mm_edid_error = this->height_mm_edid_error = this->edid_error; + goto cont; + } + /* Parse EDID */ + if (fields & (LIBGAMMA_CRTC_INFO_MACRO_EDID ^ LIBGAMMA_CRTC_INFO_EDID)) + e |= libgamma_internal_parse_edid(this, fields); + +cont: + /* Get gamma ramp size */ + e |= (fields & LIBGAMMA_CRTC_INFO_GAMMA_SIZE) ? get_gamma_ramp_size(this, crtc) : 0; + /* Store gamma ramp depth */ + this->gamma_depth = 16; + /* DRM does not support quering gamma ramp support */ + 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 +} diff --git a/libgamma_linux_drm_internal_release_connectors_and_encoders.c b/libgamma_linux_drm_internal_release_connectors_and_encoders.c new file mode 100644 index 0000000..bede0ed --- /dev/null +++ b/libgamma_linux_drm_internal_release_connectors_and_encoders.c @@ -0,0 +1,32 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Release all connectors and encoders + * + * @param this The graphics card data + */ +void +libgamma_linux_drm_internal_release_connectors_and_encoders(libgamma_drm_card_data_t *restrict this) +{ + size_t i, n; + + /* Release individual encoders */ + if (this->encoders) + for (i = 0, n = (size_t)(this->res->count_connectors); i < n; i++) + if (this->encoders[i]) + drmModeFreeEncoder(this->encoders[i]); + /* Release encoder array */ + free(this->encoders); + this->encoders = NULL; + + /* Release individual connectors */ + if (this->connectors) + for (i = 0, n = (size_t)(this->res->count_connectors); i < n; i++) + if (this->connectors[i]) + drmModeFreeConnector(this->connectors[i]); + /* Release connector array */ + free(this->connectors); + this->connectors = NULL; +} diff --git a/libgamma_linux_drm_method_capabilities.c b/libgamma_linux_drm_method_capabilities.c new file mode 100644 index 0000000..f6d0546 --- /dev/null +++ b/libgamma_linux_drm_method_capabilities.c @@ -0,0 +1,41 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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) +{ + /* Support for all information except gamma ramp support */ + this->crtc_information = LIBGAMMA_CRTC_INFO_MACRO_EDID + | LIBGAMMA_CRTC_INFO_MACRO_VIEWPORT + | LIBGAMMA_CRTC_INFO_MACRO_RAMP + | LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER + | LIBGAMMA_CRTC_INFO_ACTIVE + | LIBGAMMA_CRTC_INFO_MACRO_CONNECTOR; + /* DRM supports multiple partitions and CRTC:s but not sites */ + this->default_site_known = 1; + this->multiple_sites = 0; + this->multiple_partitions = 1; + this->multiple_crtcs = 1; + /* Partitions are graphics cards in DRM */ + this->partitions_are_graphics_cards = 1; + /* Linux does not have system restore capabilities */ + this->site_restore = 0; + this->partition_restore = 0; + this->crtc_restore = 0; + /* Gamma ramp sizes are identical but not fixed */ + this->identical_gamma_sizes = 1; + this->fixed_gamma_size = 0; + /* Gamma ramp depths are fixed */ + this->fixed_gamma_depth = 1; + /* DRM is a real non-faked adjustment method */ + this->real = 1; + this->fake = 0; + /* Gamma ramp adjustments are persistent */ + this->auto_restore = 0; +} diff --git a/libgamma_linux_drm_partition_destroy.c b/libgamma_linux_drm_partition_destroy.c new file mode 100644 index 0000000..5fe8791 --- /dev/null +++ b/libgamma_linux_drm_partition_destroy.c @@ -0,0 +1,20 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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; + libgamma_linux_drm_internal_release_connectors_and_encoders(data); + if (data->res) + drmModeFreeResources(data->res); + if (data->fd >= 0) + close(data->fd); + free(data); +} diff --git a/libgamma_linux_drm_partition_initialise.c b/libgamma_linux_drm_partition_initialise.c new file mode 100644 index 0000000..02cfffc --- /dev/null +++ b/libgamma_linux_drm_partition_initialise.c @@ -0,0 +1,151 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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) +{ + char buf[1024]; /* My output of `sysconf(_SC_GETGR_R_SIZE_MAX)`. */ + gid_t supplemental_groups[NGROUPS_MAX]; + struct group *group, _grp; + struct stat attr; + int i, n; + + + /* Check which the device exists */ + if (errno == ENXIO || errno == ENODEV) + return LIBGAMMA_NO_SUCH_PARTITION; + + + /* If we did not get access permission, figure out why */ + + if (errno != EACCES) { + /* If we could not figure out what went + * wrong, just return the error we got */ + return LIBGAMMA_ERRNO_SET; + } + +#define __test(R, W) ((attr.st_mode & ((R) | (W))) == ((R) | (W))) + + /* Get permission requirement for the file */ + if (stat(pathname, &attr)) + return errno == EACCES ? LIBGAMMA_NO_SUCH_PARTITION : LIBGAMMA_ERRNO_SET; + + /* Test owner's, group's and others' permissions */ + 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; + + /* The group should be "video", but perhaps + it is "root" to restrict users */ + if (!attr.st_gid /* root group */ || __test(S_IRGRP, S_IWGRP)) + return LIBGAMMA_DEVICE_RESTRICTED; + + + /* Get the user's supplemental group membership list */ + n = getgroups(NGROUPS_MAX, supplemental_groups); + if (n < 0) + return LIBGAMMA_ERRNO_SET; + + /* Test whether any of the supplemental + group should be satisfactory */ + for (i = 0; i < n; i++) + if (supplemental_groups[i] == attr.st_gid) + break; + + /* If one of the supplemental groups should be satisfactory, + then we do not know anything more than that access failed */ + if (i != n) + return LIBGAMMA_DEVICE_ACCESS_FAILED; + + /* Otherwise, try to get the name of the group that is + required and report the missing group membership */ + errno = getgrgid_r(attr.st_gid, &_grp, buf, sizeof(buf) / sizeof(char), &group); + if (errno == ERANGE) { + /* The lenght of the group's name is absurdly long, degrade to thread-unsafe. */ + errno = 0; + group = getgrgid(attr.st_gid); + } else if (errno) { + return LIBGAMMA_ERRNO_SET; + } + + libgamma_group_gid_set(attr.st_gid); + libgamma_group_name_set(group ? group->gr_name : NULL); + return LIBGAMMA_DEVICE_REQUIRE_GROUP; +#undef __test +} + + +/** + * 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) + return LIBGAMMA_ERRNO_SET; + data->fd = -1; + data->res = NULL; + data->encoders = NULL; + data->connectors = 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) { + 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; + this->data = data; + return 0; + +fail_res: + drmModeFreeResources(data->res); +fail_fd: + close(data->fd); +fail_data: + free(data); + return rc; +} diff --git a/libgamma_linux_drm_partition_restore.c b/libgamma_linux_drm_partition_restore.c new file mode 100644 index 0000000..9de56ef --- /dev/null +++ b/libgamma_linux_drm_partition_restore.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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; + errno = ENOTSUP; + return LIBGAMMA_ERRNO_SET; +} diff --git a/libgamma_linux_drm_site_destroy.c b/libgamma_linux_drm_site_destroy.c new file mode 100644 index 0000000..68a6b4c --- /dev/null +++ b/libgamma_linux_drm_site_destroy.c @@ -0,0 +1,14 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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; +} diff --git a/libgamma_linux_drm_site_initialise.c b/libgamma_linux_drm_site_initialise.c new file mode 100644 index 0000000..81f6e12 --- /dev/null +++ b/libgamma_linux_drm_site_initialise.c @@ -0,0 +1,42 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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. Once 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) + return LIBGAMMA_NO_SUCH_SITE; + + /* Count the number of available graphics cards by + `stat`:ing their existence in an API filesystem */ + this->partitions_available = 0; + for (;;) { + /* Construct pathname of graphics card device */ + snprintf(pathname, sizeof(pathname) / sizeof(char), + DRM_DEV_NAME, DRM_DIR_NAME, (int)(this->partitions_available)); + /* `stat` the graphics card's existence */ + if (stat(pathname, &_attr)) + break; + /* Move on to next graphics card */ + if (this->partitions_available++ > INT_MAX) + return LIBGAMMA_IMPOSSIBLE_AMOUNT; + } + return 0; +} diff --git a/libgamma_linux_drm_site_restore.c b/libgamma_linux_drm_site_restore.c new file mode 100644 index 0000000..0a5864f --- /dev/null +++ b/libgamma_linux_drm_site_restore.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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; + errno = ENOTSUP; + return LIBGAMMA_ERRNO_SET; +} diff --git a/libgamma_list_methods.c b/libgamma_list_methods.c index 6b912e1..7c923f1 100644 --- a/libgamma_list_methods.c +++ b/libgamma_list_methods.c @@ -125,7 +125,7 @@ libgamma_list_methods(int *restrict methods, size_t buf_size, int operation) { size_t n = 0; -#define X(CONST, CNAME, DEPTH, RAMPS)\ +#define X(CONST, ...)\ if (list_method_test(CONST, operation) && n++ < buf_size)\ methods[n - 1] = CONST; LIST_AVAILABLE_METHODS(X) diff --git a/libgamma_method_capabilities.c b/libgamma_method_capabilities.c index 34623af..d5bdb93 100644 --- a/libgamma_method_capabilities.c +++ b/libgamma_method_capabilities.c @@ -16,7 +16,7 @@ libgamma_method_capabilities(libgamma_method_capabilities_t *restrict this, int memset(this, 0, sizeof(*this)); switch (method) { -#define X(CONST, CNAME, DEPTH, RAMPS)\ +#define X(CONST, CNAME, ...)\ case CONST:\ libgamma_##CNAME##_method_capabilities(this);\ return 0; diff --git a/libgamma_name_of_connector_type.c b/libgamma_name_of_connector_type.c index 2f9b377..f02b961 100644 --- a/libgamma_name_of_connector_type.c +++ b/libgamma_name_of_connector_type.c @@ -18,8 +18,9 @@ const char * libgamma_name_of_connector_type(int connector) { switch (connector) { -#define X(CONST, NAME)\ - case CONST: return NAME; +#define X(CONST, NAME, ...)\ + case CONST:\ + return NAME; LIST_CONNECTOR_TYPES(X) #undef X default: diff --git a/libgamma_name_of_error.c b/libgamma_name_of_error.c index 56de28a..bd34998 100644 --- a/libgamma_name_of_error.c +++ b/libgamma_name_of_error.c @@ -13,8 +13,9 @@ const char * libgamma_name_of_error(int value) { switch (value) { -#define X(NAME, DESC)\ - case NAME: return #NAME; +#define X(NAME, ...)\ + case NAME:\ + return #NAME; LIST_ERRORS(X) #undef X default: diff --git a/libgamma_name_of_method.c b/libgamma_name_of_method.c index 3e1843d..e671d51 100644 --- a/libgamma_name_of_method.c +++ b/libgamma_name_of_method.c @@ -13,8 +13,9 @@ const char * libgamma_name_of_method(int method) { switch (method) { -#define X(CONST, NAME, CNAME, ENABLED)\ - case CONST: return #NAME; +#define X(CONST, NAME, ...)\ + case CONST:\ + return #NAME; LIST_METHODS(X) #undef X default: diff --git a/libgamma_name_of_subpixel_order.c b/libgamma_name_of_subpixel_order.c index f8c0bf8..c3612bf 100644 --- a/libgamma_name_of_subpixel_order.c +++ b/libgamma_name_of_subpixel_order.c @@ -17,8 +17,9 @@ const char * libgamma_name_of_subpixel_order(int order) { switch (order) { -#define X(CONST, NAME)\ - case CONST: return NAME; +#define X(CONST, NAME, ...)\ + case CONST:\ + return NAME; LIST_SUBPIXEL_ORDERS(X) #undef X default: diff --git a/libgamma_partition_destroy.c b/libgamma_partition_destroy.c index 9709865..4f96945 100644 --- a/libgamma_partition_destroy.c +++ b/libgamma_partition_destroy.c @@ -11,7 +11,7 @@ void libgamma_partition_destroy(libgamma_partition_state_t *restrict this) { switch (this->site->method) { -#define X(CONST, CNAME, DEPTH, RAMPS)\ +#define X(CONST, CNAME, ...)\ case CONST:\ libgamma_##CNAME##_partition_destroy(this);\ break; diff --git a/libgamma_partition_initialise.c b/libgamma_partition_initialise.c index 80b5976..4f2e763 100644 --- a/libgamma_partition_initialise.c +++ b/libgamma_partition_initialise.c @@ -18,7 +18,7 @@ libgamma_partition_initialise(libgamma_partition_state_t *restrict this, libgamm this->partition = partition; switch (site->method) { -#define X(CONST, CNAME, DEPTH, RAMPS)\ +#define X(CONST, CNAME, ...)\ case CONST:\ return libgamma_##CNAME##_partition_initialise(this, site, partition); LIST_AVAILABLE_METHODS(X) diff --git a/libgamma_partition_restore.c b/libgamma_partition_restore.c index 0b20626..e1ff6bb 100644 --- a/libgamma_partition_restore.c +++ b/libgamma_partition_restore.c @@ -13,7 +13,7 @@ int libgamma_partition_restore(libgamma_partition_state_t *restrict this) { switch (this->site->method) { -#define X(CONST, CNAME, DEPTH, RAMPS)\ +#define X(CONST, CNAME, ...)\ case CONST:\ return libgamma_##CNAME##_partition_restore(this); LIST_AVAILABLE_METHODS(X) diff --git a/libgamma_quartz_cg_crtc_destroy.c b/libgamma_quartz_cg_crtc_destroy.c new file mode 100644 index 0000000..e73bb65 --- /dev/null +++ b/libgamma_quartz_cg_crtc_destroy.c @@ -0,0 +1,14 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Release all resources held by a CRTC state + * + * @param this The CRTC state + */ +void +libgamma_quartz_cg_crtc_destroy(libgamma_crtc_state_t *restrict this) +{ + (void) this; +} diff --git a/libgamma_quartz_cg_crtc_get_gamma_rampsf.c b/libgamma_quartz_cg_crtc_get_gamma_rampsf.c new file mode 100644 index 0000000..a2e8056 --- /dev/null +++ b/libgamma_quartz_cg_crtc_get_gamma_rampsf.c @@ -0,0 +1,35 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Get the current gamma ramps for a CRTC, `float` 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_quartz_cg_crtc_get_gamma_rampsf(libgamma_crtc_state_t *restrict this, libgamma_gamma_rampsf_t *restrict ramps) +{ + CGDirectDisplayID *restrict crtcs = this->partition->data; + CGDirectDisplayID crtc_id = crtcs[this->crtc]; + uint32_t gamma_size_out; + CGError r; +#ifdef DEBUG + /* Gamma ramps sizes are identical but not fixed */ + if (ramps->red_size != ramps->green_size || ramps->red_size != ramps->blue_size) + return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; +#endif + /* Read current gamma ramps */ + r = CGGetDisplayTransferByTable(crtc_id, (uint32_t)ramps->red_size, ramps->red, ramps->green, ramps->blue, &gamma_size_out); + if (r != kCGErrorSuccess) + return LIBGAMMA_GAMMA_RAMP_READ_FAILED; + /* I hope that it will not actually ever change, + but it does return the the gamma ramp size despite + that it can be queried without querying for more */ + if (gamma_size_out != ramps->red_size) + return LIBGAMMA_GAMMA_RAMP_SIZE_CHANGED; + return 0; +} diff --git a/libgamma_quartz_cg_crtc_initialise.c b/libgamma_quartz_cg_crtc_initialise.c new file mode 100644 index 0000000..988185f --- /dev/null +++ b/libgamma_quartz_cg_crtc_initialise.c @@ -0,0 +1,21 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + + +/** + * 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_quartz_cg_crtc_initialise(libgamma_crtc_state_t *restrict this, + libgamma_partition_state_t *restrict partition, size_t crtc) +{ + (void) this; + return crtc < partition->crtcs_available ? 0 : LIBGAMMA_NO_SUCH_CRTC; +} diff --git a/libgamma_quartz_cg_crtc_restore.c b/libgamma_quartz_cg_crtc_restore.c new file mode 100644 index 0000000..78514eb --- /dev/null +++ b/libgamma_quartz_cg_crtc_restore.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_quartz_cg_crtc_restore(libgamma_crtc_state_t *restrict this) +{ + (void) this; + errno = ENOTSUP; + return LIBGAMMA_ERRNO_SET; +} diff --git a/libgamma_quartz_cg_crtc_set_gamma_rampsf.c b/libgamma_quartz_cg_crtc_set_gamma_rampsf.c new file mode 100644 index 0000000..5cde1eb --- /dev/null +++ b/libgamma_quartz_cg_crtc_set_gamma_rampsf.c @@ -0,0 +1,27 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Set the gamma ramps for a CRTC, `float` 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_quartz_cg_crtc_set_gamma_rampsf(libgamma_crtc_state_t *restrict this, const libgamma_gamma_rampsf_t *restrict ramps) +{ + CGDirectDisplayID *restrict crtcs = this->partition->data; + CGDirectDisplayID crtc_id = crtcs[this->crtc]; + CGError r; +#ifdef DEBUG + /* Gamma ramps sizes are identical but not fixed */ + if (ramps->red_size != ramps->green_size || ramps->red_size != ramps->blue_size) + return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; +#endif + /* Apply gamma ramps */ + r = CGSetDisplayTransferByTable(crtc_id, (uint32_t)ramps->red_size, ramps->red, ramps->green, ramps->blue); + return r == kCGErrorSuccess ? 0 : LIBGAMMA_GAMMA_RAMP_WRITE_FAILED; +} diff --git a/libgamma_quartz_cg_get_crtc_information.c b/libgamma_quartz_cg_get_crtc_information.c new file mode 100644 index 0000000..da4937e --- /dev/null +++ b/libgamma_quartz_cg_get_crtc_information.c @@ -0,0 +1,56 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + + +/** + * 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_quartz_cg_get_crtc_information(libgamma_crtc_information_t *restrict this, + libgamma_crtc_state_t *restrict crtc, int32_t fields) +{ +#define SUPPORTED_FIELDS (LIBGAMMA_CRTC_INFO_GAMMA_SIZE | LIBGAMMA_CRTC_INFO_GAMMA_DEPTH) +#define _E(FIELD) ((fields & FIELD) ? LIBGAMMA_CRTC_INFO_NOT_SUPPORTED : 0) + + CGDirectDisplayID *restrict crtcs; + size_t gamma_size; + + /* Quartz/CoreGraphics does not support EDID or monitor dimensions */ + this->edid_error = _E(LIBGAMMA_CRTC_INFO_EDID); + this->width_mm_error = _E(LIBGAMMA_CRTC_INFO_WIDTH_MM); + this->height_mm_error = _E(LIBGAMMA_CRTC_INFO_HEIGHT_MM); + this->width_mm_edid_error = _E(LIBGAMMA_CRTC_INFO_WIDTH_MM_EDID); + this->height_mm_edid_error = _E(LIBGAMMA_CRTC_INFO_HEIGHT_MM_EDID); + /* Quartz/CoreGraphics does support gamma ramp size query + The gamma ramps are identical but not fixed, and the query can fail */ + this->gamma_size_error = 0; + if ((fields & LIBGAMMA_CRTC_INFO_GAMMA_SIZE)) { + crtcs = crtc->partition->data; + gamma_size = CGDisplayGammaTableCapacity(crtcs[crtc->crtc]); + this->red_gamma_size = this->green_gamma_size = this->blue_gamma_size = (size_t)gamma_size; + this->gamma_size_error = gamma_size < 2 ? LIBGAMMA_SINGLETON_GAMMA_RAMP : 0; + } + /* Quartz/CoreGraphics uses `float` ramps */ + this->gamma_depth = -1; + this->gamma_depth_error = 0; + /* Quartz/CoreGraphics does not support gamma ramp support queries */ + this->gamma_support_error = _E(LIBGAMMA_CRTC_INFO_GAMMA_SUPPORT); + /* Quartz/CoreGraphics does not support EDID or connector information */ + this->subpixel_order_error = _E(LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER); + this->active_error = _E(LIBGAMMA_CRTC_INFO_ACTIVE); + this->connector_name_error = _E(LIBGAMMA_CRTC_INFO_CONNECTOR_NAME); + this->connector_type_error = _E(LIBGAMMA_CRTC_INFO_CONNECTOR_TYPE); + this->gamma_error = _E(LIBGAMMA_CRTC_INFO_GAMMA); + + /* We failed if gamma ramp size query failed or if an unsupport field was queried */ + return (this->gamma_size_error || (fields & ~SUPPORTED_FIELDS)) ? -1 : 0; + +#undef _E +#undef SUPPORTED_FIELDS +} diff --git a/libgamma_quartz_cg_method_capabilities.c b/libgamma_quartz_cg_method_capabilities.c new file mode 100644 index 0000000..661fc0f --- /dev/null +++ b/libgamma_quartz_cg_method_capabilities.c @@ -0,0 +1,49 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Return the capabilities of the adjustment method + * + * @param this The data structure to fill with the method's capabilities + */ +void +libgamma_quartz_cg_method_capabilities(libgamma_method_capabilities_t* restrict this) +{ + /* Gamma ramps size and depth can be queried */ + this->crtc_information = LIBGAMMA_CRTC_INFO_GAMMA_SIZE | LIBGAMMA_CRTC_INFO_GAMMA_DEPTH; + /* Quartz/CoreGraphics does not support sites or partitions */ + this->default_site_known = 1; + this->multiple_sites = 0; + this->multiple_partitions = 0; + /* Quartz/CoreGraphics does support CRTC:s */ + this->multiple_crtcs = 1; + /* Partitions are not supported... */ + this->partitions_are_graphics_cards = 0; + /* CoreGraphics have support for system restore */ + this->site_restore = 1; + this->partition_restore = 1; + /* But not for individual CRTC:s */ + this->crtc_restore = 0; + /* Gamma ramp sizes are identifical but not fixed */ + this->identical_gamma_sizes = 1; + this->fixed_gamma_size = 0; + /* Gamma ramp depths are fixed */ + this->fixed_gamma_depth = 1; + /* Quartz/CoreGraphics is a real adjustment method that can be faked */ +#ifdef FAKE_LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS + /* It is considered real but fake if it is translated to X RandR */ + this->fake = 1; +# ifdef HAVE_LIBGAMMA_METHOD_X_RANDR + this->real = 1; +# else + this->real = 0; +# endif +#else + /* It is real and not fake if we are running on Mac OS X */ + this->fake = 0; + this->real = 1; +#endif + /* Gamma ramp adjustments are non-persistent */ + this->auto_restore = 1; +} diff --git a/libgamma_quartz_cg_partition_destroy.c b/libgamma_quartz_cg_partition_destroy.c new file mode 100644 index 0000000..9aed872 --- /dev/null +++ b/libgamma_quartz_cg_partition_destroy.c @@ -0,0 +1,14 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Release all resources held by a partition state + * + * @param this The partition state + */ +void +libgamma_quartz_cg_partition_destroy(libgamma_partition_state_t *restrict this) +{ + free(this->data); +} diff --git a/libgamma_quartz_cg_partition_initialise.c b/libgamma_quartz_cg_partition_initialise.c new file mode 100644 index 0000000..694ecbc --- /dev/null +++ b/libgamma_quartz_cg_partition_initialise.c @@ -0,0 +1,59 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_quartz_cg_partition_initialise(libgamma_partition_state_t *restrict this, + libgamma_site_state_t *restrict site, size_t partition) +{ + CGDirectDisplayID *crtcs, *crtcs_old; + uint32_t cap = 4, n; + + (void) site; + + this->data = NULL; + + if (partition) + return LIBGAMMA_NO_SUCH_PARTITION; + + /* Allocate array of CRTC ID:s */ + crtcs = malloc((size_t)cap * sizeof(CGDirectDisplayID)); + if (!crtcs) + return LIBGAMMA_ERRNO_SET; + + /* It is not possible to ask CoreGraphics how many CRTC:s are + * available. We have to ask it to give us a ID:s of a number + * of CRTC:s and ask for more if we got as many as we asked for. */ + for (;;) { + /* Ask for CRTC ID:s */ + if (CGGetOnlineDisplayList(cap, crtcs, &n) != kCGErrorSuccess) + return free(crtcs), LIBGAMMA_LIST_CRTCS_FAILED; + /* If we did not get as many as we asked for then we have all */ + if (n < cap) + break; + /* Increase the number CRTC ID:s to ask for */ + if (cap > SIZE_MAX / 2) /* We could also test ~0, but it is still too many */ + return free(crtcs), LIBGAMMA_IMPOSSIBLE_AMOUNT; + cap <<= 1; + /* Grow the array of CRTC ID:s so that it can fit all we are asking for */ + crtcs = realloc(crtcs_old = crtcs, (size_t)cap * sizeof(CGDirectDisplayID)); + if (!crtcs) { + free(crtcs_old); + return LIBGAMMA_ERRNO_SET; + } + } + + /* Store CRTC ID:s and CRTC count */ + this->data = crtcs; + this->crtcs_available = (size_t)n; + return 0; +} diff --git a/libgamma_quartz_cg_partition_restore.c b/libgamma_quartz_cg_partition_restore.c new file mode 100644 index 0000000..094952b --- /dev/null +++ b/libgamma_quartz_cg_partition_restore.c @@ -0,0 +1,16 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_quartz_cg_partition_restore(libgamma_partition_state_t *restrict this) +{ + return libgamma_quartz_cg_site_restore(this->site); +} diff --git a/libgamma_quartz_cg_site_destroy.c b/libgamma_quartz_cg_site_destroy.c new file mode 100644 index 0000000..9fd65d1 --- /dev/null +++ b/libgamma_quartz_cg_site_destroy.c @@ -0,0 +1,15 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Release all resources held by a site state + * + * @param this The site state + */ +void +libgamma_quartz_cg_site_destroy(libgamma_site_state_t *restrict this) +{ + (void) this; + close_fake_quartz_cg(); +} diff --git a/libgamma_quartz_cg_site_initialise.c b/libgamma_quartz_cg_site_initialise.c new file mode 100644 index 0000000..962471d --- /dev/null +++ b/libgamma_quartz_cg_site_initialise.c @@ -0,0 +1,23 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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. Once 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_quartz_cg_site_initialise(libgamma_site_state_t *restrict this, char *restrict site) +{ + this->partitions_available = 1; + return site ? 0 : LIBGAMMA_NO_SUCH_SITE; +} diff --git a/libgamma_quartz_cg_site_restore.c b/libgamma_quartz_cg_site_restore.c new file mode 100644 index 0000000..0accad5 --- /dev/null +++ b/libgamma_quartz_cg_site_restore.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_quartz_cg_site_restore(libgamma_site_state_t *restrict this) +{ + (void) this; + CGDisplayRestoreColorSyncSettings(); + return 0; +} diff --git a/libgamma_site_destroy.c b/libgamma_site_destroy.c index c3e060a..83b640b 100644 --- a/libgamma_site_destroy.c +++ b/libgamma_site_destroy.c @@ -11,7 +11,7 @@ void libgamma_site_destroy(libgamma_site_state_t *restrict this) { switch (this->method) { -#define X(CONST, CNAME, DEPTH, RAMPS)\ +#define X(CONST, CNAME, ...)\ case CONST:\ libgamma_##CNAME##_site_destroy(this);\ break; diff --git a/libgamma_site_initialise.c b/libgamma_site_initialise.c index 23acc2d..15d7680 100644 --- a/libgamma_site_initialise.c +++ b/libgamma_site_initialise.c @@ -23,7 +23,7 @@ libgamma_site_initialise(libgamma_site_state_t *restrict this, int method, char this->site = site; switch (method) { -#define X(CONST, CNAME, DEPTH, RAMPS)\ +#define X(CONST, CNAME, ...)\ case CONST:\ return libgamma_##CNAME##_site_initialise(this, site); LIST_AVAILABLE_METHODS(X) diff --git a/libgamma_site_restore.c b/libgamma_site_restore.c index b6c936a..52be79e 100644 --- a/libgamma_site_restore.c +++ b/libgamma_site_restore.c @@ -13,7 +13,7 @@ int libgamma_site_restore(libgamma_site_state_t *restrict this) { switch (this->method) { -#define X(CONST, CNAME, DEPTH, RAMPS)\ +#define X(CONST, CNAME, ...)\ case CONST:\ return libgamma_##CNAME##_site_restore(this); LIST_AVAILABLE_METHODS(X) diff --git a/libgamma_strerror.c b/libgamma_strerror.c index c252a49..77d4c89 100644 --- a/libgamma_strerror.c +++ b/libgamma_strerror.c @@ -20,7 +20,7 @@ libgamma_strerror(int error_code) switch (error_code) { #define X(NAME, DESC)\ case NAME:\ - desc = #NAME;\ + desc = DESC;\ break; LIST_ERRORS(X) #undef X diff --git a/libgamma_strerror_r.c b/libgamma_strerror_r.c index 42f396e..781558c 100644 --- a/libgamma_strerror_r.c +++ b/libgamma_strerror_r.c @@ -26,7 +26,7 @@ libgamma_strerror_r(int error_code, char buf[], size_t bufsize) switch (error_code) { #define X(NAME, DESC)\ case NAME:\ - desc = #NAME;\ + desc = DESC;\ break; LIST_ERRORS(X) #undef X @@ -42,7 +42,7 @@ libgamma_strerror_r(int error_code, char buf[], size_t bufsize) /* XSI strerror_r */ int: (errno = (int)(intptr_t)strerror_r(error_code, buf, bufsize)) ? NULL : buf, /* GNU strerror_r */ - char *: (desc = (char *)(uintptr_t)strerror_r(error_code, buf, bufsize))); + char *: (char *)(intptr_t)strerror_r(error_code, buf, bufsize)); if (desc) { errno = saved_errno; if (!buf || strcmp(buf, "No error information")) diff --git a/libgamma_value_of_connector_type.c b/libgamma_value_of_connector_type.c index ff81bfc..5ffdaf5 100644 --- a/libgamma_value_of_connector_type.c +++ b/libgamma_value_of_connector_type.c @@ -13,13 +13,13 @@ int libgamma_value_of_connector_type(const char *connector) { -#define X(CONST, NAME)\ +#define X(CONST, NAME, ...)\ if (!strcmp(connector, NAME))\ return CONST; LIST_CONNECTOR_TYPES(X) #undef X -#define X(CONST, NAME)\ +#define X(CONST, ...)\ if (!strcmp(connector, #CONST))\ return CONST; LIST_CONNECTOR_TYPES(X) diff --git a/libgamma_value_of_error.c b/libgamma_value_of_error.c index 6d2f878..41ca40f 100644 --- a/libgamma_value_of_error.c +++ b/libgamma_value_of_error.c @@ -6,7 +6,7 @@ * Get the value of a `libgamma` error definition refered to by name * * @param name The name of the definition associated with the error code - * @return The error code, zero if the name does is `NULL` + * @return The error code, zero if the name is `NULL` * or does not refer to a `libgamma` error */ int @@ -14,7 +14,7 @@ libgamma_value_of_error(const char *name) { if (!name) return 0; -#define X(NAME, DESC)\ +#define X(NAME, ...)\ if (!strcmp(name, #NAME))\ return NAME; LIST_ERRORS(X) diff --git a/libgamma_value_of_method.c b/libgamma_value_of_method.c index ffd69c8..7015453 100644 --- a/libgamma_value_of_method.c +++ b/libgamma_value_of_method.c @@ -12,13 +12,13 @@ int libgamma_value_of_method(const char *method) { -#define X(CONST, NAME, CNAME, ENABLED)\ +#define X(CONST, NAME, ...)\ if (!strcmp(method, #NAME))\ return CONST; LIST_METHODS(X) #undef X -#define X(CONST, NAME, CNAME, ENABLED)\ +#define X(CONST, ...)\ if (!strcmp(method, #CONST))\ return CONST; LIST_METHODS(X) diff --git a/libgamma_value_of_subpixel_order.c b/libgamma_value_of_subpixel_order.c index 02a1fa7..163fed2 100644 --- a/libgamma_value_of_subpixel_order.c +++ b/libgamma_value_of_subpixel_order.c @@ -13,13 +13,13 @@ int libgamma_value_of_subpixel_order(const char *order) { -#define X(CONST, NAME)\ +#define X(CONST, NAME, ...)\ if (!strcmp(order, NAME))\ return CONST; LIST_SUBPIXEL_ORDERS(X) #undef X -#define X(CONST, NAME)\ +#define X(CONST, ...)\ if (!strcmp(order, #CONST))\ return CONST; LIST_SUBPIXEL_ORDERS(X) diff --git a/libgamma_w32_gdi_crtc_destroy.c b/libgamma_w32_gdi_crtc_destroy.c new file mode 100644 index 0000000..0bbb8e9 --- /dev/null +++ b/libgamma_w32_gdi_crtc_destroy.c @@ -0,0 +1,15 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Release all resources held by a CRTC state + * + * @param this The CRTC state + */ +void +libgamma_w32_gdi_crtc_destroy(libgamma_crtc_state_t *restrict this) +{ + if (this->data) + ReleaseDC(NULL, this->data); +} diff --git a/libgamma_w32_gdi_crtc_get_gamma_ramps16.c b/libgamma_w32_gdi_crtc_get_gamma_ramps16.c new file mode 100644 index 0000000..64218d7 --- /dev/null +++ b/libgamma_w32_gdi_crtc_get_gamma_ramps16.c @@ -0,0 +1,27 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Get the current 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_w32_gdi_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps16_t *restrict ramps) +{ +#ifdef DEBUG + /* Windows GDI have fixed gamma ramp sizes */ + if (ramps-> red_size != W32_GDI_GAMMA_RAMP_SIZE || + ramps->green_size != W32_GDI_GAMMA_RAMP_SIZE || + ramps-> blue_size != W32_GDI_GAMMA_RAMP_SIZE) + return LIBGAMMA_WRONG_GAMMA_RAMP_SIZE; +#endif + /* Read current gamma ramps */ + if (!GetDeviceGammaRamp(this->data, ramps->red)) + return LIBGAMMA_GAMMA_RAMP_READ_FAILED; + return 0; +} diff --git a/libgamma_w32_gdi_crtc_initialise.c b/libgamma_w32_gdi_crtc_initialise.c new file mode 100644 index 0000000..7bd2218 --- /dev/null +++ b/libgamma_w32_gdi_crtc_initialise.c @@ -0,0 +1,43 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + + +/** + * 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_w32_gdi_crtc_initialise(libgamma_crtc_state_t *restrict this, + libgamma_partition_state_t *restrict partition, size_t crtc) +{ + DISPLAY_DEVICE display; + HDC context; + + (void) partition; + + this->data = NULL; + + /* Windows's API mandates this... */ + display.cb = sizeof(DISPLAY_DEVICE); + /* Get identifier for selected CRTC */ + if (!EnumDisplayDevices(NULL, (DWORD)crtc, &display, 0)) + return LIBGAMMA_NO_SUCH_CRTC; + /* Check that the connector is enabled, + * newer versions of Windows will always pass. + * (According to w32's documentation, but that + * that is a load of crap) */ + if (!(display.StateFlags & DISPLAY_DEVICE_ACTIVE)) + return LIBGAMMA_CONNECTOR_DISABLED; + /* Acquire CRTC connection. */ + context = CreateDC(TEXT("DISPLAY"), display.DeviceName, NULL, NULL); + if (!context) + return LIBGAMMA_OPEN_CRTC_FAILED; + this->data = context; + return 0; +} diff --git a/libgamma_w32_gdi_crtc_restore.c b/libgamma_w32_gdi_crtc_restore.c new file mode 100644 index 0000000..85dceb6 --- /dev/null +++ b/libgamma_w32_gdi_crtc_restore.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_w32_gdi_crtc_restore(libgamma_crtc_state_t *restrict this) +{ + (void) this; + errno = ENOTSUP; + return LIBGAMMA_ERRNO_SET; +} diff --git a/libgamma_w32_gdi_crtc_set_gamma_ramps16.c b/libgamma_w32_gdi_crtc_set_gamma_ramps16.c new file mode 100644 index 0000000..10f7524 --- /dev/null +++ b/libgamma_w32_gdi_crtc_set_gamma_ramps16.c @@ -0,0 +1,27 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_w32_gdi_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict this, const libgamma_gamma_ramps16_t *restrict ramps) +{ +#ifdef DEBUG + /* Windows GDI have fixed gamma ramp sizes */ + if (ramps-> red_size != W32_GDI_GAMMA_RAMP_SIZE || + ramps->green_size != W32_GDI_GAMMA_RAMP_SIZE || + ramps-> blue_size != W32_GDI_GAMMA_RAMP_SIZE) + return LIBGAMMA_WRONG_GAMMA_RAMP_SIZE; +#endif + /* Apply gamma ramps */ + if (!SetDeviceGammaRamp(this->data, ramps->red)) + return LIBGAMMA_GAMMA_RAMP_WRITE_FAILED; + return 0; +} diff --git a/libgamma_w32_gdi_get_crtc_information.c b/libgamma_w32_gdi_get_crtc_information.c new file mode 100644 index 0000000..c3c2819 --- /dev/null +++ b/libgamma_w32_gdi_get_crtc_information.c @@ -0,0 +1,59 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + + +/** + * 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_w32_gdi_get_crtc_information(libgamma_crtc_information_t *restrict this, + libgamma_crtc_state_t *restrict crtc, int32_t fields) +{ +#define KNOWN_FIELDS (LIBGAMMA_CRTC_INFO_GAMMA_SIZE | LIBGAMMA_CRTC_INFO_GAMMA_DEPTH) +#define _E(FIELD) ((fields & FIELD) ? LIBGAMMA_CRTC_INFO_NOT_SUPPORTED : 0) + + (void) crtc; + + /* Windows GDI does not support EDID or monitor dimensions */ + this->edid_error = _E(LIBGAMMA_CRTC_INFO_EDID); + this->width_mm_error = _E(LIBGAMMA_CRTC_INFO_WIDTH_MM); + this->height_mm_error = _E(LIBGAMMA_CRTC_INFO_HEIGHT_MM); + this->width_mm_edid_error = _E(LIBGAMMA_CRTC_INFO_WIDTH_MM_EDID); + this->height_mm_edid_error = _E(LIBGAMMA_CRTC_INFO_HEIGHT_MM_EDID); + /* Windows GDI have fixed gamma ramp sizes */ + this->red_gamma_size = W32_GDI_GAMMA_RAMP_SIZE; + this->green_gamma_size = W32_GDI_GAMMA_RAMP_SIZE; + this->blue_gamma_size = W32_GDI_GAMMA_RAMP_SIZE; + this->gamma_size_error = 0; + /* Windows GDI have fixed gamma ramp depth */ + this->gamma_depth = 16; + this->gamma_depth_error = 0; + /* It is possible to query Windows GDI whether the device + have gamma ramp support. It cannot fail. However, I think + the result is incorrect if multiple monitors are active, + so we cannot include this. */ + /* + if ((fields & LIBGAMMA_CRTC_INFO_GAMMA_SUPPORT)) + this->gamma_support = GetDeviceCaps(crtc->data, COLORMGMTCAPS) == CM_GAMMA_RAMP; + this->gamma_support_error = 0; + */ + this->gamma_support_error = _E(LIBGAMMA_CRTC_INFO_GAMMA_SUPPORT); + /* Windows GDI does not support EDID or connector information */ + this->subpixel_order_error = _E(LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER); + this->active_error = _E(LIBGAMMA_CRTC_INFO_ACTIVE); + this->connector_name_error = _E(LIBGAMMA_CRTC_INFO_CONNECTOR_NAME); + this->connector_type_error = _E(LIBGAMMA_CRTC_INFO_CONNECTOR_TYPE); + this->gamma_error = _E(LIBGAMMA_CRTC_INFO_GAMMA); + + /* There was a failure if and only if unsupport field was requested. */ + return (fields & ~KNOWN_FIELDS) ? -1 : 0; + +#undef _E +#undef KNOWN_FIELDS +} diff --git a/libgamma_w32_gdi_method_capabilities.c b/libgamma_w32_gdi_method_capabilities.c new file mode 100644 index 0000000..18860c8 --- /dev/null +++ b/libgamma_w32_gdi_method_capabilities.c @@ -0,0 +1,47 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Return the capabilities of the adjustment method + * + * @param this The data structure to fill with the method's capabilities + */ +void +libgamma_w32_gdi_method_capabilities(libgamma_method_capabilities_t *restrict this) +{ + /* Gamma ramps size, depth and support can be queried */ + this->crtc_information = LIBGAMMA_CRTC_INFO_GAMMA_SIZE | LIBGAMMA_CRTC_INFO_GAMMA_DEPTH; + /* Windows GDI does not support sites or partitions */ + this->default_site_known = 1; + this->multiple_sites = 0; + this->multiple_partitions = 0; + /* Windows GDI does support CRTC:s */ + this->multiple_crtcs = 1; + /* Partitions are not supported... */ + this->partitions_are_graphics_cards = 0; + /* Windows GDI does not have system restore capabilities */ + this->site_restore = 0; + this->partition_restore = 0; + this->crtc_restore = 0; + /* Ramps sizes are fixed and identical and ramp depth is too */ + this->identical_gamma_sizes = 1; + this->fixed_gamma_size = 1; + this->fixed_gamma_depth = 1; + /* Windows GDI is a real adjustment method that can be faked */ +#ifdef FAKE_LIBGAMMA_METHOD_W32_GDI + /* It is considered real but fake if it is translated to X RandR */ + this->fake = 1; +# ifdef HAVE_LIBGAMMA_METHOD_X_RANDR + this->real = 1; +# else + this->real = 0; +# endif +#else + /* It is real and not fake if we are running on Windows */ + this->fake = 0; + this->real = 1; +#endif + /* Gamma ramp adjustments are persistent */ + this->auto_restore = 0; +} diff --git a/libgamma_w32_gdi_partition_destroy.c b/libgamma_w32_gdi_partition_destroy.c new file mode 100644 index 0000000..e508083 --- /dev/null +++ b/libgamma_w32_gdi_partition_destroy.c @@ -0,0 +1,14 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Release all resources held by a partition state + * + * @param this The partition state + */ +void +libgamma_w32_gdi_partition_destroy(libgamma_partition_state_t *restrict this) +{ + (void) this; +} diff --git a/libgamma_w32_gdi_partition_initialise.c b/libgamma_w32_gdi_partition_initialise.c new file mode 100644 index 0000000..81ab398 --- /dev/null +++ b/libgamma_w32_gdi_partition_initialise.c @@ -0,0 +1,35 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + + +/** + * 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_w32_gdi_partition_initialise(libgamma_partition_state_t *restrict this, + libgamma_site_state_t *restrict site, size_t partition) +{ + DWORD n = 0; + DISPLAY_DEVICE display; + + (void) site; + + if (partition) + return LIBGAMMA_NO_SUCH_PARTITION; + + /* Count CRTC:s by iteration over all possible identifiers + until we reach on that does not exist */ + display.cb = sizeof(DISPLAY_DEVICE); + while (EnumDisplayDevices(NULL, n, &display, 0)) + if (n++ == UINT32_MAX) + return LIBGAMMA_IMPOSSIBLE_AMOUNT; + this->crtcs_available = (size_t)n; + return 0; +} diff --git a/libgamma_w32_gdi_partition_restore.c b/libgamma_w32_gdi_partition_restore.c new file mode 100644 index 0000000..d2d5498 --- /dev/null +++ b/libgamma_w32_gdi_partition_restore.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_w32_gdi_partition_restore(libgamma_partition_state_t *restrict this) +{ + (void) this; + errno = ENOTSUP; + return LIBGAMMA_ERRNO_SET; +} diff --git a/libgamma_w32_gdi_site_destroy.c b/libgamma_w32_gdi_site_destroy.c new file mode 100644 index 0000000..4b022d9 --- /dev/null +++ b/libgamma_w32_gdi_site_destroy.c @@ -0,0 +1,14 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Release all resources held by a site state + * + * @param this The site state + */ +void +libgamma_w32_gdi_site_destroy(libgamma_site_state_t *restrict this) +{ + (void) this; +} diff --git a/libgamma_w32_gdi_site_initialise.c b/libgamma_w32_gdi_site_initialise.c new file mode 100644 index 0000000..7fa8fcc --- /dev/null +++ b/libgamma_w32_gdi_site_initialise.c @@ -0,0 +1,23 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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. Once 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_w32_gdi_site_initialise(libgamma_site_state_t *restrict this, char* restrict site) +{ + this->partitions_available = 1; + return !site ? 0 : LIBGAMMA_NO_SUCH_SITE; +} diff --git a/libgamma_w32_gdi_site_restore.c b/libgamma_w32_gdi_site_restore.c new file mode 100644 index 0000000..dd688f0 --- /dev/null +++ b/libgamma_w32_gdi_site_restore.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_w32_gdi_site_restore(libgamma_site_state_t *restrict this) +{ + (void) this; + errno = ENOTSUP; + return LIBGAMMA_ERRNO_SET; +} diff --git a/libgamma_x_randr_crtc_destroy.c b/libgamma_x_randr_crtc_destroy.c new file mode 100644 index 0000000..476aeaa --- /dev/null +++ b/libgamma_x_randr_crtc_destroy.c @@ -0,0 +1,15 @@ +/* See LICENSE file for copyright and license details. */ +#define IN_LIBGAMMA_X_RANDR +#include "common.h" + + +/** + * Release all resources held by a CRTC state + * + * @param this The CRTC state + */ +void +libgamma_x_randr_crtc_destroy(libgamma_crtc_state_t *restrict this) +{ + (void) this; +} diff --git a/libgamma_x_randr_crtc_get_gamma_ramps16.c b/libgamma_x_randr_crtc_get_gamma_ramps16.c new file mode 100644 index 0000000..5e6ad5d --- /dev/null +++ b/libgamma_x_randr_crtc_get_gamma_ramps16.c @@ -0,0 +1,50 @@ +/* See LICENSE file for copyright and license details. */ +#define IN_LIBGAMMA_X_RANDR +#include "common.h" + + +/** + * Get the current 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_x_randr_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps16_t *restrict ramps) +{ + xcb_connection_t *restrict connection = this->partition->site->data; + xcb_randr_get_crtc_gamma_cookie_t cookie; + xcb_randr_get_crtc_gamma_reply_t *restrict reply; + xcb_generic_error_t *error; + uint16_t *restrict red; + uint16_t *restrict green; + uint16_t *restrict blue; + +#ifdef DEBUG + /* Gamma ramp sizes are identical but not fixed */ + if (ramps->red_size != ramps->green_size || ramps->red_size != ramps->blue_size) + return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; +#endif + + /* Read current gamma ramps */ + cookie = xcb_randr_get_crtc_gamma(connection, *(xcb_randr_crtc_t *)this->data); + reply = xcb_randr_get_crtc_gamma_reply(connection, cookie, &error); + + /* Check for errors */ + if (error) + return libgamma_x_randr_internal_translate_error(error->error_code, LIBGAMMA_GAMMA_RAMP_READ_FAILED, 0); + + /* Get current gamma ramps from response */ + red = xcb_randr_get_crtc_gamma_red(reply); + green = xcb_randr_get_crtc_gamma_green(reply); + blue = xcb_randr_get_crtc_gamma_blue(reply); + /* Copy over the gamma ramps to our memory */ + memcpy(ramps->red, red, ramps->red_size * sizeof(uint16_t)); + memcpy(ramps->green, green, ramps->green_size * sizeof(uint16_t)); + memcpy(ramps->blue, blue, ramps->blue_size * sizeof(uint16_t)); + + free(reply); + return 0; +} diff --git a/libgamma_x_randr_crtc_initialise.c b/libgamma_x_randr_crtc_initialise.c new file mode 100644 index 0000000..808b2c2 --- /dev/null +++ b/libgamma_x_randr_crtc_initialise.c @@ -0,0 +1,23 @@ +/* See LICENSE file for copyright and license details. */ +#define IN_LIBGAMMA_X_RANDR +#include "common.h" + + +/** + * 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_x_randr_crtc_initialise(libgamma_crtc_state_t *restrict this, + libgamma_partition_state_t *restrict partition, size_t crtc) +{ + libgamma_x_randr_partition_data_t *restrict screen_data = partition->data; + xcb_randr_crtc_t *restrict crtc_ids = screen_data->crtcs; + this->data = crtc_ids + crtc; + return crtc < partition->crtcs_available ? 0 : LIBGAMMA_NO_SUCH_CRTC; +} diff --git a/libgamma_x_randr_crtc_restore.c b/libgamma_x_randr_crtc_restore.c new file mode 100644 index 0000000..c8eb9b9 --- /dev/null +++ b/libgamma_x_randr_crtc_restore.c @@ -0,0 +1,19 @@ +/* See LICENSE file for copyright and license details. */ +#define IN_LIBGAMMA_X_RANDR +#include "common.h" + + +/** + * 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_x_randr_crtc_restore(libgamma_crtc_state_t *restrict this) +{ + (void) this; + errno = ENOTSUP; + return LIBGAMMA_ERRNO_SET; +} diff --git a/libgamma_x_randr_crtc_set_gamma_ramps16.c b/libgamma_x_randr_crtc_set_gamma_ramps16.c new file mode 100644 index 0000000..5bb9bb3 --- /dev/null +++ b/libgamma_x_randr_crtc_set_gamma_ramps16.c @@ -0,0 +1,34 @@ +/* See LICENSE file for copyright and license details. */ +#define IN_LIBGAMMA_X_RANDR +#include "common.h" + + +/** + * 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_x_randr_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict this, const libgamma_gamma_ramps16_t *ramps) +{ + xcb_connection_t *restrict connection = this->partition->site->data; + xcb_void_cookie_t cookie; + xcb_generic_error_t *restrict error; +#ifdef DEBUG + /* Gamma ramp sizes are identical but not fixed */ + if (ramps->red_size != ramps->green_size || ramps->red_size != ramps->blue_size) + return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; +#endif + + /* Apply gamma ramps */ + cookie = xcb_randr_set_crtc_gamma_checked(connection, *(xcb_randr_crtc_t*)this->data, + (uint16_t)ramps->red_size, ramps->red, ramps->green, ramps->blue); + /* Check for errors */ + error = xcb_request_check(connection, cookie); + if (error) + return libgamma_x_randr_internal_translate_error(error->error_code, LIBGAMMA_GAMMA_RAMP_WRITE_FAILED, 0); + return 0; +} diff --git a/libgamma_x_randr_get_crtc_information.c b/libgamma_x_randr_get_crtc_information.c new file mode 100644 index 0000000..29abd8b --- /dev/null +++ b/libgamma_x_randr_get_crtc_information.c @@ -0,0 +1,400 @@ +/* See LICENSE file for copyright and license details. */ +#define IN_LIBGAMMA_X_RANDR +#include "common.h" + + +/** + * Get the gamma ramp size of 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 Non-zero on error + */ +static int +get_gamma_ramp_size(libgamma_crtc_information_t *restrict out, libgamma_crtc_state_t *restrict crtc) +{ + xcb_connection_t *restrict connection = crtc->partition->site->data; + xcb_randr_crtc_t *restrict crtc_id = crtc->data; + xcb_randr_get_crtc_gamma_size_cookie_t cookie; + xcb_randr_get_crtc_gamma_size_reply_t *restrict reply; + xcb_generic_error_t *error; + + /* Query gamma ramp size */ + out->gamma_size_error = 0; + cookie = xcb_randr_get_crtc_gamma_size(connection, *crtc_id); + reply = xcb_randr_get_crtc_gamma_size_reply(connection, cookie, &error); + if (error) { + out->gamma_size_error = libgamma_x_randr_internal_translate_error(error->error_code, + LIBGAMMA_GAMMA_RAMPS_SIZE_QUERY_FAILED, 1); + return out->gamma_size_error; + } + /* Sanity check gamma ramp size */ + if (reply->size < 2) + out->gamma_size_error = LIBGAMMA_SINGLETON_GAMMA_RAMP; + /* Store gamma ramp size */ + out->red_gamma_size = out->green_gamma_size = out->blue_gamma_size = reply->size; + /* Release resources and return successfulnes */ + free(reply); + return out->gamma_size_error; +} + + +/** + * Read information from the CRTC's output + * + * @param out Instance of a data structure to fill with the information about the CRTC + * @param output The CRTC's output information + * @return Non-zero if at least on error occured + */ +static int +read_output_data(libgamma_crtc_information_t *restrict out, xcb_randr_get_output_info_reply_t *restrict output) +{ + switch (output->connection) { + case XCB_RANDR_CONNECTION_CONNECTED: + /* We have a monitor connected, report that and store information that is provided to us */ + out->active = 1; + out->width_mm = output->mm_width; + out->height_mm = output->mm_height; + switch (output->subpixel_order) { +#define X(CONST, NAME, RENDER_SUFFIX)\ + case XCB_RENDER_SUB_PIXEL_##RENDER_SUFFIX:\ + out->subpixel_order = CONST;\ + break; + LIST_SUBPIXEL_ORDERS(X) +#undef X + default: + out->subpixel_order_error = LIBGAMMA_SUBPIXEL_ORDER_NOT_RECOGNISED; + break; + } + return 0; + + case XCB_RANDR_CONNECTION_UNKNOWN: + /* If we do know whether a monitor is connected report that and assume it is not */ + out->active_error = LIBGAMMA_STATE_UNKNOWN; + /* fall through */ + default: + /* If no monitor is connected, report that on fails that require it */ + out->width_mm_error = LIBGAMMA_NOT_CONNECTED; + out->height_mm_error = LIBGAMMA_NOT_CONNECTED; + out->subpixel_order_error = LIBGAMMA_NOT_CONNECTED; + /* And store that we are not connected */ + out->active = 0; + /* This fuction only failed if we could not figure out whether a monitor is connected */ + return output->connection != XCB_RANDR_CONNECTION_UNKNOWN ? 0 : -1; + } +} + + +/** + * Determine the connector type from the connector name + * + * @param this The CRTC information to use and extend + * @param Non-zero on error + */ +static int +get_connector_type(libgamma_crtc_information_t *restrict this) +{ + /* Since we require the name of the output of get the type of the connected, + copy any reported error on the output's name to the connector's type, + and report failure if there was an error */ + if ((this->connector_type_error = this->connector_name_error)) + return -1; + +#define __select(name, type)\ + do {\ + if (strstr(this->connector_name, name "-") == this->connector_name) {\ + this->connector_type = LIBGAMMA_CONNECTOR_TYPE_##type;\ + return 0;\ + }\ + } while (0) + + /* Check begin on the name of the output to find out what type the connector is of */ + __select ("None", Unknown); + __select ("VGA", VGA); + __select ("DVI-I", DVII); + __select ("DVI-D", DVID); + __select ("DVI-A", DVIA); + __select ("DVI", DVI); + __select ("Composite", Composite); + __select ("S-Video", SVIDEO); + __select ("Component", Component); + __select ("LFP", LFP); + __select ("Proprietary", Unknown); + __select ("HDMI", HDMI); + __select ("DisplayPort", DisplayPort); + +#undef __select + + /* If there was no matching output name pattern report that and exit with an error */ + this->connector_name_error = LIBGAMMA_CONNECTOR_TYPE_NOT_RECOGNISED; + return -1; +} + + +/** + * Get the output name of a CRTC + * + * @param this Instance of a data structure to fill with the information about the CRTC + * @param output The CRTC's output's information + * @return Non-zero on error + */ +static int +get_output_name(libgamma_crtc_information_t *restrict out, xcb_randr_get_output_info_reply_t *restrict output) +{ + char *restrict store; + uint8_t *restrict name; + uint16_t length; + size_t i; + + /* Get the name of the output and the length of that name */ + name = xcb_randr_get_output_info_name(output); + length = output->name_len; /* There is no NUL-termination */ + if (!name) + return out->connector_name_error = LIBGAMMA_REPLY_VALUE_EXTRACTION_FAILED; + + /* Allocate a memory area for a NUL-terminated copy of the name */ + store = out->connector_name = malloc(((size_t)length + 1) * sizeof(char)); + if (!store) { + out->connector_name_error = errno; + return -1; + } + + /* char is guaranteed to be (u)int_least8_t, but it is only guaranteed to be (u)int8_t + * on POSIX, so to be truly portable we will not assume that char is (u)int8_t */ + for (i = 0; i < (size_t)length; i++) + store[i] = (char)name[i]; + store[length] = '\0'; + + return 0; +} + + +/** + * Get the Extended Display Information Data of the monitor connected to the connector of 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 + * @param output The CRTC's output + * @return Non-zero on error + */ +static int +get_edid(libgamma_crtc_information_t *restrict out, libgamma_crtc_state_t *restrict crtc, xcb_randr_output_t output) +{ + xcb_connection_t *restrict connection = crtc->partition->site->data; + xcb_randr_list_output_properties_cookie_t prop_cookie; + xcb_randr_list_output_properties_reply_t *restrict prop_reply; + xcb_atom_t *atoms; + xcb_atom_t *atoms_end; + xcb_generic_error_t *error; + xcb_get_atom_name_cookie_t atom_name_cookie; + xcb_get_atom_name_reply_t *restrict atom_name_reply; + char *restrict atom_name; + int atom_name_len; + xcb_randr_get_output_property_cookie_t atom_cookie; + xcb_randr_get_output_property_reply_t *restrict atom_reply; + unsigned char* restrict atom_data; + int length; + + /* Acquire a list of all properties of the output */ + prop_cookie = xcb_randr_list_output_properties(connection, output); + prop_reply = xcb_randr_list_output_properties_reply(connection, prop_cookie, &error); + if (error) + return out->edid_error = libgamma_x_randr_internal_translate_error(error->error_code, LIBGAMMA_LIST_PROPERTIES_FAILED, 1); + + /* Extract the properties form the data structure that holds them, */ + atoms = xcb_randr_list_output_properties_atoms(prop_reply); + /* and get the last one so that we can iterate over them nicely */ + atoms_end = atoms + xcb_randr_list_output_properties_atoms_length(prop_reply); + + if (!atoms) { + free(prop_reply); + return out->edid_error = LIBGAMMA_REPLY_VALUE_EXTRACTION_FAILED; + } + + /* For each property */ + for (; atoms != atoms_end; atoms++) { + /* Acquire the atom name */ + atom_name_cookie = xcb_get_atom_name(connection, *atoms); + atom_name_reply = xcb_get_atom_name_reply(connection, atom_name_cookie, &error); + if (error) + continue; + + /* Extract the atom name from the data structure that holds it */ + atom_name = xcb_get_atom_name_name(atom_name_reply); + /* As well as the length of the name; it is not NUL-termianted */ + atom_name_len = xcb_get_atom_name_name_length(atom_name_reply); + + if (/* Check for errors */ + !atom_name || /* atom_name_len < 1 || */ + /* Check that the length is the expected length for the EDID property */ + atom_name_len != 4 || + /* Check that the property is the EDID property */ + atom_name[0] != 'E' || atom_name[1] != 'D' || atom_name[2] != 'I' || atom_name[3] != 'D') { + free(atom_name_reply); + continue; + } + + /* Acquire the property's value, we know that it is either 128 or 256 byte long */ + atom_cookie = xcb_randr_get_output_property(connection, output, *atoms, XCB_GET_PROPERTY_TYPE_ANY, 0, 256, 0, 0); + atom_reply = xcb_randr_get_output_property_reply(connection, atom_cookie, &error); + /* (*) EDID version 1.0 through 1.4 define it as 128 bytes long, + * but version 2.0 define it as 256 bytes long. However, + * version 2.0 is rare(?) and has been deprecated and replaced + * by version 1.3 (I guess that is with a new version epoch, + * but I do not know.) */ + if (error) { + free(atom_name_reply); + free(prop_reply); + return out->edid_error = LIBGAMMA_PROPERTY_VALUE_QUERY_FAILED; + } + + /* Extract the property's value */ + atom_data = xcb_randr_get_output_property_data(atom_reply); + /* and its actual length */ + length = xcb_randr_get_output_property_data_length(atom_reply); + if (!atom_data || length < 1) { + free(atom_reply); + free(atom_name_reply); + free(prop_reply); + return out->edid_error = LIBGAMMA_REPLY_VALUE_EXTRACTION_FAILED; + } + + /* Store the EDID */ + out->edid_length = (size_t)length; + out->edid = malloc((size_t)length * sizeof(unsigned char)); + if (!out->edid) + out->edid_error = errno; + else + memcpy(out->edid, atom_data, (size_t)length * sizeof(unsigned char)); + + /* Release resouces */ + free(atom_reply); + free(atom_name_reply); + free(prop_reply); + + return out->edid_error; + } + + 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_x_randr_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; + xcb_randr_get_output_info_reply_t *restrict output_info = NULL; + xcb_randr_output_t output; + int free_edid, free_name; + xcb_connection_t *restrict connection; + libgamma_x_randr_partition_data_t *restrict screen_data; + size_t output_index; + xcb_randr_get_output_info_cookie_t cookie; + xcb_generic_error_t *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); + + /* We need to free the output's name after us if it is not explicitly requested */ + free_name = !(fields & LIBGAMMA_CRTC_INFO_CONNECTOR_NAME); + + /* Jump if the output information is not required */ + if (!(fields & (LIBGAMMA_CRTC_INFO_MACRO_ACTIVE | LIBGAMMA_CRTC_INFO_MACRO_CONNECTOR))) + goto cont; + + /* Get connector and connector information */ + connection = crtc->partition->site->data; + screen_data = crtc->partition->data; + output_index = screen_data->crtc_to_output[crtc->crtc]; + /* `SIZE_MAX` is used for CRTC:s that misses mapping to its output (should not happen), + * because `SIZE_MAX - 1` is the highest theoretical possible value */ + if (output_index == SIZE_MAX) { + e |= this->edid_error = this->gamma_error = this->width_mm_edid_error + = this->height_mm_edid_error = this->connector_type_error + = this->connector_name_error = this->subpixel_order_error + = this->width_mm_error = this->height_mm_error + = this->active_error = LIBGAMMA_CONNECTOR_UNKNOWN; + goto cont; + } + /* Get the output */ + output = screen_data->outputs[output_index]; + /* Query output information */ + cookie = xcb_randr_get_output_info(connection, output, screen_data->config_timestamp); + output_info = xcb_randr_get_output_info_reply(connection, cookie, &error); + if (error) { + e |= this->edid_error = this->gamma_error = this->width_mm_edid_error + = this->height_mm_edid_error = this->connector_type_error + = this->connector_name_error = this->subpixel_order_error + = this->width_mm_error = this->height_mm_error + = this->active_error = LIBGAMMA_OUTPUT_INFORMATION_QUERY_FAILED; + goto cont; + } + + /* Get connector name */ + e |= get_output_name(this, output_info); + /* Get connector type */ + if (fields & LIBGAMMA_CRTC_INFO_CONNECTOR_TYPE) + e |= get_connector_type(this); + /* Get additional output data, excluding EDID */ + e |= read_output_data(this, output_info); + if (fields & LIBGAMMA_CRTC_INFO_MACRO_VIEWPORT) + e |= this->width_mm_error | this->height_mm_error; + e |= (fields & LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER) ? this->subpixel_order_error : 0; + + /* If we do not want any EDID information, jump */ + if (!(fields & LIBGAMMA_CRTC_INFO_MACRO_EDID)) + goto cont; + /* If there is not monitor that report error in EDID related fields */ + if (!this->active) { + e |= this->edid_error = this->gamma_error = this->width_mm_edid_error + = this->height_mm_edid_error = LIBGAMMA_NOT_CONNECTED; + goto cont; + } + /* Get EDID */ + e |= get_edid(this, crtc, output); + if (!this->edid) { + this->gamma_error = this->width_mm_edid_error = this->height_mm_edid_error = this->edid_error; + goto cont; + } + /* Parse EDID */ + if ((fields & (LIBGAMMA_CRTC_INFO_MACRO_EDID ^ LIBGAMMA_CRTC_INFO_EDID))) + e |= libgamma_internal_parse_edid(this, fields); + +cont: + /* Get gamma ramp size */ + e |= (fields & LIBGAMMA_CRTC_INFO_GAMMA_SIZE) ? get_gamma_ramp_size(this, crtc) : 0; + /* Store gamma ramp depth. */ + this->gamma_depth = 16; + /* X RandR does not support quering gamma ramp support. */ + 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; + } + /* Free the output name after us */ + if (free_name) { + free(this->connector_name); + this->connector_name = NULL; + } + + free(output_info); + return e ? -1 : 0; + +#undef _E +} diff --git a/libgamma_x_randr_internal_translate_error.c b/libgamma_x_randr_internal_translate_error.c new file mode 100644 index 0000000..7752c03 --- /dev/null +++ b/libgamma_x_randr_internal_translate_error.c @@ -0,0 +1,31 @@ +/* See LICENSE file for copyright and license details. */ +#define IN_LIBGAMMA_X_RANDR +#include "common.h" + + +/** + * Translate an xcb error into a libgamma error + * + * @param error_code The xcb error + * @param default_error The libgamma error to use if the xcb error is not recognised + * @param return_errno Whether an `errno` value may be returned + * @return The libgamma error + */ +int +libgamma_x_randr_internal_translate_error(int error_code, int default_error, int return_errno) +{ + int r = LIBGAMMA_ERRNO_SET; + switch (error_code) { + case XCB_CONN_ERROR: errno = ECONNABORTED; break; + case XCB_CONN_CLOSED_EXT_NOTSUPPORTED: errno = ENOPROTOOPT; break; + case XCB_CONN_CLOSED_MEM_INSUFFICIENT: errno = ENOMEM; break; + case XCB_CONN_CLOSED_REQ_LEN_EXCEED: errno = EMSGSIZE; break; + case XCB_CONN_CLOSED_PARSE_ERR: r = LIBGAMMA_NO_SUCH_SITE; break; + case XCB_CONN_CLOSED_INVALID_SCREEN: r = LIBGAMMA_NO_SUCH_PARTITION; break; + case XCB_CONN_CLOSED_FDPASSING_FAILED: errno = EIO; break; + default: + r = default_error; + break; + } + return (return_errno && r > 0) ? errno : r; +} diff --git a/libgamma_x_randr_method_capabilities.c b/libgamma_x_randr_method_capabilities.c new file mode 100644 index 0000000..4371ecc --- /dev/null +++ b/libgamma_x_randr_method_capabilities.c @@ -0,0 +1,43 @@ +/* See LICENSE file for copyright and license details. */ +#define IN_LIBGAMMA_X_RANDR +#include "common.h" + + +/** + * Return the capabilities of the adjustment method + * + * @param this The data structure to fill with the method's capabilities + */ +void +libgamma_x_randr_method_capabilities(libgamma_method_capabilities_t *restrict this) +{ + char *display = getenv("DISPLAY"); + /* Support for all information except active status and gamma ramp support. + Active status can be queried but it is not guaranteed produces an up to date result. */ + this->crtc_information = LIBGAMMA_CRTC_INFO_MACRO_EDID + | LIBGAMMA_CRTC_INFO_MACRO_VIEWPORT + | LIBGAMMA_CRTC_INFO_MACRO_RAMP + | LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER + | LIBGAMMA_CRTC_INFO_MACRO_CONNECTOR; + /* X RandR supports multiple sites, partitions and CRTC:s */ + this->default_site_known = display && *display; + this->multiple_sites = 1; + this->multiple_partitions = 1; + this->multiple_crtcs = 1; + /* Partitions are screens and not graphics cards in X */ + this->partitions_are_graphics_cards = 0; + /* X does not have system restore capabilities */ + this->site_restore = 0; + this->partition_restore = 0; + this->crtc_restore = 0; + /* Gamma ramp sizes are identical but not fixed */ + this->identical_gamma_sizes = 1; + this->fixed_gamma_size = 0; + /* Gamma ramp depths are fixed */ + this->fixed_gamma_depth = 1; + /* X RandR is a real non-faked adjustment method */ + this->real = 1; + this->fake = 0; + /* Gamma ramp adjustments are persistent */ + this->auto_restore = 0; +} diff --git a/libgamma_x_randr_partition_destroy.c b/libgamma_x_randr_partition_destroy.c new file mode 100644 index 0000000..a48a02d --- /dev/null +++ b/libgamma_x_randr_partition_destroy.c @@ -0,0 +1,19 @@ +/* See LICENSE file for copyright and license details. */ +#define IN_LIBGAMMA_X_RANDR +#include "common.h" + + +/** + * Release all resources held by a partition state + * + * @param this The partition state + */ +void +libgamma_x_randr_partition_destroy(libgamma_partition_state_t *restrict this) +{ + libgamma_x_randr_partition_data_t *restrict data = this->data; + free(data->crtcs); + free(data->outputs); + free(data->crtc_to_output); + free(data); +} diff --git a/libgamma_x_randr_partition_initialise.c b/libgamma_x_randr_partition_initialise.c new file mode 100644 index 0000000..aa5df50 --- /dev/null +++ b/libgamma_x_randr_partition_initialise.c @@ -0,0 +1,161 @@ +/* See LICENSE file for copyright and license details. */ +#define IN_LIBGAMMA_X_RANDR +#include "common.h" + + +/** + * Duplicate a memory area + * + * @param ptr The memory area + * @param bytes The size, in bytes, of the memory area + * @return A duplication of the memory, `NULL` if zero-length or on error + */ +static inline void * +xmemdup(void *restrict ptr, size_t bytes) +{ + char *restrict rc; + if (!bytes) + return NULL; + rc = malloc(bytes); + if (!rc) + return NULL; + memcpy(rc, ptr, bytes); + return rc; +} + + +/** + * 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_x_randr_partition_initialise(libgamma_partition_state_t *restrict this, + libgamma_site_state_t *restrict site, size_t partition) +{ + int fail_rc = LIBGAMMA_ERRNO_SET; + xcb_connection_t *restrict connection = site->data; + xcb_screen_t *restrict screen = NULL; + xcb_generic_error_t *error = NULL; + const xcb_setup_t *restrict setup; + xcb_screen_iterator_t iter; + xcb_randr_get_screen_resources_current_cookie_t cookie; + xcb_randr_get_screen_resources_current_reply_t *restrict reply; + xcb_randr_crtc_t *restrict crtcs; + xcb_randr_output_t *restrict outputs; + libgamma_x_randr_partition_data_t *restrict data; + xcb_randr_get_output_info_cookie_t out_cookie; + xcb_randr_get_output_info_reply_t *out_reply; + size_t i; + uint16_t j; + + /* Get screen list */ + setup = xcb_get_setup(connection); + if (!setup) + return LIBGAMMA_LIST_PARTITIONS_FAILED; + iter = xcb_setup_roots_iterator(setup); + + /* Get the screen */ + for (i = 0; iter.rem > 0; i++, xcb_screen_next(&iter)) + if (i == partition) { + screen = iter.data; + break; + } + /* Report failure if we did not find the screen */ + if (!iter.rem) + return LIBGAMMA_NO_SUCH_PARTITION; + + /* Check that the screen is not `NULL`. + * (Do not think this can happen, but why not.) */ + if (!screen) + return LIBGAMMA_NULL_PARTITION; + + /* Get the current resources of the screen */ + cookie = xcb_randr_get_screen_resources_current(connection, screen->root); + reply = xcb_randr_get_screen_resources_current_reply(connection, cookie, &error); + if (error) + return libgamma_x_randr_internal_translate_error(error->error_code, LIBGAMMA_LIST_CRTCS_FAILED, 0); + + /* Get the number of available CRTC:s */ + this->crtcs_available = reply->num_crtcs; + /* Get the CRTC and output lists */ + crtcs = xcb_randr_get_screen_resources_current_crtcs(reply); + outputs = xcb_randr_get_screen_resources_current_outputs(reply); + if (!crtcs || !outputs) { + free(reply); + return LIBGAMMA_REPLY_VALUE_EXTRACTION_FAILED; + } + + /* Allocate adjustment method dependent data memory area. + We use `calloc` because we want `data`'s pointers to be `NULL` if not allocated at `fail`. */ + data = calloc(1, sizeof(libgamma_x_randr_partition_data_t)); + if (!data) + goto fail; + + /* Copy the CRTC:s, just so we do not have to keep the reply in memory */ + data->crtcs = xmemdup(crtcs, (size_t)(reply->num_crtcs) * sizeof(xcb_randr_crtc_t)); + if (!data->crtcs && reply->num_crtcs > 0) + goto fail; + + /* Copy the outputs as well */ + data->outputs = xmemdup(outputs, (size_t)reply->num_outputs * sizeof(xcb_randr_output_t)); + if (!data->outputs && reply->num_outputs > 0) + goto fail; + + /* Get the number of available outputs */ + data->outputs_count = (size_t)reply->num_outputs; + + /* Create mapping table from CRTC indices to output indicies. (injection) */ + data->crtc_to_output = malloc((size_t)reply->num_crtcs * sizeof(size_t)); + if (!data->crtc_to_output) + goto fail; + /* All CRTC:s should be mapped, but incase they are not, all unmapped CRTC:s should have + an invalid target, namely `SIZE_MAX`, which is 1 more than the theoretical limit */ + for (i = 0; i < (size_t)reply->num_crtcs; i++) + data->crtc_to_output[i] = SIZE_MAX; + /* Fill the table */ + for (i = 0; i < (size_t)reply->num_outputs; i++) { + /* Query output (target) information */ + out_cookie = xcb_randr_get_output_info(connection, outputs[i], reply->config_timestamp); + out_reply = xcb_randr_get_output_info_reply(connection, out_cookie, &error); + if (error) { + fail_rc = libgamma_x_randr_internal_translate_error(error->error_code, + LIBGAMMA_OUTPUT_INFORMATION_QUERY_FAILED, 0); + goto fail; + } + + /* Find CRTC (source) */ + for (j = 0; j < reply->num_crtcs; j++) { + if (crtcs[j] == out_reply->crtc) { + data->crtc_to_output[j] = i; + break; + } + } + + /* Release output information */ + free(out_reply); + } + + /* Store the configuration timestamp */ + data->config_timestamp = reply->config_timestamp; + /* Store the adjustment method dependent data */ + this->data = data; + /* Release resources and return successfully */ + free(reply); + return 0; + +fail: + /* Release resources and return with an error */ + if (data) { + free(data->crtcs); + free(data->outputs); + free(data->crtc_to_output); + free(data); + } + free(reply); + return fail_rc; +} diff --git a/libgamma_x_randr_partition_restore.c b/libgamma_x_randr_partition_restore.c new file mode 100644 index 0000000..ebe16c9 --- /dev/null +++ b/libgamma_x_randr_partition_restore.c @@ -0,0 +1,19 @@ +/* See LICENSE file for copyright and license details. */ +#define IN_LIBGAMMA_X_RANDR +#include "common.h" + + +/** + * 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_x_randr_partition_restore(libgamma_partition_state_t *restrict this) +{ + (void) this; + errno = ENOTSUP; + return LIBGAMMA_ERRNO_SET; +} diff --git a/libgamma_x_randr_site_destroy.c b/libgamma_x_randr_site_destroy.c new file mode 100644 index 0000000..ba4d836 --- /dev/null +++ b/libgamma_x_randr_site_destroy.c @@ -0,0 +1,15 @@ +/* See LICENSE file for copyright and license details. */ +#define IN_LIBGAMMA_X_RANDR +#include "common.h" + + +/** + * Release all resources held by a site state + * + * @param this The site state + */ +void +libgamma_x_randr_site_destroy(libgamma_site_state_t *restrict this) +{ + xcb_disconnect((xcb_connection_t *)this->data); +} diff --git a/libgamma_x_randr_site_initialise.c b/libgamma_x_randr_site_initialise.c new file mode 100644 index 0000000..61c011b --- /dev/null +++ b/libgamma_x_randr_site_initialise.c @@ -0,0 +1,82 @@ +/* See LICENSE file for copyright and license details. */ +#define IN_LIBGAMMA_X_RANDR +#include "common.h" + + +/** + * 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. Once 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_x_randr_site_initialise(libgamma_site_state_t *restrict this, char *restrict site) +{ + xcb_generic_error_t *error = NULL; + xcb_connection_t *restrict connection; + xcb_randr_query_version_cookie_t cookie; + xcb_randr_query_version_reply_t *restrict reply; + const xcb_setup_t *restrict setup; + xcb_screen_iterator_t iter; + + /* Connect to the display server */ + this->data = connection = xcb_connect(site, NULL); + if (!connection || xcb_connection_has_error(connection)) + return LIBGAMMA_OPEN_SITE_FAILED; + + /* Query the version of the X RandR extension protocol */ + cookie = xcb_randr_query_version(connection, RANDR_VERSION_MAJOR, RANDR_VERSION_MINOR); + reply = xcb_randr_query_version_reply(connection, cookie, &error); + + /* Check for version query failure */ + if (error || !reply) { + /* Release resources */ + free(reply); + /* If `xcb_connect` failed, both `error` and `reply` will be `NULL`. + * TODO: Can both be `NULL` for any other reason? */ + if (!error && !reply) + return LIBGAMMA_OPEN_SITE_FAILED; + xcb_disconnect(connection); + /* Translate and report error. */ + if (error != NULL) + return libgamma_x_randr_internal_translate_error(error->error_code, LIBGAMMA_PROTOCOL_VERSION_QUERY_FAILED, 0); + return LIBGAMMA_PROTOCOL_VERSION_QUERY_FAILED; + } + + /* Check protocol compatibility, + we require 1.3 but 2.x may not be backwards compatible */ + if (reply->major_version != RANDR_VERSION_MAJOR || reply->minor_version < RANDR_VERSION_MINOR) { +#ifdef DEBUG + /* Print used protocol */ + fprintf(stderr, "libgamma: RandR protocol version: %u.%u", reply->major_version, reply->minor_version); +#endif + /* Release resources */ + free(reply); + xcb_disconnect(connection); + /* Report error */ + return LIBGAMMA_PROTOCOL_VERSION_NOT_SUPPORTED; + } + + /* We do not longer need to know the version of the protocol */ + free(reply); + + /* Get available screens */ + setup = xcb_get_setup(connection); + if (!setup) { + xcb_disconnect(connection); + return LIBGAMMA_LIST_PARTITIONS_FAILED; + } + iter = xcb_setup_roots_iterator(setup); + /* Get the number of available screens */ + this->partitions_available = (size_t)iter.rem; + + /* Sanity check the number of available screens. */ + return iter.rem >= 0 ? 0 : LIBGAMMA_NEGATIVE_PARTITION_COUNT; +} diff --git a/libgamma_x_randr_site_restore.c b/libgamma_x_randr_site_restore.c new file mode 100644 index 0000000..5cf5d07 --- /dev/null +++ b/libgamma_x_randr_site_restore.c @@ -0,0 +1,19 @@ +/* See LICENSE file for copyright and license details. */ +#define IN_LIBGAMMA_X_RANDR +#include "common.h" + + +/** + * 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_x_randr_site_restore(libgamma_site_state_t *restrict this) +{ + (void) this; + errno = ENOTSUP; + return LIBGAMMA_ERRNO_SET; +} diff --git a/libgamma_x_vidmode_crtc_destroy.c b/libgamma_x_vidmode_crtc_destroy.c new file mode 100644 index 0000000..4fe5d92 --- /dev/null +++ b/libgamma_x_vidmode_crtc_destroy.c @@ -0,0 +1,14 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Release all resources held by a CRTC state + * + * @param this The CRTC state + */ +void +libgamma_x_vidmode_crtc_destroy(libgamma_crtc_state_t *restrict this) +{ + (void) this; +} diff --git a/libgamma_x_vidmode_crtc_get_gamma_ramps16.c b/libgamma_x_vidmode_crtc_get_gamma_ramps16.c new file mode 100644 index 0000000..993e126 --- /dev/null +++ b/libgamma_x_vidmode_crtc_get_gamma_ramps16.c @@ -0,0 +1,26 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Get the current 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_x_vidmode_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict this, libgamma_gamma_ramps16_t *restrict ramps) +{ +#ifdef DEBUG + /* Gamma ramp sizes are identical but not fixed */ + if (ramps->red_size != ramps->green_size || ramps->red_size != ramps->blue_size) + return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; +#endif + /* Read current gamma ramps */ + if (!XF86VidModeGetGammaRamp((Display *)this->partition->site->data, (int)this->partition->partition, + (int)ramps->red_size, ramps->red, ramps->green, ramps->blue)) + return LIBGAMMA_GAMMA_RAMP_READ_FAILED; + return 0; +} diff --git a/libgamma_x_vidmode_crtc_initialise.c b/libgamma_x_vidmode_crtc_initialise.c new file mode 100644 index 0000000..ca36a6d --- /dev/null +++ b/libgamma_x_vidmode_crtc_initialise.c @@ -0,0 +1,21 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_x_vidmode_crtc_initialise(libgamma_crtc_state_t *restrict this, + libgamma_partition_state_t *restrict partition, size_t crtc) +{ + (void) this; + (void) partition; + return !crtc ? 0 : LIBGAMMA_NO_SUCH_CRTC; +} diff --git a/libgamma_x_vidmode_crtc_restore.c b/libgamma_x_vidmode_crtc_restore.c new file mode 100644 index 0000000..fb67351 --- /dev/null +++ b/libgamma_x_vidmode_crtc_restore.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_x_vidmode_crtc_restore(libgamma_crtc_state_t *restrict this) +{ + (void) this; + errno = ENOTSUP; + return LIBGAMMA_ERRNO_SET; +} diff --git a/libgamma_x_vidmode_crtc_set_gamma_ramps16.c b/libgamma_x_vidmode_crtc_set_gamma_ramps16.c new file mode 100644 index 0000000..6ad18fc --- /dev/null +++ b/libgamma_x_vidmode_crtc_set_gamma_ramps16.c @@ -0,0 +1,26 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_x_vidmode_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict this, const libgamma_gamma_ramps16_t *restrict ramps) +{ +#ifdef DEBUG + /* Gamma ramp sizes are identical but not fixed */ + if (ramps->red_size != ramps->green_size || ramps->red_size != ramps->blue_size) + return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; +#endif + /* Apply gamma ramps */ + if (!XF86VidModeSetGammaRamp((Display *)this->partition->site->data, (int)this->partition->partition, + (int)ramps->red_size, ramps->red, ramps->green, ramps->blue)) + return LIBGAMMA_GAMMA_RAMP_WRITE_FAILED; + return 0; +} diff --git a/libgamma_x_vidmode_get_crtc_information.c b/libgamma_x_vidmode_get_crtc_information.c new file mode 100644 index 0000000..8462b1b --- /dev/null +++ b/libgamma_x_vidmode_get_crtc_information.c @@ -0,0 +1,55 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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; oOn error refer to the error reports in `this` + */ +int +libgamma_x_vidmode_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) + + Display *restrict connection; + int stops = 0; + + /* X VidMode does not support EDID or monitor dimensions */ + this->edid_error = _E(LIBGAMMA_CRTC_INFO_EDID); + this->width_mm_error = _E(LIBGAMMA_CRTC_INFO_WIDTH_MM); + this->height_mm_error = _E(LIBGAMMA_CRTC_INFO_HEIGHT_MM); + this->width_mm_edid_error = _E(LIBGAMMA_CRTC_INFO_WIDTH_MM_EDID); + this->height_mm_edid_error = _E(LIBGAMMA_CRTC_INFO_HEIGHT_MM_EDID); + this->gamma_size_error = 0; + /* X VidMode does support gamma ramp size query. The gamma + ramps are identical but not fixed, and the query can fail. */ + if ((fields & LIBGAMMA_CRTC_INFO_GAMMA_SIZE)) { + connection = crtc->partition->site->data; + if (!XF86VidModeGetGammaRampSize(connection, (int)crtc->partition->partition, &stops)) + this->gamma_size_error = LIBGAMMA_GAMMA_RAMPS_SIZE_QUERY_FAILED; + else if (stops < 2) + this->gamma_size_error = LIBGAMMA_SINGLETON_GAMMA_RAMP; + this->red_gamma_size = this->green_gamma_size = this->blue_gamma_size = (size_t)stops; + } + /* X VidMode uses 16-bit integer ramps */ + this->gamma_depth = 16; + this->gamma_depth_error = 0; + /* X VidMode does not support gamma ramp support queries */ + this->gamma_support_error = _E(LIBGAMMA_CRTC_INFO_GAMMA_SUPPORT); + /* X VidMode does not support EDID or connector information */ + this->subpixel_order_error = _E(LIBGAMMA_CRTC_INFO_SUBPIXEL_ORDER); + this->active_error = _E(LIBGAMMA_CRTC_INFO_ACTIVE); + this->connector_name_error = _E(LIBGAMMA_CRTC_INFO_CONNECTOR_NAME); + this->connector_type_error = _E(LIBGAMMA_CRTC_INFO_CONNECTOR_TYPE); + this->gamma_error = _E(LIBGAMMA_CRTC_INFO_GAMMA); + + /* We failed if gamma ramp size query failed or if an unsupport field was queried. */ + return (this->gamma_size_error || (fields & ~(LIBGAMMA_CRTC_INFO_GAMMA_DEPTH | LIBGAMMA_CRTC_INFO_GAMMA_SIZE))) ? -1 : 0; + +#undef _E +} diff --git a/libgamma_x_vidmode_method_capabilities.c b/libgamma_x_vidmode_method_capabilities.c new file mode 100644 index 0000000..5ef885d --- /dev/null +++ b/libgamma_x_vidmode_method_capabilities.c @@ -0,0 +1,37 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Return the capabilities of the adjustment method + * + * @param this The data structure to fill with the method's capabilities + */ +void +libgamma_x_vidmode_method_capabilities(libgamma_method_capabilities_t *restrict this) +{ + char *restrict display = getenv("DISPLAY"); + /* Gamma ramps size and depth can be queried */ + this->crtc_information = LIBGAMMA_CRTC_INFO_GAMMA_SIZE | LIBGAMMA_CRTC_INFO_GAMMA_DEPTH; + /* X VidMode supports multiple sites and partitions but not CRTC:s */ + this->default_site_known = (display && *display) ? 1 : 0; + this->multiple_sites = 1; + this->multiple_partitions = 1; + this->multiple_crtcs = 0; + /* Partitions are screens and not graphics cards in X */ + this->partitions_are_graphics_cards = 0; + /* X does not have system restore capabilities */ + this->site_restore = 0; + this->partition_restore = 0; + this->crtc_restore = 0; + /* Gamma ramp sizes are identical but not fixed */ + this->identical_gamma_sizes = 1; + this->fixed_gamma_size = 0; + /* Gamma ramp depths are fixed */ + this->fixed_gamma_depth = 1; + /* X VidMode is a real non-faked adjustment method */ + this->real = 1; + this->fake = 0; + /* Gamma ramp adjustments are persistent */ + this->auto_restore = 0; +} diff --git a/libgamma_x_vidmode_partition_destroy.c b/libgamma_x_vidmode_partition_destroy.c new file mode 100644 index 0000000..708d67f --- /dev/null +++ b/libgamma_x_vidmode_partition_destroy.c @@ -0,0 +1,14 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Release all resources held by a partition state + * + * @param this The partition state + */ +void +libgamma_x_vidmode_partition_destroy(libgamma_partition_state_t *restrict this) +{ + (void) this; +} diff --git a/libgamma_x_vidmode_partition_initialise.c b/libgamma_x_vidmode_partition_initialise.c new file mode 100644 index 0000000..829e822 --- /dev/null +++ b/libgamma_x_vidmode_partition_initialise.c @@ -0,0 +1,20 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_x_vidmode_partition_initialise(libgamma_partition_state_t *restrict this, + libgamma_site_state_t *restrict site, size_t partition) +{ + this->crtcs_available = 1; + return partition < site->partitions_available ? 0 : LIBGAMMA_NO_SUCH_PARTITION; +} diff --git a/libgamma_x_vidmode_partition_restore.c b/libgamma_x_vidmode_partition_restore.c new file mode 100644 index 0000000..35e6719 --- /dev/null +++ b/libgamma_x_vidmode_partition_restore.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_x_vidmode_partition_restore(libgamma_partition_state_t *restrict this) +{ + (void) this; + errno = ENOTSUP; + return LIBGAMMA_ERRNO_SET; +} diff --git a/libgamma_x_vidmode_site_destroy.c b/libgamma_x_vidmode_site_destroy.c new file mode 100644 index 0000000..378d336 --- /dev/null +++ b/libgamma_x_vidmode_site_destroy.c @@ -0,0 +1,14 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * Release all resources held by a site state + * + * @param this The site state + */ +void +libgamma_x_vidmode_site_destroy(libgamma_site_state_t *restrict this) +{ + XCloseDisplay((Display *)this->data); +} diff --git a/libgamma_x_vidmode_site_initialise.c b/libgamma_x_vidmode_site_initialise.c new file mode 100644 index 0000000..fd4fa55 --- /dev/null +++ b/libgamma_x_vidmode_site_initialise.c @@ -0,0 +1,40 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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. Once 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_x_vidmode_site_initialise(libgamma_site_state_t *restrict this, char *restrict site) +{ + /* Connect to the display */ + Display *restrict connection; + int _major, _minor, screens; + this->data = connection = XOpenDisplay(site); + if (!this->data) + return LIBGAMMA_OPEN_SITE_FAILED; + /* Query X VidMode extension protocol version */ + if (!XF86VidModeQueryVersion(connection, &_major, &_minor)) { + XCloseDisplay(connection); + return LIBGAMMA_PROTOCOL_VERSION_QUERY_FAILED; + } + /* Query the number of available screens */ + screens = ScreenCount(connection); + if (screens < 0) { + XCloseDisplay(connection); + return LIBGAMMA_NEGATIVE_PARTITION_COUNT; + } + this->partitions_available = (size_t)screens; + return 0; +} diff --git a/libgamma_x_vidmode_site_restore.c b/libgamma_x_vidmode_site_restore.c new file mode 100644 index 0000000..77e9034 --- /dev/null +++ b/libgamma_x_vidmode_site_restore.c @@ -0,0 +1,18 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +/** + * 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_x_vidmode_site_restore(libgamma_site_state_t *restrict this) +{ + (void) this; + errno = ENOTSUP; + return LIBGAMMA_ERRNO_SET; +} diff --git a/gamma-dummy.h b/method-dummy.h index 684934e..d6c5488 100644 --- a/gamma-dummy.h +++ b/method-dummy.h @@ -1,6 +1,188 @@ /* See LICENSE file for copyright and license details. */ -#ifndef LIBGAMMA_GAMMA_DUMMY_H -#define LIBGAMMA_GAMMA_DUMMY_H +#if !defined(LIBGAMMA_DUMMY_GET_RAMPS) && !defined(LIBGAMMA_DUMMY_SET_RAMPS) + + +/** + * Configuration set for the dummy adjustment method + */ +typedef struct libgamma_dummy_configurations { + /** + * The method's capabilities + * + * Some fields are ignored: + * - real + * - fake + */ + libgamma_method_capabilities_t capabilities; + + /** + * Template for CRTC:s information + * + * Some fields are ignored: + * - width_mm_edid + * - width_mm_edid_error + * - height_mm_edid + * - height_mm_edid_error + * - gamma_red + * - gamma_green + * - gamma_blue + * - gamma_error + */ + libgamma_crtc_information_t crtc_info_template; + + /** + * The adjustment method to use + */ + int real_method; + + /** + * The number of sites on the system + */ + size_t site_count; + + /** + * The number of paritions on a site before it has been configured + */ + size_t default_partition_count; + + /** + * The number of CRTC:s on a paritions before it has been configured + */ + size_t default_crtc_count; + + /** + * Whether the sites should be inherited from the real method + */ + unsigned inherit_sites : 1; + + /** + * Whether the partitions should be inherited from the real method + */ + unsigned inherit_partition_count : 1; + + /** + * Whether the CRTC:s should be inherited from the real method + */ + unsigned inherit_crtc_count : 1; + + /** + * When a site has been created, stall until the partition count has + * been configured + */ + unsigned stall_for_partition_count : 1; + + /** + * When a parition has been created, stall until the CRTC count has + * been configured + */ + unsigned stall_for_crtc_count : 1; + + /** + * Methods should stall until the system has been configured + * unless $LIBGAMMA_DUMMY_STALL is not true + */ + unsigned stalled_start : 1; + + /** + * Whether to print what is going on in the phony system + */ + unsigned verbose : 1; + +} libgamma_dummy_configurations_t; + + +/** + * Dummy adjustment method internal data for a CRTC + */ +typedef struct libgamma_dummy_crtc { + /** + * The gamma ramp for the red channel + */ + void *restrict gamma_red; + + /** + * The gamma ramp for the green channel + */ + void *restrict gamma_green; + + /** + * The gamma ramp for the blue channel + */ + void *restrict gamma_blue; + + /** + * Information about the CRTC and monitor + * + * Some fields are ignored: + * - width_mm_edid + * - width_mm_edid_error + * - height_mm_edid + * - height_mm_edid_error + * - gamma_red + * - gamma_green + * - gamma_blue + * - gamma_error + */ + libgamma_crtc_information_t info; + + /** + * Partition state that contains this information + */ + libgamma_crtc_state_t *state; + +} libgamma_dummy_crtc_t; + + +/** + * Dummy adjustment method internal data for a partition + */ +typedef struct libgamma_dummy_partition { + /** + * The CRTC:s on the system + */ + libgamma_dummy_crtc_t *crtcs; + + /** + * The number of CRTC:s on the system + */ + size_t crtc_count; + + /** + * Partition state that contains this information + */ + libgamma_partition_state_t *state; + +} libgamma_dummy_partition_t; + + +/** + * Dummy adjustment method internal data for a site + */ +typedef struct libgamma_dummy_site { + /** + * The partitions on the system + */ + libgamma_dummy_partition_t *partitions; + + /** + * The number of partitions on the system + */ + size_t partition_count; + + /** + * Site state that contains this information + */ + libgamma_site_state_t *state; + +} libgamma_dummy_site_t; + + + +/** + * Configurations for the dummy adjustment method + */ +extern libgamma_dummy_configurations_t libgamma_dummy_internal_configurations; + /** @@ -8,6 +190,7 @@ * * @param this The data structure to fill with the method's capabilities */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_dummy_method_capabilities(libgamma_method_capabilities_t *restrict); /** @@ -23,6 +206,7 @@ void libgamma_dummy_method_capabilities(libgamma_method_capabilities_t *restrict * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__(1), __warn_unused_result__))) int libgamma_dummy_site_initialise(libgamma_site_state_t *restrict, char *restrict); /** @@ -30,6 +214,7 @@ int libgamma_dummy_site_initialise(libgamma_site_state_t *restrict, char *restri * * @param this The site state */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_dummy_site_destroy(libgamma_site_state_t *restrict); /** @@ -39,6 +224,7 @@ void libgamma_dummy_site_destroy(libgamma_site_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_dummy_site_restore(libgamma_site_state_t *restrict); @@ -51,6 +237,7 @@ int libgamma_dummy_site_restore(libgamma_site_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_dummy_partition_initialise(libgamma_partition_state_t *restrict, libgamma_site_state_t *restrict, size_t); /** @@ -58,6 +245,7 @@ int libgamma_dummy_partition_initialise(libgamma_partition_state_t *restrict, li * * @param this The partition state */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_dummy_partition_destroy(libgamma_partition_state_t *restrict); /** @@ -67,6 +255,7 @@ void libgamma_dummy_partition_destroy(libgamma_partition_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_dummy_partition_restore(libgamma_partition_state_t *restrict); @@ -79,6 +268,7 @@ int libgamma_dummy_partition_restore(libgamma_partition_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_dummy_crtc_initialise(libgamma_crtc_state_t *restrict, libgamma_partition_state_t *restrict, size_t); /** @@ -86,6 +276,7 @@ int libgamma_dummy_crtc_initialise(libgamma_crtc_state_t *restrict, libgamma_par * * @param this The CRTC state */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_dummy_crtc_destroy(libgamma_crtc_state_t *restrict); /** @@ -95,6 +286,7 @@ void libgamma_dummy_crtc_destroy(libgamma_crtc_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_dummy_crtc_restore(libgamma_crtc_state_t *restrict); @@ -106,8 +298,10 @@ int libgamma_dummy_crtc_restore(libgamma_crtc_state_t *restrict); * @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` */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_dummy_get_crtc_information(libgamma_crtc_information_t *restrict, libgamma_crtc_state_t *restrict, int32_t); + /** * Get the current gamma ramps for a CRTC, 8-bit gamma-depth version * @@ -116,6 +310,7 @@ int libgamma_dummy_get_crtc_information(libgamma_crtc_information_t *restrict, l * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_dummy_crtc_get_gamma_ramps8(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps8_t *restrict); /** @@ -126,7 +321,8 @@ int libgamma_dummy_crtc_get_gamma_ramps8(libgamma_crtc_state_t *restrict, libgam * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -int libgamma_dummy_crtc_set_gamma_ramps8(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps8_t); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) +int libgamma_dummy_crtc_set_gamma_ramps8(libgamma_crtc_state_t *restrict, const libgamma_gamma_ramps8_t *restrict); /** @@ -137,6 +333,7 @@ int libgamma_dummy_crtc_set_gamma_ramps8(libgamma_crtc_state_t *restrict, libgam * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_dummy_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps16_t *restrict); /** @@ -147,7 +344,8 @@ int libgamma_dummy_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict, libga * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -int libgamma_dummy_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps16_t); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) +int libgamma_dummy_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict, const libgamma_gamma_ramps16_t *restrict); /** @@ -158,6 +356,7 @@ int libgamma_dummy_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict, libga * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_dummy_crtc_get_gamma_ramps32(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps32_t *restrict); /** @@ -168,7 +367,8 @@ int libgamma_dummy_crtc_get_gamma_ramps32(libgamma_crtc_state_t *restrict, libga * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -int libgamma_dummy_crtc_set_gamma_ramps32(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps32_t); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) +int libgamma_dummy_crtc_set_gamma_ramps32(libgamma_crtc_state_t *restrict, const libgamma_gamma_ramps32_t *restrict); /** @@ -179,6 +379,7 @@ int libgamma_dummy_crtc_set_gamma_ramps32(libgamma_crtc_state_t *restrict, libga * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_dummy_crtc_get_gamma_ramps64(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps64_t *restrict); /** @@ -189,7 +390,8 @@ int libgamma_dummy_crtc_get_gamma_ramps64(libgamma_crtc_state_t *restrict, libga * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -int libgamma_dummy_crtc_set_gamma_ramps64(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps64_t); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) +int libgamma_dummy_crtc_set_gamma_ramps64(libgamma_crtc_state_t *restrict, const libgamma_gamma_ramps64_t *restrict); /** @@ -200,6 +402,7 @@ int libgamma_dummy_crtc_set_gamma_ramps64(libgamma_crtc_state_t *restrict, libga * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_dummy_crtc_get_gamma_rampsf(libgamma_crtc_state_t *restrict, libgamma_gamma_rampsf_t *restrict); /** @@ -210,7 +413,8 @@ int libgamma_dummy_crtc_get_gamma_rampsf(libgamma_crtc_state_t *restrict, libgam * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -int libgamma_dummy_crtc_set_gamma_rampsf(libgamma_crtc_state_t *restrict, libgamma_gamma_rampsf_t); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) +int libgamma_dummy_crtc_set_gamma_rampsf(libgamma_crtc_state_t *restrict, const libgamma_gamma_rampsf_t *restrict); /** * Get the current gamma ramps for a CRTC, `double` version @@ -220,6 +424,7 @@ int libgamma_dummy_crtc_set_gamma_rampsf(libgamma_crtc_state_t *restrict, libgam * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_dummy_crtc_get_gamma_rampsd(libgamma_crtc_state_t *restrict, libgamma_gamma_rampsd_t *restrict); /** @@ -230,7 +435,96 @@ int libgamma_dummy_crtc_get_gamma_rampsd(libgamma_crtc_state_t *restrict, libgam * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -int libgamma_dummy_crtc_set_gamma_rampsd(libgamma_crtc_state_t *restrict, libgamma_gamma_rampsd_t); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) +int libgamma_dummy_crtc_set_gamma_rampsd(libgamma_crtc_state_t *restrict, const libgamma_gamma_rampsd_t *restrict); + + + +/** + * Restore the gamma ramps for a CRTC to the system settings for that CRTC + * and ignore the method's capabilities + * + * @param this The CRTC data + * @return Zero on success, otherwise (negative) the value of an + * error identifier provided by this library + */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) +int libgamma_dummy_internal_crtc_restore_forced(libgamma_dummy_crtc_t *restrict); + + +#else + +libgamma_dummy_crtc_t *data = this->data; +gamma_ramps_any_t ramps_; +TYPE *r_ramp = data->gamma_red; +TYPE *g_ramp = data->gamma_green; +TYPE *b_ramp = data->gamma_blue; +size_t rn = data->info.red_gamma_size; +size_t gn = data->info.green_gamma_size; +size_t bn = data->info.blue_gamma_size; +size_t i; + +#ifdef DEBUG +/* Check gamma ramp sizes */ +if (libgamma_dummy_internal_configurations.capabilities.identical_gamma_sizes) + if (ramps->red_size != ramps->green_size || ramps->red_size != ramps->blue_size) + return LIBGAMMA_MIXED_GAMMA_RAMP_SIZE; +if (ramps->red_size != rn || ramps->green_size != gn || ramps->blue_size != bn) + return LIBGAMMA_WRONG_GAMMA_RAMP_SIZE; +#endif + +if (!data->info.gamma_support) + return LIBGAMMA_GAMMA_RAMP_READ_FAILED; + +#ifdef LIBGAMMA_DUMMY_GET_RAMPS +# define __trans(TDEPTH, SUFFIX)\ +do {\ + if (data->info.gamma_depth == DEPTH) {\ + ramps_.FIELD = *ramps;\ + return libgamma_internal_translated_ramp_get(this, &ramps_, DEPTH, TDEPTH, libgamma_crtc_get_gamma_ramps##SUFFIX);\ + }\ +} while (0) +#else +# define __trans(TDEPTH, SUFFIX)\ +do {\ + if (data->info.gamma_depth == DEPTH) {\ + ramps_.FIELD = *ramps;\ + return libgamma_internal_translated_ramp_set(this, &ramps_, DEPTH, TDEPTH, libgamma_crtc_set_gamma_ramps##SUFFIX); \ + }\ +} while (0) +#endif + +#if DEPTH != 8 +__trans(8, 8); +#endif +#if DEPTH != 16 +__trans(16, 16); +#endif +#if DEPTH != 32 +__trans(32, 32); +#endif +#if DEPTH != 64 +__trans(64, 64); +#endif +#if DEPTH != -1 +__trans(-1, f); +#endif +#if DEPTH != -2 +__trans(-2, d); +#endif + +#undef __trans + +#ifdef LIBGAMMA_DUMMY_GET_RAMPS +for (i = 0; i < rn; i++) ramps->red[i] = r_ramp[i]; +for (i = 0; i < gn; i++) ramps->green[i] = g_ramp[i]; +for (i = 0; i < bn; i++) ramps->blue[i] = b_ramp[i]; +#else +for (i = 0; i < rn; i++) r_ramp[i] = ramps->red[i]; +for (i = 0; i < gn; i++) g_ramp[i] = ramps->green[i]; +for (i = 0; i < bn; i++) b_ramp[i] = ramps->blue[i]; +#endif +return 0; #endif diff --git a/gamma-linux-drm.h b/method-linux-drm.h index a8f1e1c..50da38e 100644 --- a/gamma-linux-drm.h +++ b/method-linux-drm.h @@ -1,6 +1,35 @@ /* See LICENSE file for copyright and license details. */ -#ifndef LIBGAMMA_GAMMA_LINUX_DRM_H -#define LIBGAMMA_GAMMA_LINUX_DRM_H + +#include <xf86drm.h> +#include <xf86drmMode.h> + + +/** + * 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; + /** @@ -8,6 +37,7 @@ * * @param this The data structure to fill with the method's capabilities */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_linux_drm_method_capabilities(libgamma_method_capabilities_t *restrict); /** @@ -23,6 +53,7 @@ void libgamma_linux_drm_method_capabilities(libgamma_method_capabilities_t *rest * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__(1), __warn_unused_result__))) int libgamma_linux_drm_site_initialise(libgamma_site_state_t *restrict, char *restrict); /** @@ -30,6 +61,7 @@ int libgamma_linux_drm_site_initialise(libgamma_site_state_t *restrict, char *re * * @param this The site state */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_linux_drm_site_destroy(libgamma_site_state_t *restrict); /** @@ -39,6 +71,7 @@ void libgamma_linux_drm_site_destroy(libgamma_site_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_linux_drm_site_restore(libgamma_site_state_t *restrict); @@ -51,6 +84,7 @@ int libgamma_linux_drm_site_restore(libgamma_site_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_linux_drm_partition_initialise(libgamma_partition_state_t *restrict, libgamma_site_state_t *restrict, size_t); /** @@ -58,6 +92,7 @@ int libgamma_linux_drm_partition_initialise(libgamma_partition_state_t *restrict * * @param this The partition state */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_linux_drm_partition_destroy(libgamma_partition_state_t *restrict); /** @@ -67,6 +102,7 @@ void libgamma_linux_drm_partition_destroy(libgamma_partition_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_linux_drm_partition_restore(libgamma_partition_state_t *restrict); @@ -79,6 +115,7 @@ int libgamma_linux_drm_partition_restore(libgamma_partition_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_linux_drm_crtc_initialise(libgamma_crtc_state_t *restrict, libgamma_partition_state_t *restrict, size_t); /** @@ -86,6 +123,7 @@ int libgamma_linux_drm_crtc_initialise(libgamma_crtc_state_t *restrict, libgamma * * @param this The CRTC state */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_linux_drm_crtc_destroy(libgamma_crtc_state_t *restrict); /** @@ -95,6 +133,7 @@ void libgamma_linux_drm_crtc_destroy(libgamma_crtc_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_linux_drm_crtc_restore(libgamma_crtc_state_t *restrict); @@ -106,6 +145,7 @@ int libgamma_linux_drm_crtc_restore(libgamma_crtc_state_t *restrict); * @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` */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_linux_drm_get_crtc_information(libgamma_crtc_information_t *restrict, libgamma_crtc_state_t *restrict, int32_t); /** @@ -116,6 +156,7 @@ int libgamma_linux_drm_get_crtc_information(libgamma_crtc_information_t *restric * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_linux_drm_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps16_t *restrict); /** @@ -126,7 +167,15 @@ int libgamma_linux_drm_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict, l * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -int libgamma_linux_drm_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps16_t); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) +int libgamma_linux_drm_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict, const libgamma_gamma_ramps16_t *restrict); + -#endif +/** + * Release all connectors and encoders + * + * @param this The graphics card data + */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) +void libgamma_linux_drm_internal_release_connectors_and_encoders(libgamma_drm_card_data_t *restrict); diff --git a/gamma-quartz-cg.h b/method-quartz-cg.h index 6044680..83ee61a 100644 --- a/gamma-quartz-cg.h +++ b/method-quartz-cg.h @@ -1,6 +1,13 @@ /* See LICENSE file for copyright and license details. */ -#ifndef LIBGAMMA_GAMMA_QUARTZ_CG_H -#define LIBGAMMA_GAMMA_QUARTZ_CG_H + +#ifdef FAKE_LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS +# include "fake-quartz-cg.h" +#else +# include <ApplicationServices/ApplicationServices.h> +# include <CoreGraphics/CGDirectDisplay.h> +# define close_fake_quartz_cg() /* For compatibility with "fake-quartz-cg.h" */ +#endif + /** @@ -8,6 +15,7 @@ * * @param this The data structure to fill with the method's capabilities */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_quartz_cg_method_capabilities(libgamma_method_capabilities_t *restrict); /** @@ -23,6 +31,7 @@ void libgamma_quartz_cg_method_capabilities(libgamma_method_capabilities_t *rest * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__(1), __warn_unused_result__))) int libgamma_quartz_cg_site_initialise(libgamma_site_state_t *restrict, char *restrict); /** @@ -30,6 +39,7 @@ int libgamma_quartz_cg_site_initialise(libgamma_site_state_t *restrict, char *re * * @param this The site state */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_quartz_cg_site_destroy(libgamma_site_state_t *restrict); /** @@ -39,6 +49,7 @@ void libgamma_quartz_cg_site_destroy(libgamma_site_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_quartz_cg_site_restore(libgamma_site_state_t *restrict); @@ -51,6 +62,7 @@ int libgamma_quartz_cg_site_restore(libgamma_site_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_quartz_cg_partition_initialise(libgamma_partition_state_t *restrict, libgamma_site_state_t *restrict, size_t); /** @@ -58,6 +70,7 @@ int libgamma_quartz_cg_partition_initialise(libgamma_partition_state_t *restrict * * @param this The partition state */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_quartz_cg_partition_destroy(libgamma_partition_state_t *restrict); /** @@ -67,6 +80,7 @@ void libgamma_quartz_cg_partition_destroy(libgamma_partition_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_quartz_cg_partition_restore(libgamma_partition_state_t *restrict); @@ -79,7 +93,7 @@ int libgamma_quartz_cg_partition_restore(libgamma_partition_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -__attribute__((pure)) +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__, __pure__))) int libgamma_quartz_cg_crtc_initialise(libgamma_crtc_state_t *restrict, libgamma_partition_state_t *restrict, size_t); /** @@ -87,6 +101,7 @@ int libgamma_quartz_cg_crtc_initialise(libgamma_crtc_state_t *restrict, libgamma * * @param this The CRTC state */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_quartz_cg_crtc_destroy(libgamma_crtc_state_t *restrict); /** @@ -96,6 +111,7 @@ void libgamma_quartz_cg_crtc_destroy(libgamma_crtc_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_quartz_cg_crtc_restore(libgamma_crtc_state_t *restrict); @@ -107,6 +123,7 @@ int libgamma_quartz_cg_crtc_restore(libgamma_crtc_state_t *restrict); * @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` */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_quartz_cg_get_crtc_information(libgamma_crtc_information_t *restrict, libgamma_crtc_state_t *restrict, int32_t); /** @@ -117,6 +134,7 @@ int libgamma_quartz_cg_get_crtc_information(libgamma_crtc_information_t *restric * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_quartz_cg_crtc_get_gamma_rampsf(libgamma_crtc_state_t *restrict, libgamma_gamma_rampsf_t *restrict); /** @@ -127,7 +145,5 @@ int libgamma_quartz_cg_crtc_get_gamma_rampsf(libgamma_crtc_state_t *restrict, li * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -int libgamma_quartz_cg_crtc_set_gamma_rampsf(libgamma_crtc_state_t *restrict, libgamma_gamma_rampsf_t); - - -#endif +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) +int libgamma_quartz_cg_crtc_set_gamma_rampsf(libgamma_crtc_state_t *restrict, const libgamma_gamma_rampsf_t *restrict); diff --git a/gamma-w32-gdi.h b/method-w32-gdi.h index 245a94d..d78af91 100644 --- a/gamma-w32-gdi.h +++ b/method-w32-gdi.h @@ -1,6 +1,23 @@ /* See LICENSE file for copyright and license details. */ -#ifndef LIBGAMMA_GAMMA_W32_GDI_H -#define LIBGAMMA_GAMMA_W32_GDI_H + +#ifndef WINVER +# define WINVER 0x0500 +#endif +#ifdef FAKE_LIBGAMMA_METHOD_W32_GDI +# include "fake-w32-gdi.h" +#else +# include <windows.h> +# include <wingdi.h> +#endif + + +/** + * The gamma ramp size that devices will always have in Windows GDI + * + * @see http://msdn.microsoft.com/en-us/library/windows/desktop/dd372194(v=vs.85).aspx + */ +#define W32_GDI_GAMMA_RAMP_SIZE 256 + /** @@ -8,6 +25,7 @@ * * @param this The data structure to fill with the method's capabilities */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_w32_gdi_method_capabilities(libgamma_method_capabilities_t *restrict); /** @@ -23,6 +41,7 @@ void libgamma_w32_gdi_method_capabilities(libgamma_method_capabilities_t *restri * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__(1))) int libgamma_w32_gdi_site_initialise(libgamma_site_state_t *restrict, char *restrict); /** @@ -30,6 +49,7 @@ int libgamma_w32_gdi_site_initialise(libgamma_site_state_t *restrict, char *rest * * @param this The site state */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_w32_gdi_site_destroy(libgamma_site_state_t *restrict); /** @@ -39,6 +59,7 @@ void libgamma_w32_gdi_site_destroy(libgamma_site_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_w32_gdi_site_restore(libgamma_site_state_t *restrict); @@ -51,6 +72,7 @@ int libgamma_w32_gdi_site_restore(libgamma_site_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_w32_gdi_partition_initialise(libgamma_partition_state_t *restrict, libgamma_site_state_t *restrict, size_t); /** @@ -58,6 +80,7 @@ int libgamma_w32_gdi_partition_initialise(libgamma_partition_state_t *restrict, * * @param this The partition state */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_w32_gdi_partition_destroy(libgamma_partition_state_t *restrict); /** @@ -67,6 +90,7 @@ void libgamma_w32_gdi_partition_destroy(libgamma_partition_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_w32_gdi_partition_restore(libgamma_partition_state_t *restrict); @@ -79,6 +103,7 @@ int libgamma_w32_gdi_partition_restore(libgamma_partition_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_w32_gdi_crtc_initialise(libgamma_crtc_state_t *restrict, libgamma_partition_state_t *restrict, size_t); /** @@ -86,6 +111,7 @@ int libgamma_w32_gdi_crtc_initialise(libgamma_crtc_state_t *restrict, libgamma_p * * @param this The CRTC state */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_w32_gdi_crtc_destroy(libgamma_crtc_state_t *restrict); /** @@ -95,6 +121,7 @@ void libgamma_w32_gdi_crtc_destroy(libgamma_crtc_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_w32_gdi_crtc_restore(libgamma_crtc_state_t *restrict); @@ -106,6 +133,7 @@ int libgamma_w32_gdi_crtc_restore(libgamma_crtc_state_t *restrict); * @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` */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_w32_gdi_get_crtc_information(libgamma_crtc_information_t *restrict, libgamma_crtc_state_t *restrict, int32_t); /** @@ -116,6 +144,7 @@ int libgamma_w32_gdi_get_crtc_information(libgamma_crtc_information_t *restrict, * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_w32_gdi_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps16_t *restrict); /** @@ -126,7 +155,5 @@ int libgamma_w32_gdi_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict, lib * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -int libgamma_w32_gdi_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps16_t); - - -#endif +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) +int libgamma_w32_gdi_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict, const libgamma_gamma_ramps16_t *restrict); diff --git a/gamma-x-randr.h b/method-x-randr.h index 3591192..81c5275 100644 --- a/gamma-x-randr.h +++ b/method-x-randr.h @@ -1,6 +1,54 @@ /* See LICENSE file for copyright and license details. */ -#ifndef LIBGAMMA_GAMMA_X_RANDR_H -#define LIBGAMMA_GAMMA_X_RANDR_H + +#include <xcb/xcb.h> +#include <xcb/randr.h> + + +/** + * The major version of RandR the library expects + */ +#define RANDR_VERSION_MAJOR 1 + +/** + * The minor version of RandR the library expects + */ +#define RANDR_VERSION_MINOR 3 + + +/** + * Data structure for partition data + */ +typedef struct libgamma_x_randr_partition_data { + /** + * Mapping from CRTC indices to CRTC identifiers + */ + xcb_randr_crtc_t *crtcs; + + /** + * Mapping from output indices to output identifiers + */ + xcb_randr_output_t *outputs; + + /** + * The number of outputs available + */ + size_t outputs_count; + + /** + * Mapping from CRTC indices to output indices. + * CRTC's without an output (should be impossible) + * have the value `SIZE_MAX` which is impossible + * for an existing mapping + */ + size_t *crtc_to_output; + + /** + * Screen configuration timestamp + */ + xcb_timestamp_t config_timestamp; + +} libgamma_x_randr_partition_data_t; + /** @@ -8,6 +56,7 @@ * * @param this The data structure to fill with the method's capabilities */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_x_randr_method_capabilities(libgamma_method_capabilities_t *restrict); /** @@ -23,6 +72,7 @@ void libgamma_x_randr_method_capabilities(libgamma_method_capabilities_t *restri * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__(1), __warn_unused_result__))) int libgamma_x_randr_site_initialise(libgamma_site_state_t *restrict, char *restrict); /** @@ -30,6 +80,7 @@ int libgamma_x_randr_site_initialise(libgamma_site_state_t *restrict, char *rest * * @param this The site state. */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_x_randr_site_destroy(libgamma_site_state_t *restrict); /** @@ -39,6 +90,7 @@ void libgamma_x_randr_site_destroy(libgamma_site_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_x_randr_site_restore(libgamma_site_state_t *restrict); @@ -51,6 +103,7 @@ int libgamma_x_randr_site_restore(libgamma_site_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_x_randr_partition_initialise(libgamma_partition_state_t *restrict, libgamma_site_state_t *restrict, size_t); /** @@ -58,6 +111,7 @@ int libgamma_x_randr_partition_initialise(libgamma_partition_state_t *restrict, * * @param this The partition state */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_x_randr_partition_destroy(libgamma_partition_state_t *restrict); /** @@ -67,6 +121,7 @@ void libgamma_x_randr_partition_destroy(libgamma_partition_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_x_randr_partition_restore(libgamma_partition_state_t *restrict); @@ -79,6 +134,7 @@ int libgamma_x_randr_partition_restore(libgamma_partition_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_x_randr_crtc_initialise(libgamma_crtc_state_t *restrict, libgamma_partition_state_t *restrict, size_t); /** @@ -86,6 +142,7 @@ int libgamma_x_randr_crtc_initialise(libgamma_crtc_state_t *restrict, libgamma_p * * @param this The CRTC state */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_x_randr_crtc_destroy(libgamma_crtc_state_t *restrict); /** @@ -95,6 +152,7 @@ void libgamma_x_randr_crtc_destroy(libgamma_crtc_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_x_randr_crtc_restore(libgamma_crtc_state_t *restrict); @@ -106,6 +164,7 @@ int libgamma_x_randr_crtc_restore(libgamma_crtc_state_t *restrict); * @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` */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_x_randr_get_crtc_information(libgamma_crtc_information_t *restrict, libgamma_crtc_state_t *restrict, int32_t); /** @@ -116,6 +175,7 @@ int libgamma_x_randr_get_crtc_information(libgamma_crtc_information_t *restrict, * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_x_randr_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps16_t *restrict); /** @@ -126,7 +186,28 @@ int libgamma_x_randr_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict, lib * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -int libgamma_x_randr_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps16_t); +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) +int libgamma_x_randr_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict, const libgamma_gamma_ramps16_t *restrict); + + + +/** + * Translate an xcb error into a libgamma error + * + * @param error_code The xcb error + * @param default_error The libgamma error to use if the xcb error is not recognised + * @param return_errno Whether an `errno` value may be returned + * @return The libgamma error + */ +LIBGAMMA_GCC_ONLY__(__attribute__((__warn_unused_result__))) +int libgamma_x_randr_internal_translate_error(int, int, int); + +/* xcb violates the rule to never return struct:s */ +#ifdef IN_LIBGAMMA_X_RANDR +# ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Waggregate-return" +# endif #endif diff --git a/gamma-x-vidmode.h b/method-x-vidmode.h index 8a95442..3612ff1 100644 --- a/gamma-x-vidmode.h +++ b/method-x-vidmode.h @@ -1,6 +1,7 @@ /* See LICENSE file for copyright and license details. */ -#ifndef LIBGAMMA_GAMMA_X_VIDMODE_H -#define LIBGAMMA_GAMMA_X_VIDMODE_H + +#include <X11/Xlib.h> +#include <X11/extensions/xf86vmode.h> /** @@ -8,6 +9,7 @@ * * @param this The data structure to fill with the method's capabilities */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_x_vidmode_method_capabilities(libgamma_method_capabilities_t *restrict); /** @@ -23,6 +25,7 @@ void libgamma_x_vidmode_method_capabilities(libgamma_method_capabilities_t *rest * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__(1), __warn_unused_result__))) int libgamma_x_vidmode_site_initialise(libgamma_site_state_t *restrict, char *restrict); /** @@ -30,6 +33,7 @@ int libgamma_x_vidmode_site_initialise(libgamma_site_state_t *restrict, char *re * * @param this The site state */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_x_vidmode_site_destroy(libgamma_site_state_t *restrict); /** @@ -39,6 +43,7 @@ void libgamma_x_vidmode_site_destroy(libgamma_site_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_x_vidmode_site_restore(libgamma_site_state_t *restrict); @@ -51,6 +56,7 @@ int libgamma_x_vidmode_site_restore(libgamma_site_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_x_vidmode_partition_initialise(libgamma_partition_state_t *restrict, libgamma_site_state_t *restrict, size_t); /** @@ -58,6 +64,7 @@ int libgamma_x_vidmode_partition_initialise(libgamma_partition_state_t *restrict * * @param this The partition state */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_x_vidmode_partition_destroy(libgamma_partition_state_t *restrict); /** @@ -67,6 +74,7 @@ void libgamma_x_vidmode_partition_destroy(libgamma_partition_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_x_vidmode_partition_restore(libgamma_partition_state_t *restrict); @@ -79,7 +87,7 @@ int libgamma_x_vidmode_partition_restore(libgamma_partition_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -__attribute__((const)) +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__, __const__))) int libgamma_x_vidmode_crtc_initialise(libgamma_crtc_state_t *restrict, libgamma_partition_state_t *restrict, size_t); /** @@ -87,6 +95,7 @@ int libgamma_x_vidmode_crtc_initialise(libgamma_crtc_state_t *restrict, libgamma * * @param this The CRTC state */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__))) void libgamma_x_vidmode_crtc_destroy(libgamma_crtc_state_t *restrict); /** @@ -96,6 +105,7 @@ void libgamma_x_vidmode_crtc_destroy(libgamma_crtc_state_t *restrict); * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_x_vidmode_crtc_restore(libgamma_crtc_state_t *restrict); @@ -107,6 +117,7 @@ int libgamma_x_vidmode_crtc_restore(libgamma_crtc_state_t *restrict); * @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` */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_x_vidmode_get_crtc_information(libgamma_crtc_information_t *restrict, libgamma_crtc_state_t *restrict, int32_t); /** @@ -117,6 +128,7 @@ int libgamma_x_vidmode_get_crtc_information(libgamma_crtc_information_t *restric * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) int libgamma_x_vidmode_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps16_t *restrict); /** @@ -127,7 +139,5 @@ int libgamma_x_vidmode_crtc_get_gamma_ramps16(libgamma_crtc_state_t *restrict, l * @return Zero on success, otherwise (negative) the value of an * error identifier provided by this library */ -int libgamma_x_vidmode_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict, libgamma_gamma_ramps16_t); - - -#endif +LIBGAMMA_GCC_ONLY__(__attribute__((__nonnull__, __warn_unused_result__))) +int libgamma_x_vidmode_crtc_set_gamma_ramps16(libgamma_crtc_state_t *restrict, const libgamma_gamma_ramps16_t *restrict); diff --git a/mk/method-dummy=yes.mk b/mk/method-dummy=yes.mk index 18773cf..3694cb3 100644 --- a/mk/method-dummy=yes.mk +++ b/mk/method-dummy=yes.mk @@ -1,3 +1,29 @@ -HDR_METHODS += gamma-dummy.h -METHODS_PARAMS += LIBGAMMA_METHOD_DUMMY dummy 0 ramps16 -CPPFLAGS_METHODS += -DHAVE_LIBGAMMA_METHOD_DUMMY +HDR_DUMMY = method-dummy.h +PARAMS_DUMMY = LIBGAMMA_METHOD_DUMMY dummy 0 ramps16 +CPPFLAGS_DUMMY = -DHAVE_LIBGAMMA_METHOD_DUMMY + +OBJ_DUMMY =\ + libgamma_dummy_method_capabilities.o\ + libgamma_dummy_site_initialise.o\ + libgamma_dummy_site_destroy.o\ + libgamma_dummy_site_restore.o\ + libgamma_dummy_partition_initialise.o\ + libgamma_dummy_partition_destroy.o\ + libgamma_dummy_partition_restore.o\ + libgamma_dummy_crtc_initialise.o\ + libgamma_dummy_crtc_destroy.o\ + libgamma_dummy_crtc_restore.o\ + libgamma_dummy_get_crtc_information.o\ + libgamma_dummy_crtc_get_gamma_ramps8.o\ + libgamma_dummy_crtc_set_gamma_ramps8.o\ + libgamma_dummy_crtc_get_gamma_ramps16.o\ + libgamma_dummy_crtc_set_gamma_ramps16.o\ + libgamma_dummy_crtc_get_gamma_ramps32.o\ + libgamma_dummy_crtc_set_gamma_ramps32.o\ + libgamma_dummy_crtc_get_gamma_ramps64.o\ + libgamma_dummy_crtc_set_gamma_ramps64.o\ + libgamma_dummy_crtc_get_gamma_rampsf.o\ + libgamma_dummy_crtc_set_gamma_rampsf.o\ + libgamma_dummy_crtc_get_gamma_rampsd.o\ + libgamma_dummy_crtc_set_gamma_rampsd.o\ + libgamma_dummy_internal_configurations.o diff --git a/mk/method-linux-drm=yes.mk b/mk/method-linux-drm=yes.mk index 8799388..fcb8515 100644 --- a/mk/method-linux-drm=yes.mk +++ b/mk/method-linux-drm=yes.mk @@ -1,5 +1,21 @@ -HDR_METHODS += gamma-linux-drm.h -METHODS_PARAMS += LIBGAMMA_METHOD_LINUX_DRM linux_drm 16 ramps16 -CPPFLAGS_METHODS += -DHAVE_LIBGAMMA_METHOD_LINUX_DRM -CFLAGS_METHODS += $$(pkg-config --cflags libdrm) -LDFLAGS_METHODS += $$(pkg-config --libs libdrm) +HDR_LINUX_DRM = method-linux-drm.h +PARAMS_LINUX_DRM = LIBGAMMA_METHOD_LINUX_DRM linux_drm 16 ramps16 +CPPFLAGS_LINUX_DRM = -DHAVE_LIBGAMMA_METHOD_LINUX_DRM +CFLAGS_LINUX_DRM = $$(pkg-config --cflags libdrm) +LDFLAGS_LINUX_DRM = $$(pkg-config --libs libdrm) + +OBJ_LINUX_DRM =\ + libgamma_linux_drm_method_capabilities.o\ + libgamma_linux_drm_site_initialise.o\ + libgamma_linux_drm_site_destroy.o\ + libgamma_linux_drm_site_restore.o\ + libgamma_linux_drm_partition_initialise.o\ + libgamma_linux_drm_partition_destroy.o\ + libgamma_linux_drm_partition_restore.o\ + libgamma_linux_drm_crtc_initialise.o\ + libgamma_linux_drm_crtc_destroy.o\ + libgamma_linux_drm_crtc_restore.o\ + libgamma_linux_drm_get_crtc_information.o\ + libgamma_linux_drm_crtc_get_gamma_ramps16.o\ + libgamma_linux_drm_crtc_set_gamma_ramps16.o\ + libgamma_linux_drm_internal_release_connectors_and_encoders.o diff --git a/mk/method-quartz-cg=fake.mk b/mk/method-quartz-cg=fake.mk index e33253a..496ac8a 100644 --- a/mk/method-quartz-cg=fake.mk +++ b/mk/method-quartz-cg=fake.mk @@ -1,3 +1,3 @@ -HDR_METHODS += gamma-quartz-cg.h -METHODS_PARAMS += LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS quartz_cg -1 rampsf -CPPFLAGS_METHODS += -DHAVE_LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS -DFAKE_LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS +HDR_QUARTZ_GC = method-quartz-cg.h +PARAMS_QUARTZ_GC = LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS quartz_cg -1 rampsf +CPPFLAGS_QUARTZ_GC = -DHAVE_LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS -DFAKE_LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS diff --git a/mk/method-quartz-cg=yes.mk b/mk/method-quartz-cg=yes.mk index b98d03d..cb079cf 100644 --- a/mk/method-quartz-cg=yes.mk +++ b/mk/method-quartz-cg=yes.mk @@ -1,8 +1,23 @@ F_APPLICATION_SERVICES = /System/Library/Frameworks/ApplicationServices.framework I_APPLICATION_SERVICES = $(F_APPLICATION_SERVICES)/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Headers -HDR_METHODS += gamma-quartz-cg.h -METHODS_PARAMS += LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS quartz_cg -1 rampsf -CPPFLAGS_METHODS += -DHAVE_LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS -CFLAGS_METHODS += -I$(I_APPLICATION_SERVICES) -F$(F_APPLICATION_SERVICES) -LDFLAGS_METHODS += -framework ApplicationServices +HDR_QUARTZ_GC = method-quartz-cg.h +PARAMS_QUARTZ_GC = LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS quartz_cg -1 rampsf +CPPFLAGS_QUARTZ_GC = -DHAVE_LIBGAMMA_METHOD_QUARTZ_CORE_GRAPHICS +CFLAGS_QUARTZ_GC = -I$(I_APPLICATION_SERVICES) -F$(F_APPLICATION_SERVICES) +LDFLAGS_QUARTZ_GC = -framework ApplicationServices + +OBJ_QUARTZ_GC =\ + libgamma_quartz_cg_method_capabilities.o\ + libgamma_quartz_cg_site_initialise.o\ + libgamma_quartz_cg_site_destroy.o\ + libgamma_quartz_cg_site_restore.o\ + libgamma_quartz_cg_partition_initialise.o\ + libgamma_quartz_cg_partition_destroy.o\ + libgamma_quartz_cg_partition_restore.o\ + libgamma_quartz_cg_crtc_initialise.o\ + libgamma_quartz_cg_crtc_destroy.o\ + libgamma_quartz_cg_crtc_restore.o\ + libgamma_quartz_cg_get_crtc_information.o\ + libgamma_quartz_cg_crtc_get_gamma_rampsf.o\ + libgamma_quartz_cg_crtc_set_gamma_rampsf.o diff --git a/mk/method-w32-gdi=fake.mk b/mk/method-w32-gdi=fake.mk index add5f79..fd068a8 100644 --- a/mk/method-w32-gdi=fake.mk +++ b/mk/method-w32-gdi=fake.mk @@ -1,3 +1,3 @@ -HDR_METHODS += gamma-w32-gdi.h -METHODS_PARAMS += LIBGAMMA_METHOD_W32_GDI w32_gdi 16 ramps16 -CPPFLAGS_METHODS += -DHAVE_LIBGAMMA_METHOD_W32_GDI -DFAKE_LIBGAMMA_METHOD_W32_GDI +HDR_W32_GDI = method-w32-gdi.h +PARAMS_W32_GDI = LIBGAMMA_METHOD_W32_GDI w32_gdi 16 ramps16 +CPPFLAGS_W32_GDI = -DHAVE_LIBGAMMA_METHOD_W32_GDI -DFAKE_LIBGAMMA_METHOD_W32_GDI diff --git a/mk/method-w32-gdi=yes.mk b/mk/method-w32-gdi=yes.mk index 348b71f..3f62a2d 100644 --- a/mk/method-w32-gdi=yes.mk +++ b/mk/method-w32-gdi=yes.mk @@ -1,3 +1,18 @@ -HDR_METHODS += gamma-w32-gdi.h -METHODS_PARAMS += LIBGAMMA_METHOD_W32_GDI w32_gdi 16 ramps16 -CPPFLAGS_METHODS += -DHAVE_LIBGAMMA_METHOD_W32_GDI +HDR_W32_GDI = method-w32-gdi.h +PARAMS_W32_GDI = LIBGAMMA_METHOD_W32_GDI w32_gdi 16 ramps16 +CPPFLAGS_W32_GDI = -DHAVE_LIBGAMMA_METHOD_W32_GDI + +OBJ_W32_GDI =\ + libgamma_w32_gdi_method_capabilities.o\ + libgamma_w32_gdi_site_initialise.o\ + libgamma_w32_gdi_site_destroy.o\ + libgamma_w32_gdi_site_restore.o\ + libgamma_w32_gdi_partition_initialise.o\ + libgamma_w32_gdi_partition_destroy.o\ + libgamma_w32_gdi_partition_restore.o\ + libgamma_w32_gdi_crtc_initialise.o\ + libgamma_w32_gdi_crtc_destroy.o\ + libgamma_w32_gdi_crtc_restore.o\ + libgamma_w32_gdi_get_crtc_information.o\ + libgamma_w32_gdi_crtc_get_gamma_ramps16.o\ + libgamma_w32_gdi_crtc_set_gamma_ramps16.o diff --git a/mk/method-x-randr=yes.mk b/mk/method-x-randr=yes.mk index 91a935b..97add0d 100644 --- a/mk/method-x-randr=yes.mk +++ b/mk/method-x-randr=yes.mk @@ -1,5 +1,21 @@ -HDR_METHODS += gamma-x-randr.h -METHODS_PARAMS += LIBGAMMA_METHOD_X_RANDR x_randr 16 ramps16 -CPPFLAGS_METHODS += -DHAVE_LIBGAMMA_METHOD_X_RANDR -CFLAGS_METHODS += $$(pkg-config --cflags xcb xcb-randr) -LDFLAGS_METHODS += $$(pkg-config --libs xcb xcb-randr) +HDR_X_RANDR = method-x-randr.h +PARAMS_X_RANDR = LIBGAMMA_METHOD_X_RANDR x_randr 16 ramps16 +CPPFLAGS_X_RANDR = -DHAVE_LIBGAMMA_METHOD_X_RANDR +CFLAGS_X_RANDR = $$(pkg-config --cflags xcb xcb-randr) +LDFLAGS_X_RANDR = $$(pkg-config --libs xcb xcb-randr) + +OBJ_X_RANDR =\ + libgamma_x_randr_method_capabilities.o\ + libgamma_x_randr_site_initialise.o\ + libgamma_x_randr_site_destroy.o\ + libgamma_x_randr_site_restore.o\ + libgamma_x_randr_partition_initialise.o\ + libgamma_x_randr_partition_destroy.o\ + libgamma_x_randr_partition_restore.o\ + libgamma_x_randr_crtc_initialise.o\ + libgamma_x_randr_crtc_destroy.o\ + libgamma_x_randr_crtc_restore.o\ + libgamma_x_randr_get_crtc_information.o\ + libgamma_x_randr_crtc_get_gamma_ramps16.o\ + libgamma_x_randr_crtc_set_gamma_ramps16.o\ + libgamma_x_randr_internal_translate_error.o diff --git a/mk/method-x-vidmode=yes.mk b/mk/method-x-vidmode=yes.mk index e54d98a..8225a96 100644 --- a/mk/method-x-vidmode=yes.mk +++ b/mk/method-x-vidmode=yes.mk @@ -1,5 +1,20 @@ -HDR_METHODS += gamma-x-vidmode.h -METHODS_PARAMS += LIBGAMMA_METHOD_X_VIDMODE x_vidmode 16 ramps16 -CPPFLAGS_METHODS += -DHAVE_LIBGAMMA_METHOD_X_VIDMODE -CFLAGS_METHODS += $$(pkg-config --cflags x11 xxf86vm) -LDFLAGS_METHODS += $$(pkg-config --libs x11 xxf86vm) +HDR_X_VIDMODE = method-x-vidmode.h +PARAMS_X_VIDMODE = LIBGAMMA_METHOD_X_VIDMODE x_vidmode 16 ramps16 +CPPFLAGS_X_VIDMODE = -DHAVE_LIBGAMMA_METHOD_X_VIDMODE +CFLAGS_X_VIDMODE = $$(pkg-config --cflags x11 xxf86vm) +LDFLAGS_X_VIDMODE = $$(pkg-config --libs x11 xxf86vm) + +OBJ_X_VIDMODE =\ + libgamma_x_vidmode_method_capabilities.o\ + libgamma_x_vidmode_site_initialise.o\ + libgamma_x_vidmode_site_destroy.o\ + libgamma_x_vidmode_site_restore.o\ + libgamma_x_vidmode_partition_initialise.o\ + libgamma_x_vidmode_partition_destroy.o\ + libgamma_x_vidmode_partition_restore.o\ + libgamma_x_vidmode_crtc_initialise.o\ + libgamma_x_vidmode_crtc_destroy.o\ + libgamma_x_vidmode_crtc_restore.o\ + libgamma_x_vidmode_get_crtc_information.o\ + libgamma_x_vidmode_crtc_get_gamma_ramps16.o\ + libgamma_x_vidmode_crtc_set_gamma_ramps16.o diff --git a/set_ramps.h b/set_ramps.h index b396450..6f564c3 100644 --- a/set_ramps.h +++ b/set_ramps.h @@ -11,12 +11,12 @@ switch (this->partition->site->method) { #define X(CONST, CNAME, MDEPTH, MRAMPS)\ case CONST:\ if (!(MDEPTH)) {\ - return APPEND_RAMPS(libgamma_dummy_crtc_set_gamma_)(this, ramps);\ + return APPEND_RAMPS(libgamma_dummy_crtc_set_gamma_)(this, (const void *)ramps);\ } else if ((DEPTH) == (MDEPTH)) {\ - return libgamma_##CNAME##_crtc_set_gamma_##MRAMPS(this, *(libgamma_gamma_##MRAMPS##_t *)&ramps); \ + return libgamma_##CNAME##_crtc_set_gamma_##MRAMPS(this, (const void *)ramps);\ } else {\ - ramps_.TYPE = ramps;\ - return libgamma_internal_translated_ramp_set(this, ramps_, DEPTH, MDEPTH, libgamma_crtc_set_gamma_##MRAMPS);\ + ramps_.TYPE = *ramps;\ + return libgamma_internal_translated_ramp_set(this, &ramps_, DEPTH, MDEPTH, libgamma_crtc_set_gamma_##MRAMPS);\ } LIST_AVAILABLE_METHODS(X) #undef X diff --git a/set_ramps_fun.h b/set_ramps_fun.h index bdd1fe8..5a3b541 100644 --- a/set_ramps_fun.h +++ b/set_ramps_fun.h @@ -45,6 +45,6 @@ for (i = 0, n = ramps.blue_size; i < n; i++) ramps.blue[i] = blue_function((float)i / (float)(n - 1)); /* Apply the gamma ramps */ -e = APPEND_RAMPS(libgamma_crtc_set_gamma_)(this, ramps); +e = APPEND_RAMPS(libgamma_crtc_set_gamma_)(this, &ramps); free(ramps.red); return e; |