1 /*
2 * Copyright (C) 2011 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 // TODO(b/129481165): remove the #pragma below and fix conversion issues
18 #pragma clang diagnostic push
19 #pragma clang diagnostic ignored "-Wconversion"
20
21 #include "LayerRejecter.h"
22
23 #include <gui/BufferItem.h>
24 #include <system/window.h>
25
26 #define DEBUG_RESIZE 0
27
28 namespace android {
29
LayerRejecter(Layer::State & front,Layer::State & current,bool & recomputeVisibleRegions,bool stickySet,const std::string & name,bool transformToDisplayInverse)30 LayerRejecter::LayerRejecter(Layer::State& front, Layer::State& current,
31 bool& recomputeVisibleRegions, bool stickySet, const std::string& name,
32 bool transformToDisplayInverse)
33 : mFront(front),
34 mCurrent(current),
35 mRecomputeVisibleRegions(recomputeVisibleRegions),
36 mStickyTransformSet(stickySet),
37 mName(name),
38 mTransformToDisplayInverse(transformToDisplayInverse) {}
39
reject(const sp<GraphicBuffer> & buf,const BufferItem & item)40 bool LayerRejecter::reject(const sp<GraphicBuffer>& buf, const BufferItem& item) {
41 if (buf == nullptr) {
42 return false;
43 }
44
45 uint32_t bufWidth = buf->getWidth();
46 uint32_t bufHeight = buf->getHeight();
47
48 // check that we received a buffer of the right size
49 // (Take the buffer's orientation into account)
50 if (item.mTransform & ui::Transform::ROT_90) {
51 std::swap(bufWidth, bufHeight);
52 }
53
54 if (mTransformToDisplayInverse) {
55 uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
56 if (invTransform & ui::Transform::ROT_90) {
57 std::swap(bufWidth, bufHeight);
58 }
59 }
60
61 int actualScalingMode = item.mScalingMode;
62 bool isFixedSize = actualScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
63 if (mFront.active_legacy != mFront.requested_legacy) {
64 if (isFixedSize ||
65 (bufWidth == mFront.requested_legacy.w && bufHeight == mFront.requested_legacy.h)) {
66 // Here we pretend the transaction happened by updating the
67 // current and drawing states. Drawing state is only accessed
68 // in this thread, no need to have it locked
69 mFront.active_legacy = mFront.requested_legacy;
70
71 // We also need to update the current state so that
72 // we don't end-up overwriting the drawing state with
73 // this stale current state during the next transaction
74 //
75 // NOTE: We don't need to hold the transaction lock here
76 // because State::active_legacy is only accessed from this thread.
77 mCurrent.active_legacy = mFront.active_legacy;
78 mCurrent.modified = true;
79
80 // recompute visible region
81 mRecomputeVisibleRegions = true;
82
83 if (mFront.crop != mFront.requestedCrop) {
84 mFront.crop = mFront.requestedCrop;
85 mCurrent.crop = mFront.requestedCrop;
86 mRecomputeVisibleRegions = true;
87 }
88 }
89
90 ALOGD_IF(DEBUG_RESIZE,
91 "[%s] latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
92 " drawing={ active_legacy ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} "
93 "(%4d,%4d) "
94 "}\n"
95 " requested_legacy={ wh={%4u,%4u} }}\n",
96 mName.c_str(), bufWidth, bufHeight, item.mTransform, item.mScalingMode,
97 mFront.active_legacy.w, mFront.active_legacy.h, mFront.crop.left, mFront.crop.top,
98 mFront.crop.right, mFront.crop.bottom, mFront.crop.getWidth(),
99 mFront.crop.getHeight(), mFront.requested_legacy.w, mFront.requested_legacy.h);
100 }
101
102 if (!isFixedSize && !mStickyTransformSet) {
103 if (mFront.active_legacy.w != bufWidth || mFront.active_legacy.h != bufHeight) {
104 // reject this buffer
105 ALOGE("[%s] rejecting buffer: "
106 "bufWidth=%d, bufHeight=%d, front.active_legacy.{w=%d, h=%d}",
107 mName.c_str(), bufWidth, bufHeight, mFront.active_legacy.w,
108 mFront.active_legacy.h);
109 return true;
110 }
111 }
112
113 // if the transparent region has changed (this test is
114 // conservative, but that's fine, worst case we're doing
115 // a bit of extra work), we latch the new one and we
116 // trigger a visible-region recompute.
117 //
118 // We latch the transparent region here, instead of above where we latch
119 // the rest of the geometry because it is only content but not necessarily
120 // resize dependent.
121 if (!mFront.activeTransparentRegion_legacy.hasSameRects(
122 mFront.requestedTransparentRegion_legacy)) {
123 mFront.activeTransparentRegion_legacy = mFront.requestedTransparentRegion_legacy;
124
125 // We also need to update the current state so that
126 // we don't end-up overwriting the drawing state with
127 // this stale current state during the next transaction
128 //
129 // NOTE: We don't need to hold the transaction lock here
130 // because State::active_legacy is only accessed from this thread.
131 mCurrent.activeTransparentRegion_legacy = mFront.activeTransparentRegion_legacy;
132
133 // recompute visible region
134 mRecomputeVisibleRegions = true;
135 }
136
137 return false;
138 }
139
140 } // namespace android
141
142 // TODO(b/129481165): remove the #pragma below and fix conversion issues
143 #pragma clang diagnostic pop // ignored "-Wconversion"
144