[97960] | 1 | /* $Id: display-svga-xf86cvt.cpp 98202 2023-01-22 02:05:53Z vboxsync $ */
|
---|
| 2 | /** @file
|
---|
| 3 | * Guest Additions - Our version of xf86CVTMode.
|
---|
| 4 | */
|
---|
| 5 |
|
---|
[97957] | 6 | /*
|
---|
[97960] | 7 | * Copyright (C) 2006-2023 Oracle and/or its affiliates.
|
---|
| 8 | * This file is based on x.org server 1.18.0 file xf86cvt.c:
|
---|
| 9 | *
|
---|
[97957] | 10 | * Copyright 2005-2006 Luc Verhaegen.
|
---|
| 11 | *
|
---|
| 12 | * Permission is hereby granted, free of charge, to any person obtaining a
|
---|
| 13 | * copy of this software and associated documentation files (the "Software"),
|
---|
| 14 | * to deal in the Software without restriction, including without limitation
|
---|
| 15 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
---|
| 16 | * and/or sell copies of the Software, and to permit persons to whom the
|
---|
| 17 | * Software is furnished to do so, subject to the following conditions:
|
---|
| 18 | *
|
---|
| 19 | * The above copyright notice and this permission notice shall be included in
|
---|
| 20 | * all copies or substantial portions of the Software.
|
---|
| 21 | *
|
---|
| 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
---|
| 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
---|
| 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
---|
| 25 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
---|
| 26 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
---|
| 27 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
---|
| 28 | * OTHER DEALINGS IN THE SOFTWARE.
|
---|
| 29 | */
|
---|
| 30 |
|
---|
[97960] | 31 | #if 0
|
---|
[97957] | 32 | /*
|
---|
| 33 | * The reason for having this function in a file of its own is
|
---|
| 34 | * so that ../utils/cvt/cvt can link to it, and that xf86CVTMode
|
---|
| 35 | * code is shared directly.
|
---|
| 36 | */
|
---|
| 37 |
|
---|
| 38 | #ifdef HAVE_XORG_CONFIG_H
|
---|
| 39 | #include <xorg-config.h>
|
---|
| 40 | #else
|
---|
| 41 | #ifdef HAVE_CONFIG_H
|
---|
| 42 | #include <config.h>
|
---|
| 43 | #endif
|
---|
| 44 | #endif
|
---|
| 45 |
|
---|
| 46 | #include "xf86.h"
|
---|
| 47 | #include "xf86Modes.h"
|
---|
| 48 |
|
---|
| 49 | #include <string.h>
|
---|
[97960] | 50 | #else
|
---|
| 51 | # include "VBoxClient.h"
|
---|
| 52 | # include "display-svga-xf86cvt.h"
|
---|
| 53 | #endif
|
---|
[97957] | 54 |
|
---|
| 55 | /*
|
---|
[97960] | 56 | * This is a slightly modified version of the xf86CVTMode function from
|
---|
| 57 | * xf86cvt.c from the xorg xserver source code. Computes several parameters
|
---|
| 58 | * of a display mode out of horizontal and vertical resolutions. Replicated
|
---|
| 59 | * here to avoid further dependencies.
|
---|
| 60 | *
|
---|
| 61 | *----------------------------------------------------------------------------
|
---|
| 62 | *
|
---|
[97957] | 63 | * Generate a CVT standard mode from HDisplay, VDisplay and VRefresh.
|
---|
| 64 | *
|
---|
| 65 | * These calculations are stolen from the CVT calculation spreadsheet written
|
---|
| 66 | * by Graham Loveridge. He seems to be claiming no copyright and there seems to
|
---|
| 67 | * be no license attached to this. He apparently just wants to see his name
|
---|
| 68 | * mentioned.
|
---|
| 69 | *
|
---|
| 70 | * This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls
|
---|
| 71 | *
|
---|
| 72 | * Comments and structure corresponds to the comments and structure of the xls.
|
---|
| 73 | * This should ease importing of future changes to the standard (not very
|
---|
| 74 | * likely though).
|
---|
| 75 | *
|
---|
| 76 | * About margins; i'm sure that they are to be the bit between HDisplay and
|
---|
| 77 | * HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and
|
---|
| 78 | * VTotal, where the overscan colour is shown. FB seems to call _all_ blanking
|
---|
| 79 | * outside sync "margin" for some reason. Since we prefer seeing proper
|
---|
| 80 | * blanking instead of the overscan colour, and since the Crtc* values will
|
---|
| 81 | * probably get altered after us, we will disable margins altogether. With
|
---|
| 82 | * these calculations, Margins will plainly expand H/VDisplay, and we don't
|
---|
| 83 | * want that. -- libv
|
---|
| 84 | *
|
---|
| 85 | */
|
---|
[97960] | 86 | DisplayModeR VBoxClient_xf86CVTMode(int HDisplay, int VDisplay, float VRefresh /* Herz */, bool Reduced, bool Interlaced)
|
---|
[97957] | 87 | {
|
---|
[97960] | 88 | DisplayModeR Mode;
|
---|
[97957] | 89 |
|
---|
| 90 | /* 1) top/bottom margin size (% of height) - default: 1.8 */
|
---|
| 91 | #define CVT_MARGIN_PERCENTAGE 1.8
|
---|
| 92 |
|
---|
| 93 | /* 2) character cell horizontal granularity (pixels) - default 8 */
|
---|
| 94 | #define CVT_H_GRANULARITY 8
|
---|
| 95 |
|
---|
| 96 | /* 4) Minimum vertical porch (lines) - default 3 */
|
---|
| 97 | #define CVT_MIN_V_PORCH 3
|
---|
| 98 |
|
---|
| 99 | /* 4) Minimum number of vertical back porch lines - default 6 */
|
---|
| 100 | #define CVT_MIN_V_BPORCH 6
|
---|
| 101 |
|
---|
| 102 | /* Pixel Clock step (kHz) */
|
---|
| 103 | #define CVT_CLOCK_STEP 250
|
---|
| 104 |
|
---|
[97960] | 105 | bool Margins = false;
|
---|
[97957] | 106 | float VFieldRate, HPeriod;
|
---|
| 107 | int HDisplayRnd, HMargin;
|
---|
| 108 | int VDisplayRnd, VMargin, VSync;
|
---|
| 109 | float Interlace; /* Please rename this */
|
---|
| 110 |
|
---|
| 111 | /* CVT default is 60.0Hz */
|
---|
| 112 | if (!VRefresh)
|
---|
| 113 | VRefresh = 60.0;
|
---|
| 114 |
|
---|
| 115 | /* 1. Required field rate */
|
---|
| 116 | if (Interlaced)
|
---|
| 117 | VFieldRate = VRefresh * 2;
|
---|
| 118 | else
|
---|
| 119 | VFieldRate = VRefresh;
|
---|
| 120 |
|
---|
| 121 | /* 2. Horizontal pixels */
|
---|
| 122 | HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY);
|
---|
| 123 |
|
---|
| 124 | /* 3. Determine left and right borders */
|
---|
| 125 | if (Margins) {
|
---|
| 126 | /* right margin is actually exactly the same as left */
|
---|
[97960] | 127 | HMargin = (int)((float)HDisplayRnd * CVT_MARGIN_PERCENTAGE / 100.0);
|
---|
[97957] | 128 | HMargin -= HMargin % CVT_H_GRANULARITY;
|
---|
| 129 | }
|
---|
| 130 | else
|
---|
| 131 | HMargin = 0;
|
---|
| 132 |
|
---|
| 133 | /* 4. Find total active pixels */
|
---|
[97960] | 134 | Mode.HDisplay = HDisplayRnd + 2 * HMargin;
|
---|
[97957] | 135 |
|
---|
| 136 | /* 5. Find number of lines per field */
|
---|
| 137 | if (Interlaced)
|
---|
| 138 | VDisplayRnd = VDisplay / 2;
|
---|
| 139 | else
|
---|
| 140 | VDisplayRnd = VDisplay;
|
---|
| 141 |
|
---|
| 142 | /* 6. Find top and bottom margins */
|
---|
| 143 | /* nope. */
|
---|
| 144 | if (Margins)
|
---|
| 145 | /* top and bottom margins are equal again. */
|
---|
[97960] | 146 | VMargin = (int)((float)VDisplayRnd * CVT_MARGIN_PERCENTAGE / 100.0);
|
---|
[97957] | 147 | else
|
---|
| 148 | VMargin = 0;
|
---|
| 149 |
|
---|
[97960] | 150 | Mode.VDisplay = VDisplay + 2 * VMargin;
|
---|
[97957] | 151 |
|
---|
| 152 | /* 7. Interlace */
|
---|
| 153 | if (Interlaced)
|
---|
| 154 | Interlace = 0.5;
|
---|
| 155 | else
|
---|
| 156 | Interlace = 0.0;
|
---|
| 157 |
|
---|
| 158 | /* Determine VSync Width from aspect ratio */
|
---|
| 159 | if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay))
|
---|
| 160 | VSync = 4;
|
---|
| 161 | else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay))
|
---|
| 162 | VSync = 5;
|
---|
| 163 | else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay))
|
---|
| 164 | VSync = 6;
|
---|
| 165 | else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay))
|
---|
| 166 | VSync = 7;
|
---|
| 167 | else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay))
|
---|
| 168 | VSync = 7;
|
---|
| 169 | else /* Custom */
|
---|
| 170 | VSync = 10;
|
---|
| 171 |
|
---|
| 172 | if (!Reduced) { /* simplified GTF calculation */
|
---|
| 173 |
|
---|
| 174 | /* 4) Minimum time of vertical sync + back porch interval (µs)
|
---|
| 175 | * default 550.0 */
|
---|
| 176 | #define CVT_MIN_VSYNC_BP 550.0
|
---|
| 177 |
|
---|
| 178 | /* 3) Nominal HSync width (% of line period) - default 8 */
|
---|
| 179 | #define CVT_HSYNC_PERCENTAGE 8
|
---|
| 180 |
|
---|
| 181 | float HBlankPercentage;
|
---|
| 182 | int VSyncAndBackPorch, VBackPorch;
|
---|
| 183 | int HBlank;
|
---|
| 184 |
|
---|
| 185 | /* 8. Estimated Horizontal period */
|
---|
[97960] | 186 | HPeriod = ((float)(1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP))
|
---|
| 187 | / (VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace);
|
---|
[97957] | 188 |
|
---|
| 189 | /* 9. Find number of lines in sync + backporch */
|
---|
[97960] | 190 | if ((int)(CVT_MIN_VSYNC_BP / HPeriod) + 1 < VSync + CVT_MIN_V_PORCH)
|
---|
[97957] | 191 | VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH;
|
---|
| 192 | else
|
---|
[97960] | 193 | VSyncAndBackPorch = (int)(CVT_MIN_VSYNC_BP / HPeriod) + 1;
|
---|
[97957] | 194 |
|
---|
| 195 | /* 10. Find number of lines in back porch */
|
---|
| 196 | VBackPorch = VSyncAndBackPorch - VSync;
|
---|
| 197 | (void) VBackPorch;
|
---|
| 198 |
|
---|
| 199 | /* 11. Find total number of lines in vertical field */
|
---|
[98202] | 200 | Mode.VTotal = (int)(VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace + CVT_MIN_V_PORCH);
|
---|
[97957] | 201 |
|
---|
| 202 | /* 5) Definition of Horizontal blanking time limitation */
|
---|
| 203 | /* Gradient (%/kHz) - default 600 */
|
---|
| 204 | #define CVT_M_FACTOR 600
|
---|
| 205 |
|
---|
| 206 | /* Offset (%) - default 40 */
|
---|
| 207 | #define CVT_C_FACTOR 40
|
---|
| 208 |
|
---|
| 209 | /* Blanking time scaling factor - default 128 */
|
---|
| 210 | #define CVT_K_FACTOR 128
|
---|
| 211 |
|
---|
| 212 | /* Scaling factor weighting - default 20 */
|
---|
| 213 | #define CVT_J_FACTOR 20
|
---|
| 214 |
|
---|
[97960] | 215 | #define CVT_M_PRIME (CVT_M_FACTOR * CVT_K_FACTOR / 256)
|
---|
| 216 | #define CVT_C_PRIME ((CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + CVT_J_FACTOR)
|
---|
[97957] | 217 |
|
---|
| 218 | /* 12. Find ideal blanking duty cycle from formula */
|
---|
| 219 | HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod / 1000.0;
|
---|
| 220 |
|
---|
| 221 | /* 13. Blanking time */
|
---|
| 222 | if (HBlankPercentage < 20)
|
---|
| 223 | HBlankPercentage = 20;
|
---|
| 224 |
|
---|
[97960] | 225 | HBlank = (int)(Mode.HDisplay * HBlankPercentage / (100.0 - HBlankPercentage));
|
---|
[97957] | 226 | HBlank -= HBlank % (2 * CVT_H_GRANULARITY);
|
---|
| 227 |
|
---|
| 228 | /* 14. Find total number of pixels in a line. */
|
---|
[97960] | 229 | Mode.HTotal = Mode.HDisplay + HBlank;
|
---|
[97957] | 230 |
|
---|
| 231 | /* Fill in HSync values */
|
---|
[97960] | 232 | Mode.HSyncEnd = Mode.HDisplay + HBlank / 2;
|
---|
[97957] | 233 |
|
---|
[97960] | 234 | Mode.HSyncStart = Mode.HSyncEnd - (Mode.HTotal * CVT_HSYNC_PERCENTAGE) / 100;
|
---|
| 235 | Mode.HSyncStart += CVT_H_GRANULARITY - Mode.HSyncStart % CVT_H_GRANULARITY;
|
---|
[97957] | 236 |
|
---|
| 237 | /* Fill in VSync values */
|
---|
[97960] | 238 | Mode.VSyncStart = Mode.VDisplay + CVT_MIN_V_PORCH;
|
---|
| 239 | Mode.VSyncEnd = Mode.VSyncStart + VSync;
|
---|
[97957] | 240 |
|
---|
| 241 | }
|
---|
| 242 | else { /* Reduced blanking */
|
---|
| 243 | /* Minimum vertical blanking interval time (µs) - default 460 */
|
---|
| 244 | #define CVT_RB_MIN_VBLANK 460.0
|
---|
| 245 |
|
---|
| 246 | /* Fixed number of clocks for horizontal sync */
|
---|
| 247 | #define CVT_RB_H_SYNC 32.0
|
---|
| 248 |
|
---|
| 249 | /* Fixed number of clocks for horizontal blanking */
|
---|
| 250 | #define CVT_RB_H_BLANK 160.0
|
---|
| 251 |
|
---|
| 252 | /* Fixed number of lines for vertical front porch - default 3 */
|
---|
| 253 | #define CVT_RB_VFPORCH 3
|
---|
| 254 |
|
---|
| 255 | int VBILines;
|
---|
| 256 |
|
---|
| 257 | /* 8. Estimate Horizontal period. */
|
---|
[97960] | 258 | HPeriod = ((float)(1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) / (VDisplayRnd + 2 * VMargin);
|
---|
[97957] | 259 |
|
---|
| 260 | /* 9. Find number of lines in vertical blanking */
|
---|
[97960] | 261 | VBILines = (int)((float)CVT_RB_MIN_VBLANK / HPeriod + 1);
|
---|
[97957] | 262 |
|
---|
| 263 | /* 10. Check if vertical blanking is sufficient */
|
---|
[97960] | 264 | if (VBILines < CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH)
|
---|
[97957] | 265 | VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH;
|
---|
| 266 |
|
---|
| 267 | /* 11. Find total number of lines in vertical field */
|
---|
[97960] | 268 | Mode.VTotal = (int)(VDisplayRnd + 2 * VMargin + Interlace + VBILines);
|
---|
[97957] | 269 |
|
---|
| 270 | /* 12. Find total number of pixels in a line */
|
---|
[97960] | 271 | Mode.HTotal = (int)(Mode.HDisplay + CVT_RB_H_BLANK);
|
---|
[97957] | 272 |
|
---|
| 273 | /* Fill in HSync values */
|
---|
[97960] | 274 | Mode.HSyncEnd = (int)(Mode.HDisplay + CVT_RB_H_BLANK / 2);
|
---|
| 275 | Mode.HSyncStart = (int)(Mode.HSyncEnd - CVT_RB_H_SYNC);
|
---|
[97957] | 276 |
|
---|
| 277 | /* Fill in VSync values */
|
---|
[97960] | 278 | Mode.VSyncStart = Mode.VDisplay + CVT_RB_VFPORCH;
|
---|
| 279 | Mode.VSyncEnd = Mode.VSyncStart + VSync;
|
---|
[97957] | 280 | }
|
---|
| 281 | /* 15/13. Find pixel clock frequency (kHz for xf86) */
|
---|
[97960] | 282 | Mode.Clock = (int)(Mode.HTotal * 1000.0 / HPeriod);
|
---|
| 283 | Mode.Clock -= Mode.Clock % CVT_CLOCK_STEP;
|
---|
[97957] | 284 |
|
---|
| 285 | /* 16/14. Find actual Horizontal Frequency (kHz) */
|
---|
[97960] | 286 | Mode.HSync = (float)Mode.Clock / (float)Mode.HTotal;
|
---|
[97957] | 287 |
|
---|
| 288 | /* 17/15. Find actual Field rate */
|
---|
[97960] | 289 | Mode.VRefresh = (1000.0 * (float)Mode.Clock) / (float)(Mode.HTotal * Mode.VTotal);
|
---|
[97957] | 290 |
|
---|
| 291 | /* 18/16. Find actual vertical frame frequency */
|
---|
| 292 | /* ignore - just set the mode flag for interlaced */
|
---|
| 293 | if (Interlaced)
|
---|
[97960] | 294 | Mode.VTotal *= 2;
|
---|
[97957] | 295 |
|
---|
[97960] | 296 | #if 0
|
---|
[97957] | 297 | XNFasprintf(&tmp, "%dx%d", HDisplay, VDisplay);
|
---|
| 298 | Mode->name = tmp;
|
---|
| 299 |
|
---|
| 300 | if (Reduced)
|
---|
| 301 | Mode->Flags |= V_PHSYNC | V_NVSYNC;
|
---|
| 302 | else
|
---|
| 303 | Mode->Flags |= V_NHSYNC | V_PVSYNC;
|
---|
| 304 |
|
---|
| 305 | if (Interlaced)
|
---|
| 306 | Mode->Flags |= V_INTERLACE;
|
---|
[97960] | 307 | #endif
|
---|
[97957] | 308 |
|
---|
| 309 | return Mode;
|
---|
| 310 | }
|
---|