blob: 65c3839141064fa44e39a3b2530c36cc1d5c2547 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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
Dan Stoza9e56aa02015-11-02 13:00:03 -080017// #define LOG_NDEBUG 0
18#undef LOG_TAG
19#define LOG_TAG "DisplayDevice"
20
Chia-I Wu0607fbe2018-05-18 10:59:36 -070021#include <array>
22#include <unordered_set>
23
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080024#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
27#include <math.h>
28
29#include <cutils/properties.h>
30
Mathias Agopian076b1cc2009-04-10 14:24:30 -070031#include <utils/RefBase.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080032#include <utils/Log.h>
33
Courtney Goeltzenleuchter152279d2017-08-14 18:18:30 -060034#include <ui/DebugUtils.h>
Mathias Agopianc666cae2012-07-25 18:56:13 -070035#include <ui/DisplayInfo.h>
Mathias Agopian076b1cc2009-04-10 14:24:30 -070036#include <ui/PixelFormat.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080037
Mathias Agopiane3c697f2013-02-14 17:11:02 -080038#include <gui/Surface.h>
Jamie Gennis1a4d8832012-08-02 20:11:05 -070039
Mathias Agopian076b1cc2009-04-10 14:24:30 -070040#include <hardware/gralloc.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080041
Jesse Hall99c7dbb2013-03-14 14:29:29 -070042#include "DisplayHardware/DisplaySurface.h"
Mathias Agopian1b031492012-06-20 17:51:20 -070043#include "DisplayHardware/HWComposer.h"
Dan Stoza9e56aa02015-11-02 13:00:03 -080044#include "DisplayHardware/HWC2.h"
Mathias Agopian875d8e12013-06-07 15:35:48 -070045#include "RenderEngine/RenderEngine.h"
Mathias Agopian1b031492012-06-20 17:51:20 -070046
Mathias Agopianda8d0a52012-09-04 15:05:38 -070047#include "clz.h"
Mathias Agopian0f2f5ff2012-07-31 23:09:07 -070048#include "DisplayDevice.h"
Mathias Agopianc7d14e22011-08-01 16:32:21 -070049#include "SurfaceFlinger.h"
Mathias Agopian13127d82013-03-05 17:47:11 -080050#include "Layer.h"
Mathias Agopian1f7bec62010-06-25 18:02:21 -070051
Jaesoo Lee720a7242017-01-31 15:26:18 +090052#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
53#include <configstore/Utils.h>
54
Peiyong Linfd997e02018-03-28 15:29:00 -070055namespace android {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080056
Jaesoo Lee720a7242017-01-31 15:26:18 +090057// retrieve triple buffer setting from configstore
58using namespace android::hardware::configstore;
59using namespace android::hardware::configstore::V1_0;
Peiyong Linfd997e02018-03-28 15:29:00 -070060using android::ui::ColorMode;
Chia-I Wu0607fbe2018-05-18 10:59:36 -070061using android::ui::Dataspace;
Peiyong Lin62665892018-04-16 11:07:44 -070062using android::ui::Hdr;
Peiyong Lindd9b2ae2018-03-01 16:22:45 -080063using android::ui::RenderIntent;
Jaesoo Lee720a7242017-01-31 15:26:18 +090064
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080065/*
66 * Initialize the display to the specified values.
67 *
68 */
69
Pablo Ceballos021623b2016-04-15 17:31:51 -070070uint32_t DisplayDevice::sPrimaryDisplayOrientation = 0;
71
Chia-I Wu0607fbe2018-05-18 10:59:36 -070072namespace {
73
74// ordered list of known SDR color modes
75const std::array<ColorMode, 2> sSdrColorModes = {
76 ColorMode::DISPLAY_P3,
77 ColorMode::SRGB,
78};
79
80// ordered list of known HDR color modes
81const std::array<ColorMode, 2> sHdrColorModes = {
82 ColorMode::BT2100_PQ,
83 ColorMode::BT2100_HLG,
84};
85
86// ordered list of known SDR render intents
87const std::array<RenderIntent, 2> sSdrRenderIntents = {
88 RenderIntent::ENHANCE,
89 RenderIntent::COLORIMETRIC,
90};
91
92// ordered list of known HDR render intents
93const std::array<RenderIntent, 2> sHdrRenderIntents = {
94 RenderIntent::TONE_MAP_ENHANCE,
95 RenderIntent::TONE_MAP_COLORIMETRIC,
96};
97
98// map known color mode to dataspace
99Dataspace colorModeToDataspace(ColorMode mode) {
100 switch (mode) {
101 case ColorMode::SRGB:
102 return Dataspace::SRGB;
103 case ColorMode::DISPLAY_P3:
104 return Dataspace::DISPLAY_P3;
105 case ColorMode::BT2100_HLG:
106 return Dataspace::BT2020_HLG;
107 case ColorMode::BT2100_PQ:
108 return Dataspace::BT2020_PQ;
109 default:
110 return Dataspace::UNKNOWN;
111 }
112}
113
114// Return a list of candidate color modes.
115std::vector<ColorMode> getColorModeCandidates(ColorMode mode) {
116 std::vector<ColorMode> candidates;
117
118 // add mode itself
119 candidates.push_back(mode);
120
121 // check if mode is HDR
122 bool isHdr = false;
123 for (auto hdrMode : sHdrColorModes) {
124 if (hdrMode == mode) {
125 isHdr = true;
126 break;
127 }
128 }
129
130 // add other HDR candidates when mode is HDR
131 if (isHdr) {
132 for (auto hdrMode : sHdrColorModes) {
133 if (hdrMode != mode) {
134 candidates.push_back(hdrMode);
135 }
136 }
137 }
138
139 // add other SDR candidates
140 for (auto sdrMode : sSdrColorModes) {
141 if (sdrMode != mode) {
142 candidates.push_back(sdrMode);
143 }
144 }
145
146 return candidates;
147}
148
149// Return a list of candidate render intents.
150std::vector<RenderIntent> getRenderIntentCandidates(RenderIntent intent) {
151 std::vector<RenderIntent> candidates;
152
153 // add intent itself
154 candidates.push_back(intent);
155
156 // check if intent is HDR
157 bool isHdr = false;
158 for (auto hdrIntent : sHdrRenderIntents) {
159 if (hdrIntent == intent) {
160 isHdr = true;
161 break;
162 }
163 }
164
Chia-I Wu0607fbe2018-05-18 10:59:36 -0700165 if (isHdr) {
Chia-I Wuc4b08bd2018-05-29 12:57:23 -0700166 // add other HDR candidates when intent is HDR
Chia-I Wu0607fbe2018-05-18 10:59:36 -0700167 for (auto hdrIntent : sHdrRenderIntents) {
168 if (hdrIntent != intent) {
169 candidates.push_back(hdrIntent);
170 }
171 }
Chia-I Wuc4b08bd2018-05-29 12:57:23 -0700172 } else {
173 // add other SDR candidates when intent is SDR
174 for (auto sdrIntent : sSdrRenderIntents) {
175 if (sdrIntent != intent) {
176 candidates.push_back(sdrIntent);
177 }
178 }
Chia-I Wu0607fbe2018-05-18 10:59:36 -0700179 }
180
181 return candidates;
182}
183
184// Return the best color mode supported by HWC.
185ColorMode getHwcColorMode(
186 const std::unordered_map<ColorMode, std::vector<RenderIntent>>& hwcColorModes,
187 ColorMode mode) {
188 std::vector<ColorMode> candidates = getColorModeCandidates(mode);
189 for (auto candidate : candidates) {
190 auto iter = hwcColorModes.find(candidate);
191 if (iter != hwcColorModes.end()) {
192 return candidate;
193 }
194 }
195
196 return ColorMode::NATIVE;
197}
198
199// Return the best render intent supported by HWC.
200RenderIntent getHwcRenderIntent(const std::vector<RenderIntent>& hwcIntents, RenderIntent intent) {
201 std::vector<RenderIntent> candidates = getRenderIntentCandidates(intent);
202 for (auto candidate : candidates) {
203 for (auto hwcIntent : hwcIntents) {
204 if (candidate == hwcIntent) {
205 return candidate;
206 }
207 }
208 }
209
210 return RenderIntent::COLORIMETRIC;
211}
212
213} // anonymous namespace
214
Courtney Goeltzenleuchter5d943892017-03-22 13:46:46 -0600215// clang-format off
Mathias Agopian0f2f5ff2012-07-31 23:09:07 -0700216DisplayDevice::DisplayDevice(
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800217 const sp<SurfaceFlinger>& flinger,
Jamie Gennisdd3cb842012-10-19 18:19:11 -0700218 DisplayType type,
Jesse Hallffe1f192013-03-22 15:13:48 -0700219 int32_t hwcId,
Jamie Gennisdd3cb842012-10-19 18:19:11 -0700220 bool isSecure,
221 const wp<IBinder>& displayToken,
Lloyd Pique09594832018-01-22 17:48:03 -0800222 const sp<ANativeWindow>& nativeWindow,
Jesse Hall99c7dbb2013-03-14 14:29:29 -0700223 const sp<DisplaySurface>& displaySurface,
Lloyd Pique09594832018-01-22 17:48:03 -0800224 std::unique_ptr<RE::Surface> renderSurface,
225 int displayWidth,
226 int displayHeight,
Chia-I Wu690a76f2018-08-27 14:38:23 -0700227 int displayInstallOrientation,
Peiyong Lindd9b2ae2018-03-01 16:22:45 -0800228 bool hasWideColorGamut,
Peiyong Lin62665892018-04-16 11:07:44 -0700229 const HdrCapabilities& hdrCapabilities,
Peiyong Lin2c327ac2018-04-19 22:06:34 -0700230 const int32_t supportedPerFrameMetadata,
Chia-I Wu0607fbe2018-05-18 10:59:36 -0700231 const std::unordered_map<ColorMode, std::vector<RenderIntent>>& hwcColorModes,
Lloyd Pique09594832018-01-22 17:48:03 -0800232 int initialPowerMode)
Jesse Hallb7a05492014-08-14 15:45:06 -0700233 : lastCompositionHadVisibleLayers(false),
234 mFlinger(flinger),
Dan Stoza9e56aa02015-11-02 13:00:03 -0800235 mType(type),
236 mHwcDisplayId(hwcId),
Chih-Wei Huang27e25622013-01-07 17:33:56 +0800237 mDisplayToken(displayToken),
Lloyd Pique09594832018-01-22 17:48:03 -0800238 mNativeWindow(nativeWindow),
Jesse Hall99c7dbb2013-03-14 14:29:29 -0700239 mDisplaySurface(displaySurface),
Lloyd Pique09594832018-01-22 17:48:03 -0800240 mSurface{std::move(renderSurface)},
241 mDisplayWidth(displayWidth),
242 mDisplayHeight(displayHeight),
Chia-I Wu690a76f2018-08-27 14:38:23 -0700243 mDisplayInstallOrientation(displayInstallOrientation),
Lloyd Pique09594832018-01-22 17:48:03 -0800244 mPageFlipCount(0),
Jamie Gennisdd3cb842012-10-19 18:19:11 -0700245 mIsSecure(isSecure),
Jesse Hall01e29052013-02-19 16:13:35 -0800246 mLayerStack(NO_LAYER_STACK),
Prashant Malani2c9b11f2014-05-25 01:36:31 -0700247 mOrientation(),
Lloyd Pique09594832018-01-22 17:48:03 -0800248 mViewport(Rect::INVALID_RECT),
249 mFrame(Rect::INVALID_RECT),
250 mPowerMode(initialPowerMode),
251 mActiveConfig(0),
Yiwei Zhang7c64f172018-03-07 14:52:28 -0800252 mColorTransform(HAL_COLOR_TRANSFORM_IDENTITY),
Peiyong Lindd9b2ae2018-03-01 16:22:45 -0800253 mHasWideColorGamut(hasWideColorGamut),
Peiyong Lin62665892018-04-16 11:07:44 -0700254 mHasHdr10(false),
255 mHasHLG(false),
Peiyong Lin2c327ac2018-04-19 22:06:34 -0700256 mHasDolbyVision(false),
Chia-I Wu0607fbe2018-05-18 10:59:36 -0700257 mSupportedPerFrameMetadata(supportedPerFrameMetadata)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800258{
Courtney Goeltzenleuchter5d943892017-03-22 13:46:46 -0600259 // clang-format on
Chia-I Wu0607fbe2018-05-18 10:59:36 -0700260 populateColorModes(hwcColorModes);
261
Peiyong Linfb069302018-04-25 14:34:31 -0700262 std::vector<Hdr> types = hdrCapabilities.getSupportedHdrTypes();
263 for (Hdr hdrType : types) {
Peiyong Lin62665892018-04-16 11:07:44 -0700264 switch (hdrType) {
265 case Hdr::HDR10:
266 mHasHdr10 = true;
267 break;
268 case Hdr::HLG:
269 mHasHLG = true;
270 break;
271 case Hdr::DOLBY_VISION:
272 mHasDolbyVision = true;
273 break;
274 default:
275 ALOGE("UNKNOWN HDR capability: %d", static_cast<int32_t>(hdrType));
276 }
277 }
Jesse Hallffe1f192013-03-22 15:13:48 -0700278
Peiyong Linfb069302018-04-25 14:34:31 -0700279 float minLuminance = hdrCapabilities.getDesiredMinLuminance();
280 float maxLuminance = hdrCapabilities.getDesiredMaxLuminance();
281 float maxAverageLuminance = hdrCapabilities.getDesiredMaxAverageLuminance();
282
283 minLuminance = minLuminance <= 0.0 ? sDefaultMinLumiance : minLuminance;
284 maxLuminance = maxLuminance <= 0.0 ? sDefaultMaxLumiance : maxLuminance;
285 maxAverageLuminance = maxAverageLuminance <= 0.0 ? sDefaultMaxLumiance : maxAverageLuminance;
286 if (this->hasWideColorGamut()) {
287 // insert HDR10/HLG as we will force client composition for HDR10/HLG
288 // layers
289 if (!hasHDR10Support()) {
290 types.push_back(Hdr::HDR10);
291 }
292
293 if (!hasHLGSupport()) {
294 types.push_back(Hdr::HLG);
295 }
296 }
297 mHdrCapabilities = HdrCapabilities(types, maxLuminance, maxAverageLuminance, minLuminance);
298
Jesse Hallffe1f192013-03-22 15:13:48 -0700299 // initialize the display orientation transform.
300 setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800301}
302
Lloyd Pique09594832018-01-22 17:48:03 -0800303DisplayDevice::~DisplayDevice() = default;
Mathias Agopian92a979a2012-08-02 18:32:23 -0700304
Jesse Hall02d86562013-03-25 14:43:23 -0700305void DisplayDevice::disconnect(HWComposer& hwc) {
306 if (mHwcDisplayId >= 0) {
307 hwc.disconnectDisplay(mHwcDisplayId);
Jesse Hall02d86562013-03-25 14:43:23 -0700308 mHwcDisplayId = -1;
309 }
310}
311
Mathias Agopian92a979a2012-08-02 18:32:23 -0700312bool DisplayDevice::isValid() const {
Peiyong Lin566a3b42018-01-09 18:22:43 -0800313 return mFlinger != nullptr;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800314}
315
Mathias Agopian0f2f5ff2012-07-31 23:09:07 -0700316int DisplayDevice::getWidth() const {
Mathias Agopiana4912602012-07-12 14:25:33 -0700317 return mDisplayWidth;
318}
319
Mathias Agopian0f2f5ff2012-07-31 23:09:07 -0700320int DisplayDevice::getHeight() const {
Mathias Agopiana4912602012-07-12 14:25:33 -0700321 return mDisplayHeight;
322}
323
Mathias Agopian9e2463e2012-09-21 18:26:16 -0700324void DisplayDevice::setDisplayName(const String8& displayName) {
325 if (!displayName.isEmpty()) {
326 // never override the name with an empty name
327 mDisplayName = displayName;
328 }
329}
330
Mathias Agopian0f2f5ff2012-07-31 23:09:07 -0700331uint32_t DisplayDevice::getPageFlipCount() const {
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700332 return mPageFlipCount;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800333}
334
Chia-I Wub02087d2017-11-09 10:19:54 -0800335void DisplayDevice::flip() const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800336{
Mathias Agopian875d8e12013-06-07 15:35:48 -0700337 mFlinger->getRenderEngine().checkErrors();
Mathias Agopian076b1cc2009-04-10 14:24:30 -0700338 mPageFlipCount++;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800339}
340
Dan Stoza71433162014-02-04 16:22:36 -0800341status_t DisplayDevice::beginFrame(bool mustRecompose) const {
342 return mDisplaySurface->beginFrame(mustRecompose);
Jesse Hall028dc8f2013-08-20 16:35:32 -0700343}
344
Dan Stoza9e56aa02015-11-02 13:00:03 -0800345status_t DisplayDevice::prepareFrame(HWComposer& hwc) {
346 status_t error = hwc.prepare(*this);
347 if (error != NO_ERROR) {
348 return error;
349 }
350
351 DisplaySurface::CompositionType compositionType;
352 bool hasClient = hwc.hasClientComposition(mHwcDisplayId);
353 bool hasDevice = hwc.hasDeviceComposition(mHwcDisplayId);
354 if (hasClient && hasDevice) {
355 compositionType = DisplaySurface::COMPOSITION_MIXED;
356 } else if (hasClient) {
357 compositionType = DisplaySurface::COMPOSITION_GLES;
358 } else if (hasDevice) {
359 compositionType = DisplaySurface::COMPOSITION_HWC;
360 } else {
361 // Nothing to do -- when turning the screen off we get a frame like
362 // this. Call it a HWC frame since we won't be doing any GLES work but
363 // will do a prepare/set cycle.
364 compositionType = DisplaySurface::COMPOSITION_HWC;
365 }
366 return mDisplaySurface->prepareFrame(compositionType);
367}
Jesse Hall38efe862013-04-06 23:12:29 -0700368
Mathias Agopianda27af92012-09-13 18:17:13 -0700369void DisplayDevice::swapBuffers(HWComposer& hwc) const {
Madhuri Athota88a905b2017-05-04 16:58:15 +0530370 if (hwc.hasClientComposition(mHwcDisplayId) || hwc.hasFlipClientTargetRequest(mHwcDisplayId)) {
Lloyd Pique144e1162017-12-20 16:44:52 -0800371 mSurface->swapBuffers();
Mathias Agopianda27af92012-09-13 18:17:13 -0700372 }
Mathias Agopian52e21482012-09-24 18:07:21 -0700373
Jesse Hall99c7dbb2013-03-14 14:29:29 -0700374 status_t result = mDisplaySurface->advanceFrame();
375 if (result != NO_ERROR) {
376 ALOGE("[%s] failed pushing new frame to HWC: %d",
377 mDisplayName.string(), result);
Mathias Agopian32341382012-09-25 19:16:28 -0700378 }
Mathias Agopianda27af92012-09-13 18:17:13 -0700379}
380
Dan Stoza9e56aa02015-11-02 13:00:03 -0800381void DisplayDevice::onSwapBuffersCompleted() const {
382 mDisplaySurface->onFrameCommitted();
383}
Mathias Agopianda27af92012-09-13 18:17:13 -0700384
Chia-I Wuf846a352017-11-10 09:22:52 -0800385bool DisplayDevice::makeCurrent() const {
Lloyd Pique144e1162017-12-20 16:44:52 -0800386 bool success = mFlinger->getRenderEngine().setCurrentSurface(*mSurface);
Mathias Agopian931bda12013-08-28 18:11:46 -0700387 setViewportAndProjection();
Chia-I Wuf846a352017-11-10 09:22:52 -0800388 return success;
Mathias Agopian52bbb1a2012-07-31 19:01:53 -0700389}
390
Mathias Agopian875d8e12013-06-07 15:35:48 -0700391void DisplayDevice::setViewportAndProjection() const {
392 size_t w = mDisplayWidth;
393 size_t h = mDisplayHeight;
Dan Stozac1879002014-05-22 15:59:05 -0700394 Rect sourceCrop(0, 0, w, h);
Riley Andrewsc3ebe662014-09-04 16:20:31 -0700395 mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, h,
396 false, Transform::ROT_0);
Mathias Agopianbae92d02012-09-28 01:00:47 -0700397}
398
Dan Stoza9e56aa02015-11-02 13:00:03 -0800399const sp<Fence>& DisplayDevice::getClientTargetAcquireFence() const {
400 return mDisplaySurface->getClientTargetAcquireFence();
401}
Dan Stoza9e56aa02015-11-02 13:00:03 -0800402
Mathias Agopian1b031492012-06-20 17:51:20 -0700403// ----------------------------------------------------------------------------
404
Mathias Agopian13127d82013-03-05 17:47:11 -0800405void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) {
Mathias Agopian3b1d2b62012-07-11 13:48:17 -0700406 mVisibleLayersSortedByZ = layers;
Mathias Agopian3b1d2b62012-07-11 13:48:17 -0700407}
408
Mathias Agopian13127d82013-03-05 17:47:11 -0800409const Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const {
Mathias Agopian3b1d2b62012-07-11 13:48:17 -0700410 return mVisibleLayersSortedByZ;
411}
412
Chia-I Wu83806892017-11-16 10:50:20 -0800413void DisplayDevice::setLayersNeedingFences(const Vector< sp<Layer> >& layers) {
414 mLayersNeedingFences = layers;
415}
416
417const Vector< sp<Layer> >& DisplayDevice::getLayersNeedingFences() const {
418 return mLayersNeedingFences;
419}
420
Mathias Agopiancd60f992012-08-16 16:28:27 -0700421Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
422 Region dirty;
Mathias Agopiancd60f992012-08-16 16:28:27 -0700423 if (repaintEverything) {
424 dirty.set(getBounds());
425 } else {
Mathias Agopianda8d0a52012-09-04 15:05:38 -0700426 const Transform& planeTransform(mGlobalTransform);
Mathias Agopiancd60f992012-08-16 16:28:27 -0700427 dirty = planeTransform.transform(this->dirtyRegion);
428 dirty.andSelf(getBounds());
429 }
430 return dirty;
431}
432
Mathias Agopian3b1d2b62012-07-11 13:48:17 -0700433// ----------------------------------------------------------------------------
Prashant Malani2c9b11f2014-05-25 01:36:31 -0700434void DisplayDevice::setPowerMode(int mode) {
435 mPowerMode = mode;
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700436}
437
Prashant Malani2c9b11f2014-05-25 01:36:31 -0700438int DisplayDevice::getPowerMode() const {
439 return mPowerMode;
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700440}
441
Prashant Malani2c9b11f2014-05-25 01:36:31 -0700442bool DisplayDevice::isDisplayOn() const {
443 return (mPowerMode != HWC_POWER_MODE_OFF);
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700444}
445
446// ----------------------------------------------------------------------------
Michael Lentine6c9e34a2014-07-14 13:48:55 -0700447void DisplayDevice::setActiveConfig(int mode) {
448 mActiveConfig = mode;
449}
450
451int DisplayDevice::getActiveConfig() const {
452 return mActiveConfig;
453}
454
455// ----------------------------------------------------------------------------
Peiyong Lina52f0292018-03-14 17:26:31 -0700456void DisplayDevice::setActiveColorMode(ColorMode mode) {
Michael Wright28f24d02016-07-12 13:30:53 -0700457 mActiveColorMode = mode;
458}
459
Peiyong Lina52f0292018-03-14 17:26:31 -0700460ColorMode DisplayDevice::getActiveColorMode() const {
Michael Wright28f24d02016-07-12 13:30:53 -0700461 return mActiveColorMode;
462}
Courtney Goeltzenleuchter79d27242017-07-13 17:54:01 -0600463
Peiyong Lindd9b2ae2018-03-01 16:22:45 -0800464RenderIntent DisplayDevice::getActiveRenderIntent() const {
465 return mActiveRenderIntent;
466}
467
468void DisplayDevice::setActiveRenderIntent(RenderIntent renderIntent) {
469 mActiveRenderIntent = renderIntent;
470}
471
Yiwei Zhang7c64f172018-03-07 14:52:28 -0800472void DisplayDevice::setColorTransform(const mat4& transform) {
473 const bool isIdentity = (transform == mat4());
474 mColorTransform =
475 isIdentity ? HAL_COLOR_TRANSFORM_IDENTITY : HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX;
476}
477
478android_color_transform_t DisplayDevice::getColorTransform() const {
479 return mColorTransform;
480}
481
Peiyong Lin34beb7a2018-03-28 11:57:12 -0700482void DisplayDevice::setCompositionDataSpace(ui::Dataspace dataspace) {
Peiyong Lindd9b2ae2018-03-01 16:22:45 -0800483 mCompositionDataSpace = dataspace;
Courtney Goeltzenleuchter79d27242017-07-13 17:54:01 -0600484 ANativeWindow* const window = mNativeWindow.get();
Peiyong Lin34beb7a2018-03-28 11:57:12 -0700485 native_window_set_buffers_data_space(window, static_cast<android_dataspace>(dataspace));
Courtney Goeltzenleuchter79d27242017-07-13 17:54:01 -0600486}
Michael Wright28f24d02016-07-12 13:30:53 -0700487
Peiyong Lindd9b2ae2018-03-01 16:22:45 -0800488ui::Dataspace DisplayDevice::getCompositionDataSpace() const {
489 return mCompositionDataSpace;
490}
491
Michael Wright28f24d02016-07-12 13:30:53 -0700492// ----------------------------------------------------------------------------
Mathias Agopiand3ee2312012-08-02 14:01:42 -0700493
Mathias Agopian28947d72012-08-08 18:51:15 -0700494void DisplayDevice::setLayerStack(uint32_t stack) {
495 mLayerStack = stack;
496 dirtyRegion.set(bounds());
497}
498
499// ----------------------------------------------------------------------------
500
Mathias Agopianc1c05de2013-09-17 23:45:22 -0700501uint32_t DisplayDevice::getOrientationTransform() const {
502 uint32_t transform = 0;
503 switch (mOrientation) {
504 case DisplayState::eOrientationDefault:
505 transform = Transform::ROT_0;
506 break;
507 case DisplayState::eOrientation90:
508 transform = Transform::ROT_90;
509 break;
510 case DisplayState::eOrientation180:
511 transform = Transform::ROT_180;
512 break;
513 case DisplayState::eOrientation270:
514 transform = Transform::ROT_270;
515 break;
516 }
517 return transform;
518}
519
Mathias Agopian0f2f5ff2012-07-31 23:09:07 -0700520status_t DisplayDevice::orientationToTransfrom(
Mathias Agopian1b031492012-06-20 17:51:20 -0700521 int orientation, int w, int h, Transform* tr)
522{
523 uint32_t flags = 0;
524 switch (orientation) {
Mathias Agopian3165cc22012-08-08 19:42:09 -0700525 case DisplayState::eOrientationDefault:
Mathias Agopian1b031492012-06-20 17:51:20 -0700526 flags = Transform::ROT_0;
527 break;
Mathias Agopian3165cc22012-08-08 19:42:09 -0700528 case DisplayState::eOrientation90:
Mathias Agopian1b031492012-06-20 17:51:20 -0700529 flags = Transform::ROT_90;
530 break;
Mathias Agopian3165cc22012-08-08 19:42:09 -0700531 case DisplayState::eOrientation180:
Mathias Agopian1b031492012-06-20 17:51:20 -0700532 flags = Transform::ROT_180;
533 break;
Mathias Agopian3165cc22012-08-08 19:42:09 -0700534 case DisplayState::eOrientation270:
Mathias Agopian1b031492012-06-20 17:51:20 -0700535 flags = Transform::ROT_270;
536 break;
537 default:
538 return BAD_VALUE;
539 }
540 tr->set(flags, w, h);
541 return NO_ERROR;
542}
543
Michael Lentine47e45402014-07-18 15:34:25 -0700544void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) {
545 dirtyRegion.set(getBounds());
546
Lloyd Pique144e1162017-12-20 16:44:52 -0800547 mSurface->setNativeWindow(nullptr);
Michael Lentinef2568de2014-08-20 10:51:23 -0700548
Michael Lentine47e45402014-07-18 15:34:25 -0700549 mDisplaySurface->resizeBuffers(newWidth, newHeight);
550
551 ANativeWindow* const window = mNativeWindow.get();
Lloyd Pique144e1162017-12-20 16:44:52 -0800552 mSurface->setNativeWindow(window);
553 mDisplayWidth = mSurface->queryWidth();
554 mDisplayHeight = mSurface->queryHeight();
Michael Lentine47e45402014-07-18 15:34:25 -0700555
556 LOG_FATAL_IF(mDisplayWidth != newWidth,
557 "Unable to set new width to %d", newWidth);
558 LOG_FATAL_IF(mDisplayHeight != newHeight,
559 "Unable to set new height to %d", newHeight);
560}
561
Mathias Agopian00e8c7a2012-09-04 19:30:46 -0700562void DisplayDevice::setProjection(int orientation,
Mathias Agopianf5f714a2013-02-26 16:54:05 -0800563 const Rect& newViewport, const Rect& newFrame) {
564 Rect viewport(newViewport);
565 Rect frame(newFrame);
566
567 const int w = mDisplayWidth;
568 const int h = mDisplayHeight;
569
570 Transform R;
571 DisplayDevice::orientationToTransfrom(orientation, w, h, &R);
572
573 if (!frame.isValid()) {
574 // the destination frame can be invalid if it has never been set,
575 // in that case we assume the whole display frame.
576 frame = Rect(w, h);
577 }
578
579 if (viewport.isEmpty()) {
580 // viewport can be invalid if it has never been set, in that case
581 // we assume the whole display size.
582 // it's also invalid to have an empty viewport, so we handle that
583 // case in the same way.
584 viewport = Rect(w, h);
585 if (R.getOrientation() & Transform::ROT_90) {
586 // viewport is always specified in the logical orientation
587 // of the display (ie: post-rotation).
588 swap(viewport.right, viewport.bottom);
589 }
590 }
591
592 dirtyRegion.set(getBounds());
593
594 Transform TL, TP, S;
595 float src_width = viewport.width();
596 float src_height = viewport.height();
597 float dst_width = frame.width();
598 float dst_height = frame.height();
599 if (src_width != dst_width || src_height != dst_height) {
600 float sx = dst_width / src_width;
601 float sy = dst_height / src_height;
602 S.set(sx, 0, 0, sy);
603 }
604
605 float src_x = viewport.left;
606 float src_y = viewport.top;
607 float dst_x = frame.left;
608 float dst_y = frame.top;
609 TL.set(-src_x, -src_y);
610 TP.set(dst_x, dst_y);
611
Iris Chang7501ed62018-04-30 14:45:42 +0800612 // need to take care of primary display rotation for mGlobalTransform
613 // for case if the panel is not installed aligned with device orientation
614 if (mType == DisplayType::DISPLAY_PRIMARY) {
Iris Chang7501ed62018-04-30 14:45:42 +0800615 DisplayDevice::orientationToTransfrom(
Chia-I Wu690a76f2018-08-27 14:38:23 -0700616 (orientation + mDisplayInstallOrientation) % (DisplayState::eOrientation270 + 1),
Iris Chang7501ed62018-04-30 14:45:42 +0800617 w, h, &R);
618 }
619
Mathias Agopianf5f714a2013-02-26 16:54:05 -0800620 // The viewport and frame are both in the logical orientation.
621 // Apply the logical translation, scale to physical size, apply the
622 // physical translation and finally rotate to the physical orientation.
623 mGlobalTransform = R * TP * S * TL;
624
625 const uint8_t type = mGlobalTransform.getType();
626 mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
627 (type >= Transform::SCALE));
628
629 mScissor = mGlobalTransform.transform(viewport);
630 if (mScissor.isEmpty()) {
Mathias Agopian6c7f25a2013-05-09 20:37:10 -0700631 mScissor = getBounds();
Mathias Agopianf5f714a2013-02-26 16:54:05 -0800632 }
633
Mathias Agopianda8d0a52012-09-04 15:05:38 -0700634 mOrientation = orientation;
Pablo Ceballos021623b2016-04-15 17:31:51 -0700635 if (mType == DisplayType::DISPLAY_PRIMARY) {
636 uint32_t transform = 0;
637 switch (mOrientation) {
638 case DisplayState::eOrientationDefault:
639 transform = Transform::ROT_0;
640 break;
641 case DisplayState::eOrientation90:
642 transform = Transform::ROT_90;
643 break;
644 case DisplayState::eOrientation180:
645 transform = Transform::ROT_180;
646 break;
647 case DisplayState::eOrientation270:
648 transform = Transform::ROT_270;
649 break;
650 }
651 sPrimaryDisplayOrientation = transform;
652 }
Mathias Agopian00e8c7a2012-09-04 19:30:46 -0700653 mViewport = viewport;
654 mFrame = frame;
Mathias Agopian1b031492012-06-20 17:51:20 -0700655}
Mathias Agopian1d12d8a2012-09-18 01:38:00 -0700656
Pablo Ceballos021623b2016-04-15 17:31:51 -0700657uint32_t DisplayDevice::getPrimaryDisplayOrientationTransform() {
658 return sPrimaryDisplayOrientation;
659}
660
Mathias Agopian74d211a2013-04-22 16:55:35 +0200661void DisplayDevice::dump(String8& result) const {
Mathias Agopian1d12d8a2012-09-18 01:38:00 -0700662 const Transform& tr(mGlobalTransform);
Courtney Goeltzenleuchter152279d2017-08-14 18:18:30 -0600663 ANativeWindow* const window = mNativeWindow.get();
Courtney Goeltzenleuchter0ebaac32017-04-13 12:17:03 -0600664 result.appendFormat("+ DisplayDevice: %s\n", mDisplayName.string());
665 result.appendFormat(" type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p "
666 "(%d:%d:%d:%d), orient=%2d (type=%08x), "
667 "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n",
Courtney Goeltzenleuchter152279d2017-08-14 18:18:30 -0600668 mType, mHwcDisplayId, mLayerStack, mDisplayWidth, mDisplayHeight, window,
Lloyd Pique144e1162017-12-20 16:44:52 -0800669 mSurface->queryRedSize(), mSurface->queryGreenSize(),
670 mSurface->queryBlueSize(), mSurface->queryAlphaSize(), mOrientation,
671 tr.getType(), getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
Courtney Goeltzenleuchter0ebaac32017-04-13 12:17:03 -0600672 mVisibleLayersSortedByZ.size());
673 result.appendFormat(" v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
674 "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
675 mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
676 mFrame.left, mFrame.top, mFrame.right, mFrame.bottom, mScissor.left,
677 mScissor.top, mScissor.right, mScissor.bottom, tr[0][0], tr[1][0], tr[2][0],
678 tr[0][1], tr[1][1], tr[2][1], tr[0][2], tr[1][2], tr[2][2]);
Courtney Goeltzenleuchter152279d2017-08-14 18:18:30 -0600679 auto const surface = static_cast<Surface*>(window);
Peiyong Lin34beb7a2018-03-28 11:57:12 -0700680 ui::Dataspace dataspace = surface->getBuffersDataSpace();
Peiyong Lindd9b2ae2018-03-01 16:22:45 -0800681 result.appendFormat(" wideColorGamut=%d, hdr10=%d, colorMode=%s, dataspace: %s (%d)\n",
682 mHasWideColorGamut, mHasHdr10,
Chia-I Wu1e043612018-03-01 09:45:09 -0800683 decodeColorMode(mActiveColorMode).c_str(),
Peiyong Lin34beb7a2018-03-28 11:57:12 -0700684 dataspaceDetails(static_cast<android_dataspace>(dataspace)).c_str(), dataspace);
Mathias Agopian1d12d8a2012-09-18 01:38:00 -0700685
Jesse Hall99c7dbb2013-03-14 14:29:29 -0700686 String8 surfaceDump;
Dan Stozaf10c46e2014-11-11 10:32:31 -0800687 mDisplaySurface->dumpAsString(surfaceDump);
Jesse Hall99c7dbb2013-03-14 14:29:29 -0700688 result.append(surfaceDump);
Mathias Agopian1d12d8a2012-09-18 01:38:00 -0700689}
Irvelffc9efc2016-07-27 15:16:37 -0700690
Chia-I Wu0607fbe2018-05-18 10:59:36 -0700691// Map dataspace/intent to the best matched dataspace/colorMode/renderIntent
692// supported by HWC.
693void DisplayDevice::addColorMode(
694 const std::unordered_map<ColorMode, std::vector<RenderIntent>>& hwcColorModes,
695 const ColorMode mode, const RenderIntent intent) {
696 // find the best color mode
697 const ColorMode hwcColorMode = getHwcColorMode(hwcColorModes, mode);
698
699 // find the best render intent
700 auto iter = hwcColorModes.find(hwcColorMode);
701 const auto& hwcIntents =
702 iter != hwcColorModes.end() ? iter->second : std::vector<RenderIntent>();
703 const RenderIntent hwcIntent = getHwcRenderIntent(hwcIntents, intent);
704
705 const Dataspace dataspace = colorModeToDataspace(mode);
706 const Dataspace hwcDataspace = colorModeToDataspace(hwcColorMode);
707
708 ALOGV("DisplayDevice %d/%d: map (%s, %s) to (%s, %s, %s)", mType, mHwcDisplayId,
709 dataspaceDetails(static_cast<android_dataspace_t>(dataspace)).c_str(),
710 decodeRenderIntent(intent).c_str(),
711 dataspaceDetails(static_cast<android_dataspace_t>(hwcDataspace)).c_str(),
712 decodeColorMode(hwcColorMode).c_str(), decodeRenderIntent(hwcIntent).c_str());
713
714 mColorModes[getColorModeKey(dataspace, intent)] = {hwcDataspace, hwcColorMode, hwcIntent};
715}
716
717void DisplayDevice::populateColorModes(
718 const std::unordered_map<ColorMode, std::vector<RenderIntent>>& hwcColorModes) {
719 if (!hasWideColorGamut()) {
720 return;
721 }
722
Chia-I Wu0d711262018-05-21 15:19:35 -0700723 // collect all known SDR render intents
724 std::unordered_set<RenderIntent> sdrRenderIntents(sSdrRenderIntents.begin(),
725 sSdrRenderIntents.end());
726 auto iter = hwcColorModes.find(ColorMode::SRGB);
727 if (iter != hwcColorModes.end()) {
728 for (auto intent : iter->second) {
729 sdrRenderIntents.insert(intent);
730 }
731 }
732
Chia-I Wuc4b08bd2018-05-29 12:57:23 -0700733 // add all known SDR combinations
Chia-I Wu0d711262018-05-21 15:19:35 -0700734 for (auto intent : sdrRenderIntents) {
Chia-I Wu0607fbe2018-05-18 10:59:36 -0700735 for (auto mode : sSdrColorModes) {
736 addColorMode(hwcColorModes, mode, intent);
Peiyong Lind6fa4a72018-04-17 15:09:44 -0700737 }
738 }
Chia-I Wu0607fbe2018-05-18 10:59:36 -0700739
Chia-I Wuc4b08bd2018-05-29 12:57:23 -0700740 // collect all known HDR render intents
741 std::unordered_set<RenderIntent> hdrRenderIntents(sHdrRenderIntents.begin(),
742 sHdrRenderIntents.end());
743 iter = hwcColorModes.find(ColorMode::BT2100_PQ);
744 if (iter != hwcColorModes.end()) {
745 for (auto intent : iter->second) {
746 hdrRenderIntents.insert(intent);
747 }
748 }
749
750 // add all known HDR combinations
Chia-I Wu0607fbe2018-05-18 10:59:36 -0700751 for (auto intent : sHdrRenderIntents) {
752 for (auto mode : sHdrColorModes) {
753 addColorMode(hwcColorModes, mode, intent);
754 }
755 }
756}
757
758bool DisplayDevice::hasRenderIntent(RenderIntent intent) const {
759 // assume a render intent is supported when SRGB supports it; we should
760 // get rid of that assumption.
761 auto iter = mColorModes.find(getColorModeKey(Dataspace::SRGB, intent));
762 return iter != mColorModes.end() && iter->second.renderIntent == intent;
763}
764
Peiyong Lin3c6b7ef2018-06-05 10:58:41 -0700765bool DisplayDevice::hasLegacyHdrSupport(Dataspace dataspace) const {
Chia-I Wu0607fbe2018-05-18 10:59:36 -0700766 if ((dataspace == Dataspace::BT2020_PQ && hasHDR10Support()) ||
767 (dataspace == Dataspace::BT2020_HLG && hasHLGSupport())) {
768 auto iter =
769 mColorModes.find(getColorModeKey(dataspace, RenderIntent::TONE_MAP_COLORIMETRIC));
Peiyong Lin3c6b7ef2018-06-05 10:58:41 -0700770 return iter == mColorModes.end() || iter->second.dataspace != dataspace;
Chia-I Wu0607fbe2018-05-18 10:59:36 -0700771 }
772
773 return false;
774}
775
776void DisplayDevice::getBestColorMode(Dataspace dataspace, RenderIntent intent,
777 Dataspace* outDataspace, ColorMode* outMode,
778 RenderIntent* outIntent) const {
779 auto iter = mColorModes.find(getColorModeKey(dataspace, intent));
780 if (iter != mColorModes.end()) {
781 *outDataspace = iter->second.dataspace;
782 *outMode = iter->second.colorMode;
783 *outIntent = iter->second.renderIntent;
784 } else {
Chia-I Wu6333af52018-10-16 13:46:36 -0700785 // this is unexpected on a WCG display
786 if (hasWideColorGamut()) {
787 ALOGE("map unknown (%s)/(%s) to default color mode",
788 dataspaceDetails(static_cast<android_dataspace_t>(dataspace)).c_str(),
789 decodeRenderIntent(intent).c_str());
790 }
Chia-I Wu0607fbe2018-05-18 10:59:36 -0700791
792 *outDataspace = Dataspace::UNKNOWN;
793 *outMode = ColorMode::NATIVE;
794 *outIntent = RenderIntent::COLORIMETRIC;
795 }
Peiyong Lind6fa4a72018-04-17 15:09:44 -0700796}
797
Irvelffc9efc2016-07-27 15:16:37 -0700798std::atomic<int32_t> DisplayDeviceState::nextDisplayId(1);
799
800DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type, bool isSecure)
801 : type(type),
802 layerStack(DisplayDevice::NO_LAYER_STACK),
803 orientation(0),
804 width(0),
805 height(0),
806 isSecure(isSecure)
807{
808 viewport.makeInvalid();
809 frame.makeInvalid();
810}
Peiyong Linfd997e02018-03-28 15:29:00 -0700811
812} // namespace android