blob: 7cd283d3bb1cf9fdbab9350a364b7a3df79ae731 [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(),
88 applyDeviceOrientation(rotation, *display)),
89 mDisplay(std::move(display)),
90 mSourceCrop(sourceCrop),
91 mAllowSecureLayers(allowSecureLayers) {}
92
93const ui::Transform& DisplayRenderArea::getTransform() const {
94 return mTransform;
95}
96
97Rect DisplayRenderArea::getBounds() const {
98 return mDisplay->getBounds();
99}
100
101int DisplayRenderArea::getHeight() const {
102 return mDisplay->getHeight();
103}
104
105int DisplayRenderArea::getWidth() const {
106 return mDisplay->getWidth();
107}
108
109bool DisplayRenderArea::isSecure() const {
110 return mAllowSecureLayers && mDisplay->isSecure();
111}
112
113sp<const DisplayDevice> DisplayRenderArea::getDisplayDevice() const {
114 return mDisplay;
115}
116
117bool DisplayRenderArea::needsFiltering() const {
118 // check if the projection from the logical render area
119 // to the physical render area requires filtering
120 const Rect& sourceCrop = getSourceCrop();
121 int width = sourceCrop.width();
122 int height = sourceCrop.height();
123 if (getRotationFlags() & ui::Transform::ROT_90) {
124 std::swap(width, height);
125 }
126 return width != getReqWidth() || height != getReqHeight();
127}
128
129Rect DisplayRenderArea::getSourceCrop() const {
130 // use the projected display viewport by default.
131 if (mSourceCrop.isEmpty()) {
132 return mDisplay->getSourceClip();
133 }
134
135 // If there is a source crop provided then it is assumed that the device
136 // was in portrait orientation. This may not logically be true, so
137 // correct for the orientation error by undoing the rotation
138
139 ui::Rotation logicalOrientation = mDisplay->getOrientation();
140 if (logicalOrientation == ui::Rotation::Rotation90) {
141 logicalOrientation = ui::Rotation::Rotation270;
142 } else if (logicalOrientation == ui::Rotation::Rotation270) {
143 logicalOrientation = ui::Rotation::Rotation90;
144 }
145
146 const auto flags = ui::Transform::toRotationFlags(logicalOrientation);
147 int width = mDisplay->getSourceClip().getWidth();
148 int height = mDisplay->getSourceClip().getHeight();
149 ui::Transform rotation;
150 rotation.set(flags, width, height);
151 return rotation.transform(mSourceCrop);
152}
153
154} // namespace android