diff --git a/headers/private/graphics/common/validate_display_mode.h b/headers/private/graphics/common/validate_display_mode.h new file mode 100644 index 0000000000..e0fa3d8e1a --- /dev/null +++ b/headers/private/graphics/common/validate_display_mode.h @@ -0,0 +1,54 @@ +/* + * Copyright 2011, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ +#ifndef _VALIDATE_DISPLAY_MODE_H +#define _VALIDATE_DISPLAY_MODE_H + + +#include + +#include "edid.h" + +struct timing_constraints { + uint16 resolution; + + uint16 min_before_sync; + uint16 max_sync_start; + uint16 min_sync_length; + uint16 max_sync_length; + uint16 min_after_sync; + uint16 max_total; +}; + +struct display_constraints { + uint16 min_h_display; + uint16 max_h_display; + uint16 min_v_display; + uint16 max_v_display; + + uint32 min_pixel_clock; + uint32 max_pixel_clock; + + timing_constraints horizontal_timing; + timing_constraints vertical_timing; +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + +bool sanitize_display_mode(display_mode& mode, + const display_constraints& constraints, const edid1_info* edidInfo); +bool is_display_mode_within_bounds(display_mode& mode, const display_mode& low, + const display_mode& high); + + +#ifdef __cplusplus +} +#endif + + +#endif /* _VALIDATE_DISPLAY_MODE_H */ diff --git a/src/add-ons/accelerants/common/Jamfile b/src/add-ons/accelerants/common/Jamfile index a1ab758013..fe844b2342 100644 --- a/src/add-ons/accelerants/common/Jamfile +++ b/src/add-ons/accelerants/common/Jamfile @@ -9,9 +9,10 @@ UsePrivateHeaders [ FDirName graphics common ] ; StaticLibrary libaccelerantscommon.a : compute_display_timing.cpp create_display_modes.cpp - video_configuration.cpp ddc.c decode_edid.c dump_edid.c i2c.c + validate_display_mode.cpp + video_configuration.cpp ; diff --git a/src/add-ons/accelerants/common/validate_display_mode.cpp b/src/add-ons/accelerants/common/validate_display_mode.cpp new file mode 100644 index 0000000000..11863ffa34 --- /dev/null +++ b/src/add-ons/accelerants/common/validate_display_mode.cpp @@ -0,0 +1,128 @@ +/* + * Copyright 2011, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include + + +static uint16 +round(uint16 value, uint16 resolution) +{ + return value / resolution * resolution; +} + + +static void +sanitize_timing(uint16& display, uint16& syncStart, uint16& syncEnd, + uint16& total, const timing_constraints& constraints) +{ + if (syncStart < display + constraints.min_before_sync) + syncStart = display + constraints.min_before_sync; + else if (syncStart > constraints.max_sync_start) + syncStart = constraints.max_sync_start; + + uint32 syncLength = syncEnd - syncStart; + if (syncLength < constraints.min_sync_length) + syncLength = constraints.min_sync_length; + else if (syncLength > constraints.max_sync_length) + syncLength = constraints.max_sync_length; + + if (total < syncStart + syncLength + constraints.min_after_sync) + total = syncStart + syncLength + constraints.min_after_sync; + + if (total > constraints.max_total) { + total = constraints.max_total; + syncLength = min_c(syncLength, uint16(total - syncStart)); + } + + syncEnd = round(syncStart + syncLength, constraints.resolution); + syncStart = round(syncStart, constraints.resolution); + display = round(display, constraints.resolution); + total = round(total, constraints.resolution); +} + + +/*! Makes sure the passed in \a mode fulfills the specified \a constraints. + Returns whether or not the mode had to be changed. +*/ +bool +sanitize_display_mode(display_mode& mode, + const display_constraints& constraints, const edid1_info* edid) +{ + display_mode originalMode = mode; + + // size + + if (mode.timing.h_display < constraints.min_h_display) + mode.timing.h_display = constraints.min_h_display; + else if (mode.timing.h_display > constraints.max_h_display) + mode.timing.h_display = constraints.max_h_display; + + if (mode.timing.v_display < constraints.min_v_display) + mode.timing.v_display = constraints.min_v_display; + else if (mode.timing.v_display > constraints.max_v_display) + mode.timing.v_display = constraints.max_v_display; + + // horizontal timing + + sanitize_timing(mode.timing.h_display, mode.timing.h_sync_start, + mode.timing.h_sync_end, mode.timing.h_total, + constraints.horizontal_timing); + + // vertical timing + + sanitize_timing(mode.timing.v_display, mode.timing.v_sync_start, + mode.timing.v_sync_end, mode.timing.v_total, + constraints.vertical_timing); + + // TODO: take EDID and pixel clock into account! + + return memcmp(&mode, &originalMode, sizeof(display_mode)) != 0; +} + + +bool +is_display_mode_within_bounds(display_mode& mode, const display_mode& low, + const display_mode& high) +{ + // Check horizontal timing + if (mode.timing.h_display < low.timing.h_display + || mode.timing.h_display > high.timing.h_display + || mode.timing.h_sync_start < low.timing.h_sync_start + || mode.timing.h_sync_start > high.timing.h_sync_start + || mode.timing.h_sync_end < low.timing.h_sync_end + || mode.timing.h_sync_end > high.timing.h_sync_end + || mode.timing.h_total < low.timing.h_total + || mode.timing.h_total > high.timing.h_total) + return false; + + // Check vertical timing + if (mode.timing.h_display < low.timing.h_display + || mode.timing.h_display > high.timing.h_display + || mode.timing.h_sync_start < low.timing.h_sync_start + || mode.timing.h_sync_start > high.timing.h_sync_start + || mode.timing.h_sync_end < low.timing.h_sync_end + || mode.timing.h_sync_end > high.timing.h_sync_end + || mode.timing.h_total < low.timing.h_total + || mode.timing.h_total > high.timing.h_total) + return false; + + // Check pixel clock + if (mode.timing.pixel_clock > high.timing.pixel_clock + || mode.timing.pixel_clock < low.timing.pixel_clock) + return false; + + // Check horizontal size + if (mode.virtual_width > high.virtual_width + || mode.virtual_width < low.virtual_width) + return false; + + // Check vertical size + if (mode.virtual_height > high.virtual_height + || mode.virtual_height < low.virtual_height) + return false; + + return true; +}