summaryrefslogtreecommitdiffstats
path: root/gfx/thebes/DisplayConfigWindows.cpp
blob: 49fc13c580b77734f0c6bfd5496fa09a097f236d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <iostream>
#include <windows.h>
#include <wingdi.h>
#include <optional>
#include <vector>

#include "DisplayConfigWindows.h"

namespace mozilla {
namespace gfx {

using namespace std;

struct DisplayConfig {
  vector<DISPLAYCONFIG_PATH_INFO> mPaths;
  vector<DISPLAYCONFIG_MODE_INFO> mModes;
};

optional<DisplayConfig> GetDisplayConfig() {
  LONG result;

  UINT32 numPaths;
  UINT32 numModes;
  vector<DISPLAYCONFIG_PATH_INFO> paths;
  vector<DISPLAYCONFIG_MODE_INFO> modes;
  do {
    result = GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &numPaths,
                                         &numModes);
    if (result != ERROR_SUCCESS) {
      return {};
    }
    // allocate the recommended amount of space
    paths.resize(numPaths);
    modes.resize(numModes);

    result = QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &numPaths, paths.data(),
                                &numModes, modes.data(), NULL);
    // try again if there wasn't enough space
  } while (result == ERROR_INSUFFICIENT_BUFFER);

  if (result != ERROR_SUCCESS) return {};

  // shrink to fit the actual number of modes and paths returned
  modes.resize(numModes);
  paths.resize(numPaths);

  return DisplayConfig{paths, modes};
}

bool HasScaledResolution() {
  auto config = GetDisplayConfig();
  if (config) {
    for (auto& path : config->mPaths) {
      auto& modes = config->mModes;
      int targetModeIndex = path.targetInfo.modeInfoIdx;
      int sourceModeIndex = path.sourceInfo.modeInfoIdx;

      // Check if the source and target resolutions are different
      if ((modes[targetModeIndex]
               .targetMode.targetVideoSignalInfo.activeSize.cx !=
           modes[sourceModeIndex].sourceMode.width) ||
          (modes[targetModeIndex]
               .targetMode.targetVideoSignalInfo.activeSize.cy !=
           modes[sourceModeIndex].sourceMode.height)) {
        return true;
      }
    }
  }
  return false;
}

void GetScaledResolutions(ScaledResolutionSet& aRv) {
  auto config = GetDisplayConfig();
  if (config) {
    for (auto& path : config->mPaths) {
      auto& modes = config->mModes;
      int targetModeIndex = path.targetInfo.modeInfoIdx;
      int sourceModeIndex = path.sourceInfo.modeInfoIdx;

      // Check if the source and target resolutions are different
      IntSize src(modes[sourceModeIndex].sourceMode.width,
                  modes[sourceModeIndex].sourceMode.height);
      IntSize dst(
          modes[targetModeIndex].targetMode.targetVideoSignalInfo.activeSize.cx,
          modes[targetModeIndex]
              .targetMode.targetVideoSignalInfo.activeSize.cy);
      if (src != dst) {
        aRv.AppendElement(std::pair<IntSize, IntSize>{src, dst});
      }
    }
  }
}

}  // namespace gfx
}  // namespace mozilla