/* See LICENSE file for copyright and license details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** * Framebuffer information */ typedef struct framebuffer { /** * The file descriptor used to access the framebuffer, -1 if not opened */ int fd; /** * The width of the display in pixels */ uint32_t width; /** * The height of the display in pixels */ uint32_t height; /** * Increment for `mem` to move to next pixel on the line */ uint32_t bytes_per_pixel; /** * Increment for `mem` to move down one line but stay in the same column */ uint32_t line_length; /** * Framebuffer pointer, `MAP_FAILED` (from ) if not mapped */ int8_t *mem; } framebuffer_t; /** * Graphics card information */ typedef struct drm_card { /** * File descriptor for the connection to the graphics card, * -1 if not opened */ int fd; /** * The graphics card's mode resources, `NULL` if not acquired */ drmModeRes *restrict res; /** * The number of CRTC:s available on the graphics card */ size_t crtc_count; /** * The available connectors */ drmModeConnector **restrict connectors; /** * The available encoders */ drmModeEncoder **restrict encoders; /** * The number of connectors and encoders */ size_t connector_count; } drm_card_t; /** * CRT controller information */ typedef struct drm_crtc { /** * CRT controller identifier */ uint32_t id; /** * The graphics card */ drm_card_t *restrict card; /** * The CRT controller's connector */ drmModeConnector *restrict connector; /** * The CRT controller's encoder */ drmModeEncoder *restrict encoder; /** * Whether the connector is connected */ int connected; /** * The CRT's EDID, hexadecimally encoded */ char *restrict edid; /** * The number of stops on the gamma ramps */ size_t gamma_stops; /** * The gamma ramp for the red channel */ uint16_t *restrict red; /** * The gamma ramp for the green channel */ uint16_t *restrict green; /** * The gamma ramp for the blue channel */ uint16_t *restrict blue; } drm_crtc_t; /***** gamma.c *****/ /** * Analyse a gamma ramp * * @param stops The number of stops in the gamma ramp * @param ramp The gamma ramp * @param gamma Output parameter for the gamma * @param contrast Output parameter for the contrast * @param brightness Output parameter for the brightness */ void gamma_analyse(size_t stops, const uint16_t* restrict ramp, double *restrict gamma, double *restrict contrast, double* restrict brightness); /** * Generate a gamma ramp * * @param stops The number of stops in the gamma ramp * @param ramp Memory area to where to write the gamma ramp * @param gamma The gamma * @param contrast The contrast * @param brightness The brightness */ void gamma_generate(size_t stops, uint16_t *restrict ramp, double gamma, double contrast, double brightness); /***** framebuffer.c *****/ /** * Figure out how many framebuffers there are on the system * * @return The number of framebuffers on the system */ size_t fb_count(void); /** * Open a framebuffer * * @param index The index of the framebuffer to open * @param fb Framebuffer information to fill in * @return Zero on success, -1 on error */ int fb_open(size_t index, framebuffer_t *restrict fb); /** * Close a framebuffer * * @param fb The framebuffer information */ void fb_close(framebuffer_t *restrict fb); /** * Construct an sRGB colour in 32-bit XRGB encoding to * use when specifying colours * * @param red The red component from [0, 255] sRGB * @param green The green component from [0, 255] sRGB * @param blue The blue component from [0, 255] sRGB * @return The colour as one 32-bit integer */ #ifdef __GNUC__ __attribute__((__const__)) #endif uint32_t fb_colour(int red, int green, int blue); /** * Print a filled in rectangle to a framebuffer * * @param fb The framebuffer * @param colour The colour to use when drawing the rectangle * @param x The starting pixel on the X axis for the rectangle * @param y The starting pixel on the Y axis for the rectangle * @param width The width of the rectangle, in pixels * @param height The height of the rectangle, in pixels */ void fb_fill_rectangle(framebuffer_t *restrict fb, uint32_t colour, uint32_t x, uint32_t y, uint32_t width, uint32_t height); /** * Draw a horizontal line segment on a framebuffer * * @param fb The framebuffer * @param colour The colour to use when drawing the rectangle * @param x The starting pixel on the X axis for the line segment * @param y The starting pixel on the Y axis for the line segment * @param length The length of the line segment, in pixels */ void fb_draw_horizontal_line(framebuffer_t *restrict fb, uint32_t colour, uint32_t x, uint32_t y, uint32_t length); /** * Draw a vertical line segment on a framebuffer * * @param fb The framebuffer * @param colour The colour to use when drawing the rectangle * @param x The starting pixel on the X axis for the line segment * @param y The starting pixel on the Y axis for the line segment * @param length The length of the line segment, in pixels */ void fb_draw_vertical_line(framebuffer_t *restrict fb, uint32_t colour, uint32_t x, uint32_t y, uint32_t length); /** * Draw a single on a framebuffer * * @param fb The framebuffer * @param colour The colour to use when drawing the rectangle * @param x The pixel's position on the X axis * @param y The pixel's position on the Y axis */ static inline void fb_draw_pixel(framebuffer_t *restrict fb, uint32_t colour, uint32_t x, uint32_t y) { int8_t *mem = fb->mem + y * fb->line_length + x * fb->bytes_per_pixel; *(uint32_t *)mem = colour; } /***** state.c ******/ /** * The framebuffers on the system */ extern framebuffer_t *restrict framebuffers; /** * The number of elements in `framebuffers` */ extern size_t framebuffer_count; /** * The graphics cards on the system */ extern drm_card_t *restrict cards; /** * The number of elements in `cards` */ extern size_t card_count; /** * The connected CRT controllers on the system */ extern drm_crtc_t *restrict crtcs; /** * The software brightness setting on each connected CRT controller, on each channel */ extern double *restrict brightnesses[3]; /** * The software contrast setting on each connected CRT controller, on each channel */ extern double *restrict contrasts[3]; /** * The gamma correction on each connected CRT controller, on each channel */ extern double *restrict gammas[3]; /** * The number of elements in `crtcs`, `brightnesses[]`, `contrasts[]` and `gammas[]` */ extern size_t crtc_count; /** * Acquire video control * * @return Zero on success, -1 on error */ int acquire_video(void); /** * Release video control */ void release_video(void); /***** drmgamma.c ******/ /** * Figure out how many graphics cards there are on the system * * @return The number of graphics cards on the system */ size_t drm_card_count(void); /** * Acquire access to a graphics card * * @param index The index of the graphics card * @param card Graphics card information to fill in * @return Zero on success, -1 on error */ int drm_card_open(size_t index, drm_card_t *restrict card); /** * Release access to a graphics card * * @param card The graphics card information */ void drm_card_close(drm_card_t *restrict card); /** * Acquire access to a CRT controller * * @param index The index of the CRT controller * @param card The graphics card information * @param crtc CRT controller information to fill in * @return Zero on success, -1 on error */ int drm_crtc_open(size_t index, drm_card_t *restrict card, drm_crtc_t *restrict crtc); /** * Release access to a CRT controller * * @param crtc The CRT controller information to fill in */ void drm_crtc_close(drm_crtc_t *restrict crtc); /** * Read the gamma ramps for a CRT controller * * @param crtc CRT controller information * @return Zero on success, -1 on error */ int drm_get_gamma(drm_crtc_t *restrict crtc); /** * Apply gamma ramps for a CRT controller * * @param crtc CRT controller information * @return Zero on success, -1 on error */ int drm_set_gamma(drm_crtc_t *restrict crtc);