aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2021-03-05 18:23:13 +0100
committerMattias Andrée <maandree@kth.se>2021-03-05 18:33:49 +0100
commitf52513b09580c1533e6c48a4162d3d5f61f3b081 (patch)
tree141d0974a777f4ec5b51daed9879a2cb0d781505
parentSplit source files, merge public header files, eliminite use gpp, rewrite makefile (diff)
downloadlibgamma-f52513b09580c1533e6c48a4162d3d5f61f3b081.tar.gz
libgamma-f52513b09580c1533e6c48a4162d3d5f61f3b081.tar.bz2
libgamma-f52513b09580c1533e6c48a4162d3d5f61f3b081.tar.xz
misc
Signed-off-by: Mattias Andrée <maandree@kth.se>
-rw-r--r--Makefile25
-rw-r--r--common.h105
-rw-r--r--config.mk2
-rw-r--r--gamma-dummy.c.gpp993
-rw-r--r--gamma-linux-drm.c902
-rw-r--r--gamma-quartz-cg.c359
-rw-r--r--gamma-w32-gdi.c360
-rw-r--r--gamma-x-randr.c985
-rw-r--r--gamma-x-vidmode.c312
-rw-r--r--get_ramps.h2
-rw-r--r--legacy.c54
-rw-r--r--libgamma.h120
-rw-r--r--libgamma_connector_type_count.c2
-rw-r--r--libgamma_const_of_connector_type.c5
-rw-r--r--libgamma_const_of_method.c5
-rw-r--r--libgamma_const_of_subpixel_order.c5
-rw-r--r--libgamma_crtc_destroy.c2
-rw-r--r--libgamma_crtc_get_gamma_ramps16.c1
-rw-r--r--libgamma_crtc_get_gamma_ramps32.c1
-rw-r--r--libgamma_crtc_get_gamma_ramps64.c1
-rw-r--r--libgamma_crtc_get_gamma_ramps8.c1
-rw-r--r--libgamma_crtc_get_gamma_rampsd.c1
-rw-r--r--libgamma_crtc_get_gamma_rampsf.c1
-rw-r--r--libgamma_crtc_initialise.c2
-rw-r--r--libgamma_crtc_restore.c2
-rw-r--r--libgamma_crtc_set_gamma_ramps16.c3
-rw-r--r--libgamma_crtc_set_gamma_ramps16_f.c3
-rw-r--r--libgamma_crtc_set_gamma_ramps32.c3
-rw-r--r--libgamma_crtc_set_gamma_ramps32_f.c3
-rw-r--r--libgamma_crtc_set_gamma_ramps64.c3
-rw-r--r--libgamma_crtc_set_gamma_ramps64_f.c3
-rw-r--r--libgamma_crtc_set_gamma_ramps8.c3
-rw-r--r--libgamma_crtc_set_gamma_ramps8_f.c3
-rw-r--r--libgamma_crtc_set_gamma_rampsd.c3
-rw-r--r--libgamma_crtc_set_gamma_rampsd_f.c3
-rw-r--r--libgamma_crtc_set_gamma_rampsf.c3
-rw-r--r--libgamma_crtc_set_gamma_rampsf_f.c3
-rw-r--r--libgamma_dummy_crtc_destroy.c22
-rw-r--r--libgamma_dummy_crtc_get_gamma_ramps16.c21
-rw-r--r--libgamma_dummy_crtc_get_gamma_ramps32.c21
-rw-r--r--libgamma_dummy_crtc_get_gamma_ramps64.c21
-rw-r--r--libgamma_dummy_crtc_get_gamma_ramps8.c21
-rw-r--r--libgamma_dummy_crtc_get_gamma_rampsd.c21
-rw-r--r--libgamma_dummy_crtc_get_gamma_rampsf.c21
-rw-r--r--libgamma_dummy_crtc_initialise.c57
-rw-r--r--libgamma_dummy_crtc_restore.c20
-rw-r--r--libgamma_dummy_crtc_set_gamma_ramps16.c21
-rw-r--r--libgamma_dummy_crtc_set_gamma_ramps32.c21
-rw-r--r--libgamma_dummy_crtc_set_gamma_ramps64.c21
-rw-r--r--libgamma_dummy_crtc_set_gamma_ramps8.c21
-rw-r--r--libgamma_dummy_crtc_set_gamma_rampsd.c21
-rw-r--r--libgamma_dummy_crtc_set_gamma_rampsf.c21
-rw-r--r--libgamma_dummy_get_crtc_information.c69
-rw-r--r--libgamma_dummy_internal_configurations.c59
-rw-r--r--libgamma_dummy_internal_crtc_restore_forced.c44
-rw-r--r--libgamma_dummy_method_capabilities.c18
-rw-r--r--libgamma_dummy_partition_destroy.c24
-rw-r--r--libgamma_dummy_partition_initialise.c67
-rw-r--r--libgamma_dummy_partition_restore.c28
-rw-r--r--libgamma_dummy_site_destroy.c18
-rw-r--r--libgamma_dummy_site_initialise.c62
-rw-r--r--libgamma_dummy_site_restore.c29
-rw-r--r--libgamma_get_crtc_information.c3
-rw-r--r--libgamma_group_gid.c2
-rw-r--r--libgamma_internal_allocated_any_ramp.c15
-rw-r--r--libgamma_internal_translate_from_64.c14
-rw-r--r--libgamma_internal_translate_to_64.c19
-rw-r--r--libgamma_internal_translated_ramp_get_.c6
-rw-r--r--libgamma_internal_translated_ramp_set_.c6
-rw-r--r--libgamma_is_method_available.c3
-rw-r--r--libgamma_linux_drm_crtc_destroy.c14
-rw-r--r--libgamma_linux_drm_crtc_get_gamma_ramps16.c27
-rw-r--r--libgamma_linux_drm_crtc_initialise.c24
-rw-r--r--libgamma_linux_drm_crtc_restore.c18
-rw-r--r--libgamma_linux_drm_crtc_set_gamma_ramps16.c54
-rw-r--r--libgamma_linux_drm_get_crtc_information.c387
-rw-r--r--libgamma_linux_drm_internal_release_connectors_and_encoders.c32
-rw-r--r--libgamma_linux_drm_method_capabilities.c41
-rw-r--r--libgamma_linux_drm_partition_destroy.c20
-rw-r--r--libgamma_linux_drm_partition_initialise.c151
-rw-r--r--libgamma_linux_drm_partition_restore.c18
-rw-r--r--libgamma_linux_drm_site_destroy.c14
-rw-r--r--libgamma_linux_drm_site_initialise.c42
-rw-r--r--libgamma_linux_drm_site_restore.c18
-rw-r--r--libgamma_list_methods.c2
-rw-r--r--libgamma_method_capabilities.c2
-rw-r--r--libgamma_name_of_connector_type.c5
-rw-r--r--libgamma_name_of_error.c5
-rw-r--r--libgamma_name_of_method.c5
-rw-r--r--libgamma_name_of_subpixel_order.c5
-rw-r--r--libgamma_partition_destroy.c2
-rw-r--r--libgamma_partition_initialise.c2
-rw-r--r--libgamma_partition_restore.c2
-rw-r--r--libgamma_quartz_cg_crtc_destroy.c14
-rw-r--r--libgamma_quartz_cg_crtc_get_gamma_rampsf.c35
-rw-r--r--libgamma_quartz_cg_crtc_initialise.c21
-rw-r--r--libgamma_quartz_cg_crtc_restore.c18
-rw-r--r--libgamma_quartz_cg_crtc_set_gamma_rampsf.c27
-rw-r--r--libgamma_quartz_cg_get_crtc_information.c56
-rw-r--r--libgamma_quartz_cg_method_capabilities.c49
-rw-r--r--libgamma_quartz_cg_partition_destroy.c14
-rw-r--r--libgamma_quartz_cg_partition_initialise.c59
-rw-r--r--libgamma_quartz_cg_partition_restore.c16
-rw-r--r--libgamma_quartz_cg_site_destroy.c15
-rw-r--r--libgamma_quartz_cg_site_initialise.c23
-rw-r--r--libgamma_quartz_cg_site_restore.c18
-rw-r--r--libgamma_site_destroy.c2
-rw-r--r--libgamma_site_initialise.c2
-rw-r--r--libgamma_site_restore.c2
-rw-r--r--libgamma_strerror.c2
-rw-r--r--libgamma_strerror_r.c4
-rw-r--r--libgamma_value_of_connector_type.c4
-rw-r--r--libgamma_value_of_error.c4
-rw-r--r--libgamma_value_of_method.c4
-rw-r--r--libgamma_value_of_subpixel_order.c4
-rw-r--r--libgamma_w32_gdi_crtc_destroy.c15
-rw-r--r--libgamma_w32_gdi_crtc_get_gamma_ramps16.c27
-rw-r--r--libgamma_w32_gdi_crtc_initialise.c43
-rw-r--r--libgamma_w32_gdi_crtc_restore.c18
-rw-r--r--libgamma_w32_gdi_crtc_set_gamma_ramps16.c27
-rw-r--r--libgamma_w32_gdi_get_crtc_information.c59
-rw-r--r--libgamma_w32_gdi_method_capabilities.c47
-rw-r--r--libgamma_w32_gdi_partition_destroy.c14
-rw-r--r--libgamma_w32_gdi_partition_initialise.c35
-rw-r--r--libgamma_w32_gdi_partition_restore.c18
-rw-r--r--libgamma_w32_gdi_site_destroy.c14
-rw-r--r--libgamma_w32_gdi_site_initialise.c23
-rw-r--r--libgamma_w32_gdi_site_restore.c18
-rw-r--r--libgamma_x_randr_crtc_destroy.c15
-rw-r--r--libgamma_x_randr_crtc_get_gamma_ramps16.c50
-rw-r--r--libgamma_x_randr_crtc_initialise.c23
-rw-r--r--libgamma_x_randr_crtc_restore.c19
-rw-r--r--libgamma_x_randr_crtc_set_gamma_ramps16.c34
-rw-r--r--libgamma_x_randr_get_crtc_information.c400
-rw-r--r--libgamma_x_randr_internal_translate_error.c31
-rw-r--r--libgamma_x_randr_method_capabilities.c43
-rw-r--r--libgamma_x_randr_partition_destroy.c19
-rw-r--r--libgamma_x_randr_partition_initialise.c161
-rw-r--r--libgamma_x_randr_partition_restore.c19
-rw-r--r--libgamma_x_randr_site_destroy.c15
-rw-r--r--libgamma_x_randr_site_initialise.c82
-rw-r--r--libgamma_x_randr_site_restore.c19
-rw-r--r--libgamma_x_vidmode_crtc_destroy.c14
-rw-r--r--libgamma_x_vidmode_crtc_get_gamma_ramps16.c26
-rw-r--r--libgamma_x_vidmode_crtc_initialise.c21
-rw-r--r--libgamma_x_vidmode_crtc_restore.c18
-rw-r--r--libgamma_x_vidmode_crtc_set_gamma_ramps16.c26
-rw-r--r--libgamma_x_vidmode_get_crtc_information.c55
-rw-r--r--libgamma_x_vidmode_method_capabilities.c37
-rw-r--r--libgamma_x_vidmode_partition_destroy.c14
-rw-r--r--libgamma_x_vidmode_partition_initialise.c20
-rw-r--r--libgamma_x_vidmode_partition_restore.c18
-rw-r--r--libgamma_x_vidmode_site_destroy.c14
-rw-r--r--libgamma_x_vidmode_site_initialise.c40
-rw-r--r--libgamma_x_vidmode_site_restore.c18
-rw-r--r--method-dummy.h (renamed from gamma-dummy.h)310
-rw-r--r--method-linux-drm.h (renamed from gamma-linux-drm.h)57
-rw-r--r--method-quartz-cg.h (renamed from gamma-quartz-cg.h)30
-rw-r--r--method-w32-gdi.h (renamed from gamma-w32-gdi.h)39
-rw-r--r--method-x-randr.h (renamed from gamma-x-randr.h)87
-rw-r--r--method-x-vidmode.h (renamed from gamma-x-vidmode.h)24
-rw-r--r--mk/method-dummy=yes.mk32
-rw-r--r--mk/method-linux-drm=yes.mk26
-rw-r--r--mk/method-quartz-cg=fake.mk6
-rw-r--r--mk/method-quartz-cg=yes.mk25
-rw-r--r--mk/method-w32-gdi=fake.mk6
-rw-r--r--mk/method-w32-gdi=yes.mk21
-rw-r--r--mk/method-x-randr=yes.mk26
-rw-r--r--mk/method-x-vidmode=yes.mk25
-rw-r--r--set_ramps.h8
-rw-r--r--set_ramps_fun.h2
171 files changed, 4559 insertions, 4178 deletions
diff --git a/Makefile b/Makefile
index 6b8746d..17f7774 100644
--- a/Makefile
+++ b/Makefile
@@ -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 =\
diff --git a/common.h b/common.h
index a6584f1..c13c067 100644
--- a/common.h
+++ b/common.h
@@ -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);
diff --git a/config.mk b/config.mk
index cc02d6e..c675775 100644
--- a/config.mk
+++ b/config.mk
@@ -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);
+}
diff --git a/libgamma.h b/libgamma.h
index d798f33..93fe928 100644
--- a/libgamma.h
+++ b/libgamma.h
@@ -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;