blob: 4bae669d7c4ed95b8e1ace5d0d3f7ba2de597f1e [file] [log] [blame]
Marin Shalamanovf6b5d182020-06-12 02:08:51 +02001/*
2 * Copyright 2020 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#include "DisplayRenderArea.h"
18#include "DisplayDevice.h"
19
20namespace android {
21namespace {
22
23RenderArea::RotationFlags applyDeviceOrientation(RenderArea::RotationFlags rotation,
24 const DisplayDevice& display) {
25 uint32_t inverseRotate90 = 0;
26 uint32_t inverseReflect = 0;
27
28 // Reverse the logical orientation.
29 ui::Rotation logicalOrientation = display.getOrientation();
30 if (logicalOrientation == ui::Rotation::Rotation90) {
31 logicalOrientation = ui::Rotation::Rotation270;
32 } else if (logicalOrientation == ui::Rotation::Rotation270) {
33 logicalOrientation = ui::Rotation::Rotation90;
34 }
35
36 const ui::Rotation orientation = display.getPhysicalOrientation() + logicalOrientation;
37
38 switch (orientation) {
39 case ui::ROTATION_0:
40 return rotation;
41
42 case ui::ROTATION_90:
43 inverseRotate90 = ui::Transform::ROT_90;
44 inverseReflect = ui::Transform::ROT_180;
45 break;
46
47 case ui::ROTATION_180:
48 inverseReflect = ui::Transform::ROT_180;
49 break;
50
51 case ui::ROTATION_270:
52 inverseRotate90 = ui::Transform::ROT_90;
53 break;
54 }
55
56 const uint32_t rotate90 = rotation & ui::Transform::ROT_90;
57 uint32_t reflect = rotation & ui::Transform::ROT_180;
58
59 // Apply reflection for double rotation.
60 if (rotate90 & inverseRotate90) {
61 reflect = ~reflect & ui::Transform::ROT_180;
62 }
63
64 return static_cast<RenderArea::RotationFlags>((rotate90 ^ inverseRotate90) |
65 (reflect ^ inverseReflect));
66}
67
68} // namespace
69
70std::unique_ptr<RenderArea> DisplayRenderArea::create(wp<const DisplayDevice> displayWeak,
71 const Rect& sourceCrop, ui::Size reqSize,
72 ui::Dataspace reqDataSpace,
73 RotationFlags rotation,
74 bool allowSecureLayers) {
75 if (auto display = displayWeak.promote()) {
76 // Using new to access a private constructor.
77 return std::unique_ptr<DisplayRenderArea>(
78 new DisplayRenderArea(std::move(display), sourceCrop, reqSize, reqDataSpace,
79 rotation, allowSecureLayers));
80 }
81 return nullptr;
82}
83
84DisplayRenderArea::DisplayRenderArea(sp<const DisplayDevice> display, const Rect& sourceCrop,
85 ui::Size reqSize, ui::Dataspace reqDataSpace,
86 RotationFlags rotation, bool allowSecureLayers)
87 : RenderArea(reqSize, CaptureFill::OPAQUE, reqDataSpace, display->getViewport(),
chaviw70cb6a42020-07-30 13:57:36 -070088 allowSecureLayers, applyDeviceOrientation(rotation, *display)),
Marin Shalamanovf6b5d182020-06-12 02:08:51 +020089 mDisplay(std::move(display)),
chaviw70cb6a42020-07-30 13:57:36 -070090 mSourceCrop(sourceCrop) {}
Marin Shalamanovf6b5d182020-06-12 02:08:51 +020091
92const ui::Transform& DisplayRenderArea::getTransform() const {
93 return mTransform;
94}
95
96Rect DisplayRenderArea::getBounds() const {
97 return mDisplay->getBounds();
98}
99
100int DisplayRenderArea::getHeight() const {
101 return mDisplay->getHeight();
102}
103
104int DisplayRenderArea::getWidth() const {
105 return mDisplay->getWidth();
106}
107
108bool DisplayRenderArea::isSecure() const {
109 return mAllowSecureLayers && mDisplay->isSecure();
110}
111
112sp<const DisplayDevice> DisplayRenderArea::getDisplayDevice() const {
113 return mDisplay;
114}
115
116bool DisplayRenderArea::needsFiltering() const {
117 // check if the projection from the logical render area
118 // to the physical render area requires filtering
119 const Rect& sourceCrop = getSourceCrop();
120 int width = sourceCrop.width();
121 int height = sourceCrop.height();
122 if (getRotationFlags() & ui::Transform::ROT_90) {
123 std::swap(width, height);
124 }
125 return width != getReqWidth() || height != getReqHeight();
126}
127
128Rect DisplayRenderArea::getSourceCrop() const {
129 // use the projected display viewport by default.
130 if (mSourceCrop.isEmpty()) {
Marin Shalamanov06ca1632020-07-28 12:32:01 +0200131 return mDisplay->getViewport();
Marin Shalamanovf6b5d182020-06-12 02:08:51 +0200132 }
133
134 // If there is a source crop provided then it is assumed that the device
135 // was in portrait orientation. This may not logically be true, so
136 // correct for the orientation error by undoing the rotation
137
138 ui::Rotation logicalOrientation = mDisplay->getOrientation();
139 if (logicalOrientation == ui::Rotation::Rotation90) {
140 logicalOrientation = ui::Rotation::Rotation270;
141 } else if (logicalOrientation == ui::Rotation::Rotation270) {
142 logicalOrientation = ui::Rotation::Rotation90;
143 }
144
145 const auto flags = ui::Transform::toRotationFlags(logicalOrientation);
Marin Shalamanov06ca1632020-07-28 12:32:01 +0200146 int width = mDisplay->getViewport().getWidth();
147 int height = mDisplay->getViewport().getHeight();
Marin Shalamanovf6b5d182020-06-12 02:08:51 +0200148 ui::Transform rotation;
149 rotation.set(flags, width, height);
150 return rotation.transform(mSourceCrop);
151}
152
153} // namespace android