• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.display.mode;
18 
19 import android.util.Size;
20 import android.view.Display;
21 
22 import com.android.server.display.DisplayDeviceConfig;
23 import com.android.server.display.feature.DisplayManagerFlags;
24 
25 import java.util.ArrayList;
26 import java.util.LinkedHashMap;
27 import java.util.List;
28 import java.util.Map;
29 
30 /**
31  * When selected by app synthetic modes will only affect render rate switch rather than mode switch
32  */
33 public class SyntheticModeManager {
34     private static final float FLOAT_TOLERANCE = 0.01f;
35     private static final float SYNTHETIC_MODE_REFRESH_RATE = 60f;
36     private static final float SYNTHETIC_MODE_HIGH_BOUNDARY =
37             SYNTHETIC_MODE_REFRESH_RATE + FLOAT_TOLERANCE;
38 
39     private final boolean mSynthetic60HzModesEnabled;
40     private final boolean mHasArrSupportEnabled;
41 
SyntheticModeManager(DisplayManagerFlags flags)42     public SyntheticModeManager(DisplayManagerFlags flags) {
43         mSynthetic60HzModesEnabled = flags.isSynthetic60HzModesEnabled();
44         mHasArrSupportEnabled = flags.hasArrSupportFlag();
45     }
46 
47     /**
48      * creates display supportedModes array, exposed to applications
49      */
createAppSupportedModes(DisplayDeviceConfig config, Display.Mode[] modes, boolean hasArrSupport)50     public Display.Mode[] createAppSupportedModes(DisplayDeviceConfig config,
51             Display.Mode[] modes, boolean hasArrSupport) {
52         // TODO(b/361433651) Remove config.isVrrSupportEnabled once hasArrSupport is rolled out
53         boolean isArrSupported =
54                 mHasArrSupportEnabled ? hasArrSupport : config.isVrrSupportEnabled();
55         if (!isArrSupported || !mSynthetic60HzModesEnabled) {
56             return modes;
57         }
58         List<Display.Mode> appSupportedModes = new ArrayList<>();
59         Map<Size, int[]> sizes = new LinkedHashMap<>();
60         int nextModeId = 0;
61         // exclude "real" 60Hz modes and below for VRR displays,
62         // they will be replaced with synthetic 60Hz mode
63         // for VRR display there should be "real" mode with rr > 60Hz
64         for (Display.Mode mode : modes) {
65             if (mode.getRefreshRate() > SYNTHETIC_MODE_HIGH_BOUNDARY) {
66                 appSupportedModes.add(mode);
67             }
68             if (mode.getModeId() > nextModeId) {
69                 nextModeId = mode.getModeId();
70             }
71 
72             float divisor = mode.getVsyncRate() / SYNTHETIC_MODE_REFRESH_RATE;
73             boolean is60HzAchievable = Math.abs(divisor - Math.round(divisor)) < FLOAT_TOLERANCE;
74             if (is60HzAchievable) {
75                 sizes.put(new Size(mode.getPhysicalWidth(), mode.getPhysicalHeight()),
76                         mode.getSupportedHdrTypes());
77             }
78         }
79         // even if VRR display does not have 60Hz mode, we are still adding synthetic 60Hz mode
80         // for each screen size
81         // vsync rate, alternativeRates and hdrTypes  are not important for synthetic mode,
82         // only refreshRate and size are used for DisplayModeDirector votes.
83         for (Map.Entry<Size, int[]> entry: sizes.entrySet()) {
84             nextModeId++;
85             Size size = entry.getKey();
86             int[] hdrTypes = entry.getValue();
87             appSupportedModes.add(
88                     new Display.Mode(nextModeId, size.getWidth(), size.getHeight(), 60f, 60f, true,
89                             new float[0], hdrTypes));
90         }
91         Display.Mode[] appSupportedModesArr = new Display.Mode[appSupportedModes.size()];
92         return appSupportedModes.toArray(appSupportedModesArr);
93     }
94 }
95