blob: a6536f5d83b7bb5eda0d2b3a2ce3155068e59000 [file] [log] [blame]
Jorim Jaggi64be98d2018-04-26 23:23:29 +02001/*
2 * Copyright (C) 2018 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
Jorim Jaggi5bb571d2018-11-06 14:42:04 +010014 * limitations under the License.
Jorim Jaggi64be98d2018-04-26 23:23:29 +020015 */
16
Jorim Jaggi5bb571d2018-11-06 14:42:04 +010017package android.view;
Jorim Jaggi64be98d2018-04-26 23:23:29 +020018
19import android.graphics.Matrix;
20import android.graphics.Rect;
Jorim Jaggicd560732018-05-29 16:29:24 +020021import android.view.SurfaceControl.Transaction;
Jorim Jaggi5bb571d2018-11-06 14:42:04 +010022
23import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggi64be98d2018-04-26 23:23:29 +020024
Winson Chung71eda582018-12-11 12:54:36 -080025import java.util.function.Consumer;
26
Jorim Jaggi64be98d2018-04-26 23:23:29 +020027/**
28 * Helper class to apply surface transactions in sync with RenderThread.
Jorim Jaggi5bb571d2018-11-06 14:42:04 +010029 * @hide
Jorim Jaggi64be98d2018-04-26 23:23:29 +020030 */
31public class SyncRtSurfaceTransactionApplier {
32
Mark Renoufdf0f3bc2019-09-16 14:04:38 -040033 public static final int FLAG_ALL = 0xffffffff;
34 public static final int FLAG_ALPHA = 1;
35 public static final int FLAG_MATRIX = 1 << 1;
36 public static final int FLAG_WINDOW_CROP = 1 << 2;
37 public static final int FLAG_LAYER = 1 << 3;
38 public static final int FLAG_CORNER_RADIUS = 1 << 4;
39 public static final int FLAG_VISIBILITY = 1 << 5;
40
Jorim Jaggi64be98d2018-04-26 23:23:29 +020041 private final Surface mTargetSurface;
42 private final ViewRootImpl mTargetViewRootImpl;
43 private final float[] mTmpFloat9 = new float[9];
44
45 /**
46 * @param targetView The view in the surface that acts as synchronization anchor.
47 */
48 public SyncRtSurfaceTransactionApplier(View targetView) {
49 mTargetViewRootImpl = targetView != null ? targetView.getViewRootImpl() : null;
50 mTargetSurface = mTargetViewRootImpl != null ? mTargetViewRootImpl.mSurface : null;
51 }
52
53 /**
54 * Schedules applying surface parameters on the next frame.
55 *
Jorim Jaggi64be98d2018-04-26 23:23:29 +020056 * @param params The surface parameters to apply. DO NOT MODIFY the list after passing into
57 * this method to avoid synchronization issues.
58 */
Sunny Goyalbba378e2018-08-22 12:50:26 -070059 public void scheduleApply(final SurfaceParams... params) {
Jorim Jaggi2d39fb92018-05-16 14:37:02 -070060 if (mTargetViewRootImpl == null) {
61 return;
Jorim Jaggi64be98d2018-04-26 23:23:29 +020062 }
Jorim Jaggi5bb571d2018-11-06 14:42:04 +010063 mTargetViewRootImpl.registerRtFrameCallback(frame -> {
64 if (mTargetSurface == null || !mTargetSurface.isValid()) {
65 return;
Sunny Goyalbba378e2018-08-22 12:50:26 -070066 }
Jorim Jaggi5bb571d2018-11-06 14:42:04 +010067 Transaction t = new Transaction();
68 for (int i = params.length - 1; i >= 0; i--) {
69 SurfaceParams surfaceParams = params[i];
70 SurfaceControl surface = surfaceParams.surface;
71 t.deferTransactionUntilSurface(surface, mTargetSurface, frame);
72 applyParams(t, surfaceParams, mTmpFloat9);
73 }
74 t.setEarlyWakeup();
75 t.apply();
Jorim Jaggi2d39fb92018-05-16 14:37:02 -070076 });
Jorim Jaggi42b04752018-05-18 18:23:08 +020077
78 // Make sure a frame gets scheduled.
79 mTargetViewRootImpl.getView().invalidate();
Jorim Jaggi64be98d2018-04-26 23:23:29 +020080 }
81
Jorim Jaggi5bb571d2018-11-06 14:42:04 +010082 public static void applyParams(Transaction t, SurfaceParams params, float[] tmpFloat9) {
Mark Renoufdf0f3bc2019-09-16 14:04:38 -040083 if ((params.flags & FLAG_MATRIX) != 0) {
84 t.setMatrix(params.surface, params.matrix, tmpFloat9);
85 }
86 if ((params.flags & FLAG_WINDOW_CROP) != 0) {
87 t.setWindowCrop(params.surface, params.windowCrop);
88 }
89 if ((params.flags & FLAG_ALPHA) != 0) {
90 t.setAlpha(params.surface, params.alpha);
91 }
92 if ((params.flags & FLAG_LAYER) != 0) {
93 t.setLayer(params.surface, params.layer);
94 }
95 if ((params.flags & FLAG_CORNER_RADIUS) != 0) {
96 t.setCornerRadius(params.surface, params.cornerRadius);
97 }
98 if ((params.flags & FLAG_VISIBILITY) != 0) {
99 if (params.visible) {
100 t.show(params.surface);
101 } else {
102 t.hide(params.surface);
103 }
Jorim Jaggi67684882019-01-22 17:36:34 +0100104 }
Jorim Jaggicd560732018-05-29 16:29:24 +0200105 }
106
Winson Chung71eda582018-12-11 12:54:36 -0800107 /**
108 * Creates an instance of SyncRtSurfaceTransactionApplier, deferring until the target view is
109 * attached if necessary.
110 */
111 public static void create(final View targetView,
112 final Consumer<SyncRtSurfaceTransactionApplier> callback) {
113 if (targetView == null) {
114 // No target view, no applier
115 callback.accept(null);
116 } else if (targetView.getViewRootImpl() != null) {
117 // Already attached, we're good to go
118 callback.accept(new SyncRtSurfaceTransactionApplier(targetView));
119 } else {
120 // Haven't been attached before we can get the view root
121 targetView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
122 @Override
123 public void onViewAttachedToWindow(View v) {
124 targetView.removeOnAttachStateChangeListener(this);
125 callback.accept(new SyncRtSurfaceTransactionApplier(targetView));
126 }
127
128 @Override
129 public void onViewDetachedFromWindow(View v) {
130 // Do nothing
131 }
132 });
133 }
134 }
135
Jorim Jaggi64be98d2018-04-26 23:23:29 +0200136 public static class SurfaceParams {
137
Mark Renoufdf0f3bc2019-09-16 14:04:38 -0400138 public static class Builder {
139 final SurfaceControl surface;
140 int flags;
141 float alpha;
142 float cornerRadius;
143 Matrix matrix;
144 Rect windowCrop;
145 int layer;
146 boolean visible;
147
148 /**
149 * @param surface The surface to modify.
150 */
151 public Builder(SurfaceControl surface) {
152 this.surface = surface;
153 }
154
155 /**
156 * @param alpha The alpha value to apply to the surface.
157 * @return this Builder
158 */
159 public Builder withAlpha(float alpha) {
160 this.alpha = alpha;
161 flags |= FLAG_ALPHA;
162 return this;
163 }
164
165 /**
166 * @param matrix The matrix to apply to the surface.
167 * @return this Builder
168 */
169 public Builder withMatrix(Matrix matrix) {
170 this.matrix = matrix;
171 flags |= FLAG_MATRIX;
172 return this;
173 }
174
175 /**
176 * @param windowCrop The window crop to apply to the surface.
177 * @return this Builder
178 */
179 public Builder withWindowCrop(Rect windowCrop) {
180 this.windowCrop = windowCrop;
181 flags |= FLAG_WINDOW_CROP;
182 return this;
183 }
184
185 /**
186 * @param layer The layer to assign the surface.
187 * @return this Builder
188 */
189 public Builder withLayer(int layer) {
190 this.layer = layer;
191 flags |= FLAG_LAYER;
192 return this;
193 }
194
195 /**
196 * @param radius the Radius for rounded corners to apply to the surface.
197 * @return this Builder
198 */
199 public Builder withCornerRadius(float radius) {
200 this.cornerRadius = radius;
201 flags |= FLAG_CORNER_RADIUS;
202 return this;
203 }
204
205 /**
206 * @param visible The visibility to apply to the surface.
207 * @return this Builder
208 */
209 public Builder withVisibility(boolean visible) {
210 this.visible = visible;
211 flags |= FLAG_VISIBILITY;
212 return this;
213 }
214
215 /**
216 * @return a new SurfaceParams instance
217 */
218 public SurfaceParams build() {
219 return new SurfaceParams(surface, flags, alpha, matrix, windowCrop, layer,
220 cornerRadius, visible);
221 }
222 }
223
224 private SurfaceParams(SurfaceControl surface, int params, float alpha, Matrix matrix,
Jorim Jaggi67684882019-01-22 17:36:34 +0100225 Rect windowCrop, int layer, float cornerRadius, boolean visible) {
Mark Renoufdf0f3bc2019-09-16 14:04:38 -0400226 this.flags = params;
Jorim Jaggi5bb571d2018-11-06 14:42:04 +0100227 this.surface = surface;
Jorim Jaggi64be98d2018-04-26 23:23:29 +0200228 this.alpha = alpha;
229 this.matrix = new Matrix(matrix);
230 this.windowCrop = new Rect(windowCrop);
231 this.layer = layer;
Lucas Dupin086c6fc2018-10-16 18:06:43 -0700232 this.cornerRadius = cornerRadius;
Jorim Jaggi67684882019-01-22 17:36:34 +0100233 this.visible = visible;
Jorim Jaggi64be98d2018-04-26 23:23:29 +0200234 }
235
Mark Renoufdf0f3bc2019-09-16 14:04:38 -0400236
237 /**
238 * Constructs surface parameters to be applied when the current view state gets pushed to
239 * RenderThread.
240 *
241 * @param surface The surface to modify.
242 * @param alpha Alpha to apply.
243 * @param matrix Matrix to apply.
244 * @param windowCrop Crop to apply.
245 * @param layer The layer to apply.
246 * @param cornerRadius The corner radius to apply.
247 * @param visible The visibility to apply.
248 *
249 * @deprecated Use {@link SurfaceParams.Builder} to create an instance.
250 */
251 @Deprecated
252 public SurfaceParams(SurfaceControl surface, float alpha, Matrix matrix,
253 Rect windowCrop, int layer, float cornerRadius, boolean visible) {
254 this.flags = FLAG_ALL;
255 this.surface = surface;
256 this.alpha = alpha;
257 this.matrix = new Matrix(matrix);
Winson Chungd5852192019-09-06 17:20:28 -0700258 this.windowCrop = windowCrop != null ? new Rect(windowCrop) : null;
Mark Renoufdf0f3bc2019-09-16 14:04:38 -0400259 this.layer = layer;
260 this.cornerRadius = cornerRadius;
261 this.visible = visible;
262 }
263
264 private final int flags;
265
Jorim Jaggi5bb571d2018-11-06 14:42:04 +0100266 @VisibleForTesting
267 public final SurfaceControl surface;
268
269 @VisibleForTesting
270 public final float alpha;
271
272 @VisibleForTesting
Lucas Dupin086c6fc2018-10-16 18:06:43 -0700273 final float cornerRadius;
Jorim Jaggi5bb571d2018-11-06 14:42:04 +0100274
275 @VisibleForTesting
276 public final Matrix matrix;
277
278 @VisibleForTesting
279 public final Rect windowCrop;
280
281 @VisibleForTesting
282 public final int layer;
Jorim Jaggi67684882019-01-22 17:36:34 +0100283
284 public final boolean visible;
Jorim Jaggi64be98d2018-04-26 23:23:29 +0200285 }
286}