From f55f58cd83e8b85e3fbd293e90d43689256b3d0f Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Thu, 4 Aug 2016 00:35:12 +0200 Subject: Update get-gamma-info protocol: gamut information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- src/servers/gamma.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++---- src/types/output.c | 70 ++++++++++++++++++++++++++ src/types/output.h | 101 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 301 insertions(+), 9 deletions(-) diff --git a/src/servers/gamma.c b/src/servers/gamma.c index 0330c51..3eec7ec 100644 --- a/src/servers/gamma.c +++ b/src/servers/gamma.c @@ -47,6 +47,8 @@ int handle_get_gamma_info(size_t conn, const char* restrict message_id, const ch char* restrict buf; char depth[3]; const char* supported; + const char* colourspace; + char* gamut[8 * sizeof("White x: 1023")]; size_t n; if (crtc == NULL) return send_error("protocol error: 'CRTC' header omitted"); @@ -71,6 +73,38 @@ int handle_get_gamma_info(size_t conn, const char* restrict message_id, const ch default: supported = "maybe"; break; } + switch (output->colourspace) + { + case COLOURSPACE_SRGB_SANS_GAMUT: + case COLOURSPACE_SRGB: colourspace = "Colour space: sRGB\n"; break; + case COLOURSPACE_RGB_SANS_GAMUT: + case COLOURSPACE_RGB: colourspace = "Colour space: RGB\n"; break; + case COLOURSPACE_NON_RGB: colourspace = "Colour space: non-RGB\n"; break; + case COLOURSPACE_GREY: colourspace = "Colour space: grey\n"; break; + default: colourspace = ""; break; + } + + switch (output->colourspace) + { + case COLOURSPACE_SRGB: + case COLOURSPACE_RGB: + sprintf(gamut, + "Red x: %u\n" + "Red y: %u\n" + "Green x: %u\n" + "Green y: %u\n" + "Blue x: %u\n" + "Blue y: %u\n" + "White x: %u\n" + "White y: %u\n", + output->red_x, output->red_y, output->green_x, output->green_y, + output->blue_x, output->blue_y, output->white_x, output->white_y); + break; + default: + *gamut = '\0'; + break; + } + MAKE_MESSAGE(&buf, &n, 0, "In response to: %s\n" "Cooperative: yes\n" /* In mds: say ‘no’, mds-coopgamma changes to ‘yes’.” */ @@ -79,9 +113,10 @@ int handle_get_gamma_info(size_t conn, const char* restrict message_id, const ch "Green size: %zu\n" "Blue size: %zu\n" "Gamma support: %s\n" + "%s%s" "\n", message_id, depth, output->red_size, output->green_size, - output->blue_size, supported); + output->blue_size, supported, gamut, colourspace); return send_message(conn, buf, n); } @@ -116,6 +151,90 @@ void set_gamma(const struct output* restrict output, const union gamma_ramps* re } +/** + * Parse the EDID of a monitor + * + * @param output The output + */ +static void parse_edid(struct output* restrict output) +{ + const unsigned char* restrict edid = (const unsigned char*)(output->name); + size_t i; + unsigned char sum; + int analogue; + + output->red_x = output->green_x = output->blue_x = output->white_x = 0; + output->red_y = output->green_y = output->blue_y = output->white_y = 0; + + if (output->name_is_edid == 0) + { + output->colourspace = COLOURSPACE_UNKNOWN; + return; + } + + if (strlen(edid) < 128) + return; + for (i = 0, sum = 0; i < 128; i++) + sum += edid[i]; + if (sum != 0) + return; + if ((edid[0] != 0) || (edid[7] != 0)) + return; + for (i = 1; i < 7; i++) + if (edid[i] != 0xFF) + return; + + analogue = !(edid[20] & 0x80); + if (!analogue) + output->colourspace = COLOURSPACE_RGB; + else + switch ((edid[24] >> 3) & 3) + { + case 0: output->colourspace = COLOURSPACE_GREY; break; + case 1: output->colourspace = COLOURSPACE_RGB; break; + case 2: output->colourspace = COLOURSPACE_NON_RGB; break; + default: output->colourspace = COLOURSPACE_UNKNOWN; break; + } + + if (output->colourspace != COLOURSPACE_RGB) + return; + + if (edid[24] & 2) + output->colourspace = COLOURSPACE_SRGB; + + output->red_x = (edid[25] >> 6) & 3; + output->red_y = (edid[25] >> 4) & 3; + output->green_x = (edid[25] >> 2) & 3; + output->green_y = (edid[25] >> 0) & 3; + output->blue_x = (edid[26] >> 6) & 3; + output->blue_y = (edid[26] >> 4) & 3; + output->white_x = (edid[26] >> 2) & 3; + output->white_y = (edid[26] >> 0) & 3; + + output->red_x |= ((unsigned)(edid[27])) << 2; + output->red_y |= ((unsigned)(edid[28])) << 2; + output->green_x |= ((unsigned)(edid[29])) << 2; + output->green_y |= ((unsigned)(edid[30])) << 2; + output->blue_x |= ((unsigned)(edid[31])) << 2; + output->blue_y |= ((unsigned)(edid[32])) << 2; + output->white_x |= ((unsigned)(edid[33])) << 2; + output->white_y |= ((unsigned)(edid[34])) << 2; + + if ((output->red_x == output->red_y) && + (output->red_x == output->green_x) && + (output->red_x == output->green_y) && + (output->red_x == output->blue_x) && + (output->red_x == output->blue_y) && + (output->red_x == output->white_x) && + (output->red_x == output->white_y)) + { + if (output->colourspace == COLOURSPACE_SRGB) + output->colourspace = COLOURSPACE_SRGB_SANS_GAMUT; + else + output->colourspace = COLOURSPACE_RGB_SANS_GAMUT; + } +} + /** * Store all current gamma ramps @@ -135,17 +254,18 @@ int initialise_gamma_info(void) LIBGAMMA_CRTC_INFO_MACRO_RAMP | LIBGAMMA_CRTC_INFO_GAMMA_SUPPORT | LIBGAMMA_CRTC_INFO_CONNECTOR_NAME); - outputs[i].depth = info.gamma_depth_error ? 0 : info.gamma_depth; - outputs[i].red_size = info.gamma_size_error ? 0 : info.red_gamma_size; - outputs[i].green_size = info.gamma_size_error ? 0 : info.green_gamma_size; - outputs[i].blue_size = info.gamma_size_error ? 0 : info.blue_gamma_size; - outputs[i].supported = info.gamma_support_error ? 0 : info.gamma_support; + outputs[i].depth = info.gamma_depth_error ? 0 : info.gamma_depth; + outputs[i].red_size = info.gamma_size_error ? 0 : info.red_gamma_size; + outputs[i].green_size = info.gamma_size_error ? 0 : info.green_gamma_size; + outputs[i].blue_size = info.gamma_size_error ? 0 : info.blue_gamma_size; + outputs[i].supported = info.gamma_support_error ? 0 : info.gamma_support; if (outputs[i].depth == 0 || outputs[i].red_size == 0 || outputs[i].green_size == 0 || outputs[i].blue_size == 0) - outputs[i].supported = 0; - outputs[i].name = get_crtc_name(&info, crtcs + i); + outputs[i].supported = 0; + outputs[i].name = get_crtc_name(&info, crtcs + i); saved_errno = errno; - outputs[i].crtc = crtcs + i; + outputs[i].name_is_edid = ((info.edid_error == 0) && (info.edid != NULL)); + outputs[i].crtc = crtcs + i; libgamma_crtc_information_destroy(&info); outputs[i].ramps_size = outputs[i].red_size + outputs[i].green_size + outputs[i].blue_size; switch (outputs[i].depth) @@ -163,6 +283,7 @@ int initialise_gamma_info(void) errno = saved_errno; if (outputs[i].name == NULL) return -1; + parse_edid(outputs + i); } return 0; diff --git a/src/types/output.c b/src/types/output.c index 8576baa..80f3d36 100644 --- a/src/types/output.c +++ b/src/types/output.c @@ -125,6 +125,46 @@ size_t output_marshal(const struct output* restrict this, void* restrict buf) *(enum libgamma_decision*)(bs + off) = this->supported; off += sizeof(enum libgamma_decision); + if (bs != NULL) + *(enum colourspace*)(bs + off) = this->colourspace; + off += sizeof(enum colourspace); + + if (bs != NULL) + *(int*)(bs + off) = this->name_is_edid; + off += sizeof(int); + + if (bs != NULL) + *(unsigned*)(bs + off) = this->red_x; + off += sizeof(unsigned); + + if (bs != NULL) + *(unsigned*)(bs + off) = this->red_y; + off += sizeof(unsigned); + + if (bs != NULL) + *(unsigned*)(bs + off) = this->green_x; + off += sizeof(unsigned); + + if (bs != NULL) + *(unsigned*)(bs + off) = this->green_y; + off += sizeof(unsigned); + + if (bs != NULL) + *(unsigned*)(bs + off) = this->blue_x; + off += sizeof(unsigned); + + if (bs != NULL) + *(unsigned*)(bs + off) = this->blue_y; + off += sizeof(unsigned); + + if (bs != NULL) + *(unsigned*)(bs + off) = this->white_x; + off += sizeof(unsigned); + + if (bs != NULL) + *(unsigned*)(bs + off) = this->white_y; + off += sizeof(unsigned); + n = strlen(this->name) + 1; if (bs != NULL) memcpy(bs + off, this->name, n); @@ -179,6 +219,36 @@ size_t output_unmarshal(struct output* restrict this, const void* restrict buf) this->supported = *(const enum libgamma_decision*)(bs + off); off += sizeof(enum libgamma_decision); + this->colourspace = *(const enum colourspace*)(bs + off); + off += sizeof(enum colourspace); + + this->name_is_edid = *(const int*)(bs + off); + off += sizeof(int); + + this->red_x = *(const unsigned*)(bs + off); + off += sizeof(unsigned); + + this->red_y = *(const unsigned*)(bs + off); + off += sizeof(unsigned); + + this->green_x = *(const unsigned*)(bs + off); + off += sizeof(unsigned); + + this->green_y = *(const unsigned*)(bs + off); + off += sizeof(unsigned); + + this->blue_x = *(const unsigned*)(bs + off); + off += sizeof(unsigned); + + this->blue_y = *(const unsigned*)(bs + off); + off += sizeof(unsigned); + + this->white_x = *(const unsigned*)(bs + off); + off += sizeof(unsigned); + + this->white_y = *(const unsigned*)(bs + off); + off += sizeof(unsigned); + n = strlen(bs + off) + 1; this->name = memdup(bs + off, n); if (this->name == NULL) diff --git a/src/types/output.h b/src/types/output.h index f8a4c3e..95270ae 100644 --- a/src/types/output.h +++ b/src/types/output.h @@ -54,6 +54,49 @@ +/** + * Colour spaces + */ +enum colourspace +{ + /** + * sRGB with explicit gamut + */ + COLOURSPACE_SRGB = 0, + + /** + * sRGB without explicit gamut + */ + COLOURSPACE_SRGB_SANS_GAMUT = 1, + + /** + * RGB (but not sRGB) with known gamut + */ + COLOURSPACE_RGB = 2, + + /** + * RGB (but not sRGB) without known gamut + */ + COLOURSPACE_RGB_SANS_GAMUT = 3, + + /** + * Non-RGB multicolour + */ + COLOURSPACE_NON_RGB = 4, + + /** + * Greyscale or monochrome + */ + COLOURSPACE_GREY = 5, + + /** + * Unknown + */ + COLOURSPACE_UNKNOWN = 6 +}; + + + /** * Information about an output */ @@ -74,6 +117,64 @@ struct output */ enum libgamma_decision supported; + /** + * Whether the name is the EDID + */ + int name_is_edid; + + /** + * The monitor's colour space + */ + enum colourspace colourspace; + + /** + * The x-value (CIE xyY) of the monitor's + * red colour, multiplied by 1024 + */ + unsigned red_x; + + /** + * The y-value (CIE xyY) of the monitor's + * red colour, multiplied by 1024 + */ + unsigned red_y; + + /** + * The x-value (CIE xyY) of the monitor's + * green colour, multiplied by 1024 + */ + unsigned green_x; + + /** + * The y-value (CIE xyY) of the monitor's + * green colour, multiplied by 1024 + */ + unsigned green_y; + + /** + * The x-value (CIE xyY) of the monitor's + * blue colour, multiplied by 1024 + */ + unsigned blue_x; + + /** + * The y-value (CIE xyY) of the monitor's + * blue colour, multiplied by 1024 + */ + unsigned blue_y; + + /** + * The x-value (CIE xyY) of the monitor's + * default white point, multiplied by 1024 + */ + unsigned white_x; + + /** + * The y-value (CIE xyY) of the monitor's + * default white point, multiplied by 1024 + */ + unsigned white_y; + /** * The number of stops in the red gamma ramp */ -- cgit v1.2.3-70-g09d2