From 6ea2c001f9d23c91113b937fb99053e262d21df6 Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Thu, 25 Mar 2021 10:17:49 +0100 Subject: [PATCH] xwayland: Use libxcvt Xwayland is using a copy of the CVT generator found in Xorg. Rather than duplicating the code within the xserver tree, use the libxcvt implementation instead. Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1142 Signed-off-by: Olivier Fourdan Reviewed-by: Matt Turner --- hw/xwayland/Makefile.am | 6 +- hw/xwayland/xwayland-cvt.c | 286 +++---------------------------------- 2 files changed, 23 insertions(+), 269 deletions(-) diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am index 088ec5e66..0060df70a 100644 --- a/hw/xwayland/Makefile.am +++ b/hw/xwayland/Makefile.am @@ -12,7 +12,8 @@ Xwayland_CFLAGS = \ $(XWAYLANDMODULES_CFLAGS) \ $(DIX_CFLAGS) \ $(GLAMOR_CFLAGS) \ - $(GBM_CFLAGS) + $(GBM_CFLAGS) \ + $(LIBXCVT_CFLAGS) Xwayland_SOURCES = \ xwayland.c \ @@ -60,7 +61,8 @@ Xwayland_LDADD = \ $(GLXVND_LIB) \ $(XWAYLAND_SYS_LIBS) \ $(top_builddir)/Xext/libXvidmode.la \ - $(XSERVER_SYS_LIBS) + $(XSERVER_SYS_LIBS) \ + $(LIBXCVT_LIBS) Xwayland_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG) Xwayland_built_sources = diff --git a/hw/xwayland/xwayland-cvt.c b/hw/xwayland/xwayland-cvt.c index 1bc3cec92..ba8cbc9d1 100644 --- a/hw/xwayland/xwayland-cvt.c +++ b/hw/xwayland/xwayland-cvt.c @@ -1,8 +1,6 @@ -/* Copied from hw/xfree86/modes/xf86cvt.c into xwayland DDX and - * changed to generate an RRMode */ - /* * Copyright 2005-2006 Luc Verhaegen. + * Copyright © 2021 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,284 +21,38 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -/* - * The reason for having this function in a file of its own is - * so that ../utils/cvt/cvt can link to it, and that xf86CVTMode - * code is shared directly. - */ - #include #include #include +#include #include "xwayland-cvt.h" -/* - * Generate a CVT standard mode from HDisplay, VDisplay and VRefresh. - * - * These calculations are stolen from the CVT calculation spreadsheet written - * by Graham Loveridge. He seems to be claiming no copyright and there seems to - * be no license attached to this. He apparently just wants to see his name - * mentioned. - * - * This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls - * - * Comments and structure corresponds to the comments and structure of the xls. - * This should ease importing of future changes to the standard (not very - * likely though). - * - * About margins; i'm sure that they are to be the bit between HDisplay and - * HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and - * VTotal, where the overscan colour is shown. FB seems to call _all_ blanking - * outside sync "margin" for some reason. Since we prefer seeing proper - * blanking instead of the overscan colour, and since the Crtc* values will - * probably get altered after us, we will disable margins altogether. With - * these calculations, Margins will plainly expand H/VDisplay, and we don't - * want that. -- libv - * - */ RRModePtr -xwayland_cvt(int HDisplay, int VDisplay, float VRefresh, Bool Reduced, - Bool Interlaced) +xwayland_cvt(int hdisplay, int vdisplay, float vrefresh, Bool reduced, + Bool interlaced) { - /* 1) top/bottom margin size (% of height) - default: 1.8 */ -#define CVT_MARGIN_PERCENTAGE 1.8 - - /* 2) character cell horizontal granularity (pixels) - default 8 */ -#define CVT_H_GRANULARITY 8 - - /* 4) Minimum vertical porch (lines) - default 3 */ -#define CVT_MIN_V_PORCH 3 - - /* 4) Minimum number of vertical back porch lines - default 6 */ -#define CVT_MIN_V_BPORCH 6 - - /* Pixel Clock step (kHz) */ -#define CVT_CLOCK_STEP 250 - - Bool Margins = FALSE; - float VFieldRate, HPeriod; - int HDisplayRnd, HMargin; - int VDisplayRnd, VMargin, VSync; - float Interlace; /* Please rename this */ + struct libxcvt_mode_info *libxcvt_mode_info; char name[128]; xRRModeInfo modeinfo; + libxcvt_mode_info = + libxcvt_gen_mode_info(hdisplay, vdisplay, vrefresh, reduced, interlaced); + memset(&modeinfo, 0, sizeof modeinfo); + modeinfo.width = libxcvt_mode_info->hdisplay; + modeinfo.height = libxcvt_mode_info->vdisplay; + modeinfo.dotClock = libxcvt_mode_info->dot_clock * 1000.0; + modeinfo.hSyncStart = libxcvt_mode_info->hsync_start; + modeinfo.hSyncEnd = libxcvt_mode_info->hsync_end; + modeinfo.hTotal = libxcvt_mode_info->htotal; + modeinfo.vSyncStart = libxcvt_mode_info->vsync_start; + modeinfo.vSyncEnd = libxcvt_mode_info->vsync_end; + modeinfo.vTotal = libxcvt_mode_info->vtotal; + modeinfo.modeFlags = libxcvt_mode_info->mode_flags; - /* CVT default is 60.0Hz */ - if (!VRefresh) - VRefresh = 60.0; - - /* 1. Required field rate */ - if (Interlaced) - VFieldRate = VRefresh * 2; - else - VFieldRate = VRefresh; - - /* 2. Horizontal pixels */ - HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY); - - /* 3. Determine left and right borders */ - if (Margins) { - /* right margin is actually exactly the same as left */ - HMargin = (((float) HDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0); - HMargin -= HMargin % CVT_H_GRANULARITY; - } - else - HMargin = 0; - - /* 4. Find total active pixels */ - modeinfo.width = HDisplayRnd + 2 * HMargin; - - /* 5. Find number of lines per field */ - if (Interlaced) - VDisplayRnd = VDisplay / 2; - else - VDisplayRnd = VDisplay; - - /* 6. Find top and bottom margins */ - /* nope. */ - if (Margins) - /* top and bottom margins are equal again. */ - VMargin = (((float) VDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0); - else - VMargin = 0; - - modeinfo.height = VDisplay + 2 * VMargin; - - /* 7. Interlace */ - if (Interlaced) - Interlace = 0.5; - else - Interlace = 0.0; - - /* Determine VSync Width from aspect ratio */ - if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay)) - VSync = 4; - else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay)) - VSync = 5; - else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay)) - VSync = 6; - else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay)) - VSync = 7; - else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay)) - VSync = 7; - else /* Custom */ - VSync = 10; - - if (!Reduced) { /* simplified GTF calculation */ - - /* 4) Minimum time of vertical sync + back porch interval (µs) - * default 550.0 */ -#define CVT_MIN_VSYNC_BP 550.0 - - /* 3) Nominal HSync width (% of line period) - default 8 */ -#define CVT_HSYNC_PERCENTAGE 8 - - float HBlankPercentage; - int VSyncAndBackPorch, VBackPorch; - int HBlank; - - /* 8. Estimated Horizontal period */ - HPeriod = ((float) (1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP)) / - (VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace); - - /* 9. Find number of lines in sync + backporch */ - if (((int) (CVT_MIN_VSYNC_BP / HPeriod) + 1) < - (VSync + CVT_MIN_V_PORCH)) - VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH; - else - VSyncAndBackPorch = (int) (CVT_MIN_VSYNC_BP / HPeriod) + 1; - - /* 10. Find number of lines in back porch */ - VBackPorch = VSyncAndBackPorch - VSync; - (void) VBackPorch; - - /* 11. Find total number of lines in vertical field */ - modeinfo.vTotal = - VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace + - CVT_MIN_V_PORCH; - - /* 5) Definition of Horizontal blanking time limitation */ - /* Gradient (%/kHz) - default 600 */ -#define CVT_M_FACTOR 600 - - /* Offset (%) - default 40 */ -#define CVT_C_FACTOR 40 - - /* Blanking time scaling factor - default 128 */ -#define CVT_K_FACTOR 128 - - /* Scaling factor weighting - default 20 */ -#define CVT_J_FACTOR 20 - -#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256 -#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \ - CVT_J_FACTOR - - /* 12. Find ideal blanking duty cycle from formula */ - HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod / 1000.0; - - /* 13. Blanking time */ - if (HBlankPercentage < 20) - HBlankPercentage = 20; - - HBlank = modeinfo.width * HBlankPercentage / (100.0 - HBlankPercentage); - HBlank -= HBlank % (2 * CVT_H_GRANULARITY); - - /* 14. Find total number of pixels in a line. */ - modeinfo.hTotal = modeinfo.width + HBlank; - - /* Fill in HSync values */ - modeinfo.hSyncEnd = modeinfo.width + HBlank / 2; - - modeinfo.hSyncStart = modeinfo.hSyncEnd - - (modeinfo.hTotal * CVT_HSYNC_PERCENTAGE) / 100; - modeinfo.hSyncStart += CVT_H_GRANULARITY - - modeinfo.hSyncStart % CVT_H_GRANULARITY; - - /* Fill in VSync values */ - modeinfo.vSyncStart = modeinfo.height + CVT_MIN_V_PORCH; - modeinfo.vSyncEnd = modeinfo.vSyncStart + VSync; - - } - else { /* Reduced blanking */ - /* Minimum vertical blanking interval time (µs) - default 460 */ -#define CVT_RB_MIN_VBLANK 460.0 - - /* Fixed number of clocks for horizontal sync */ -#define CVT_RB_H_SYNC 32.0 - - /* Fixed number of clocks for horizontal blanking */ -#define CVT_RB_H_BLANK 160.0 - - /* Fixed number of lines for vertical front porch - default 3 */ -#define CVT_RB_VFPORCH 3 - - int VBILines; - - /* 8. Estimate Horizontal period. */ - HPeriod = ((float) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) / - (VDisplayRnd + 2 * VMargin); - - /* 9. Find number of lines in vertical blanking */ - VBILines = ((float) CVT_RB_MIN_VBLANK) / HPeriod + 1; - - /* 10. Check if vertical blanking is sufficient */ - if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH)) - VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH; - - /* 11. Find total number of lines in vertical field */ - modeinfo.vTotal = VDisplayRnd + 2 * VMargin + Interlace + VBILines; - - /* 12. Find total number of pixels in a line */ - modeinfo.hTotal = modeinfo.width + CVT_RB_H_BLANK; - - /* Fill in HSync values */ - modeinfo.hSyncEnd = modeinfo.width + CVT_RB_H_BLANK / 2; - modeinfo.hSyncStart = modeinfo.hSyncEnd - CVT_RB_H_SYNC; - - /* Fill in VSync values */ - modeinfo.vSyncStart = modeinfo.height + CVT_RB_VFPORCH; - modeinfo.vSyncEnd = modeinfo.vSyncStart + VSync; - } - - /* 15/13. Find pixel clock frequency (kHz for xf86) */ - modeinfo.dotClock = modeinfo.hTotal * 1000.0 / HPeriod; - modeinfo.dotClock -= modeinfo.dotClock % CVT_CLOCK_STEP; - modeinfo.dotClock *= 1000.0; -#if 0 - /* 16/14. Find actual Horizontal Frequency (kHz) */ - modeinfo.hSync = ((float) modeinfo.dotClock) / ((float) modeinfo.hTotal); -#endif - -#if 0 - /* 17/15. Find actual Field rate */ - modeinfo.vRefresh = (1000.0 * ((float) modeinfo.dotClock)) / - ((float) (modeinfo.hTotal * modeinfo.vTotal)); -#endif - - /* 18/16. Find actual vertical frame frequency */ - /* ignore - just set the mode flag for interlaced */ - if (Interlaced) - modeinfo.vTotal *= 2; - - if (Reduced) - modeinfo.modeFlags |= RR_HSyncPositive | RR_VSyncNegative; - else - modeinfo.modeFlags |= RR_HSyncNegative | RR_VSyncPositive; - - if (Interlaced) - modeinfo.modeFlags |= RR_Interlace; - - /* FWXGA hack adapted from hw/xfree86/modes/xf86EdidModes.c, because you can't say 1366 */ - if (HDisplay == 1366 && VDisplay == 768) { - modeinfo.width = 1366; - modeinfo.hSyncStart--; - modeinfo.hSyncEnd--; - } + free(libxcvt_mode_info); snprintf(name, sizeof name, "%dx%d", modeinfo.width, modeinfo.height);