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