OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.compositor; | 5 package org.chromium.chrome.browser.compositor; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
8 import android.graphics.PixelFormat; | 8 import android.graphics.PixelFormat; |
9 import android.graphics.drawable.Drawable; | 9 import android.graphics.drawable.Drawable; |
10 import android.view.SurfaceHolder; | 10 import android.view.SurfaceHolder; |
11 import android.view.SurfaceView; | 11 import android.view.SurfaceView; |
12 import android.view.View; | 12 import android.view.View; |
13 import android.view.ViewGroup; | 13 import android.view.ViewGroup; |
14 import android.widget.FrameLayout; | 14 import android.widget.FrameLayout; |
15 | 15 |
| 16 import org.chromium.base.annotations.UsedByReflection; |
| 17 |
16 /** | 18 /** |
17 * Manage multiple SurfaceViews for the compositor, so that transitions between | 19 * Manage multiple SurfaceViews for the compositor, so that transitions between |
18 * surfaces with and without an alpha channel can be visually smooth. | 20 * surfaces with and without an alpha channel can be visually smooth. |
19 * | 21 * |
20 * This class allows a client to request a 'translucent' or 'opaque' surface, an
d we will signal via | 22 * This class allows a client to request a 'translucent' or 'opaque' surface, an
d we will signal via |
21 * SurfaceHolder.Callback when it's ready. We guarantee that the client will re
ceive surfaceCreated | 23 * SurfaceHolder.Callback when it's ready. We guarantee that the client will re
ceive surfaceCreated |
22 * / surfaceDestroyed only for a surface that represents the most recently reque
sted PixelFormat. | 24 * / surfaceDestroyed only for a surface that represents the most recently reque
sted PixelFormat. |
23 * | 25 * |
24 * Internally, we maintain two SurfaceViews, since calling setFormat() to change
the PixelFormat | 26 * Internally, we maintain two SurfaceViews, since calling setFormat() to change
the PixelFormat |
25 * results in a visual glitch as the surface is torn down. crbug.com/679902 | 27 * results in a visual glitch as the surface is torn down. crbug.com/679902 |
26 * | 28 * |
27 * The client has the responsibility to call doneWithUnownedSurface() at some po
int between when we | 29 * The client has the responsibility to call doneWithUnownedSurface() at some po
int between when we |
28 * call back its surfaceCreated, when it is safe for us to hide the SurfaceView
with the wrong | 30 * call back its surfaceCreated, when it is safe for us to hide the SurfaceView
with the wrong |
29 * format. It is okay if it requests multiple surfaces without calling doneWith
UnownedSurface. | 31 * format. It is okay if it requests multiple surfaces without calling doneWith
UnownedSurface. |
30 * | 32 * |
31 * If the client requests the same format more than once in a row, it will still
receive destroyed / | 33 * If the client requests the same format more than once in a row, it will still
receive destroyed / |
32 * created / changed messages for it, even though we won't tear it down. | 34 * created / changed messages for it, even though we won't tear it down. |
33 * | 35 * |
34 * The full design doc is at https://goo.gl/aAmQzR . | 36 * The full design doc is at https://goo.gl/aAmQzR . |
35 */ | 37 */ |
36 class CompositorSurfaceManager implements SurfaceHolder.Callback { | 38 class CompositorSurfaceManager implements SurfaceHolder.Callback2 { |
| 39 public interface SurfaceHolderCallbackTarget { |
| 40 public void surfaceRedrawNeededAsync(SurfaceHolder holder, Runnable draw
ingFinished); |
| 41 public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height); |
| 42 public void surfaceCreated(SurfaceHolder holder); |
| 43 public void surfaceDestroyed(SurfaceHolder holder); |
| 44 } |
| 45 |
37 private static class SurfaceState { | 46 private static class SurfaceState { |
38 public SurfaceView surfaceView; | 47 public SurfaceView surfaceView; |
39 | 48 |
40 // Do we expect a surfaceCreated? | 49 // Do we expect a surfaceCreated? |
41 public boolean createPending; | 50 public boolean createPending; |
42 | 51 |
43 // Have we started destroying |surfaceView|, but haven't received surfac
eDestroyed yet? | 52 // Have we started destroying |surfaceView|, but haven't received surfac
eDestroyed yet? |
44 public boolean destroyPending; | 53 public boolean destroyPending; |
45 | 54 |
46 // Last PixelFormat that we received, or UNKNOWN if we don't know / don'
t want to cache it. | 55 // Last PixelFormat that we received, or UNKNOWN if we don't know / don'
t want to cache it. |
47 public int format; | 56 public int format; |
48 | 57 |
49 // Last known width, height for thsi surface. | 58 // Last known width, height for thsi surface. |
50 public int width; | 59 public int width; |
51 public int height; | 60 public int height; |
52 | 61 |
53 // Parent ViewGroup, or null. | 62 // Parent ViewGroup, or null. |
54 private ViewGroup mParent; | 63 private ViewGroup mParent; |
55 | 64 |
56 public SurfaceState(Context context, int format, SurfaceHolder.Callback
callback) { | 65 public SurfaceState(Context context, int format, SurfaceHolder.Callback2
callback) { |
57 surfaceView = new SurfaceView(context); | 66 surfaceView = new SurfaceView(context); |
58 surfaceView.setZOrderMediaOverlay(true); | 67 surfaceView.setZOrderMediaOverlay(true); |
59 surfaceView.setVisibility(View.VISIBLE); | 68 surfaceView.setVisibility(View.VISIBLE); |
60 surfaceHolder().setFormat(format); | 69 surfaceHolder().setFormat(format); |
61 surfaceHolder().addCallback(callback); | 70 surfaceHolder().addCallback(callback); |
62 | 71 |
63 // Set this to UNKNOWN until we get a format back. | 72 // Set this to UNKNOWN until we get a format back. |
64 this.format = PixelFormat.UNKNOWN; | 73 this.format = PixelFormat.UNKNOWN; |
65 } | 74 } |
66 | 75 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 // Surface that we last gave to the client with surfaceCreated. Cleared whe
n we call | 111 // Surface that we last gave to the client with surfaceCreated. Cleared whe
n we call |
103 // surfaceDestroyed on |mClient|. Note that it's not necessary that Android
has notified us | 112 // surfaceDestroyed on |mClient|. Note that it's not necessary that Android
has notified us |
104 // the surface has been destroyed; we deliberately keep it around until the
client tells us that | 113 // the surface has been destroyed; we deliberately keep it around until the
client tells us that |
105 // it's okay to get rid of it. | 114 // it's okay to get rid of it. |
106 private SurfaceState mOwnedByClient; | 115 private SurfaceState mOwnedByClient; |
107 | 116 |
108 // Surface that was most recently requested by the client. | 117 // Surface that was most recently requested by the client. |
109 private SurfaceState mRequestedByClient; | 118 private SurfaceState mRequestedByClient; |
110 | 119 |
111 // Client that we notify about surface change events. | 120 // Client that we notify about surface change events. |
112 private SurfaceHolder.Callback mClient; | 121 private SurfaceHolderCallbackTarget mClient; |
113 | 122 |
114 // View to which we'll attach the SurfaceView. | 123 // View to which we'll attach the SurfaceView. |
115 private final ViewGroup mParentView; | 124 private final ViewGroup mParentView; |
116 | 125 |
117 public CompositorSurfaceManager(ViewGroup parentView, SurfaceHolder.Callback
client) { | 126 public CompositorSurfaceManager(ViewGroup parentView, SurfaceHolderCallbackT
arget client) { |
118 mParentView = parentView; | 127 mParentView = parentView; |
119 mClient = client; | 128 mClient = client; |
120 | 129 |
121 mTranslucent = new SurfaceState(parentView.getContext(), PixelFormat.TRA
NSLUCENT, this); | 130 mTranslucent = new SurfaceState(parentView.getContext(), PixelFormat.TRA
NSLUCENT, this); |
122 mOpaque = new SurfaceState(mParentView.getContext(), PixelFormat.OPAQUE,
this); | 131 mOpaque = new SurfaceState(mParentView.getContext(), PixelFormat.OPAQUE,
this); |
123 } | 132 } |
124 | 133 |
125 /** | 134 /** |
126 * Turn off everything. | 135 * Turn off everything. |
127 */ | 136 */ |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 // client has requested a different surface but hasn't gotten it yet, th
en skip this. | 256 // client has requested a different surface but hasn't gotten it yet, th
en skip this. |
248 if (state == mOwnedByClient && state == mRequestedByClient) { | 257 if (state == mOwnedByClient && state == mRequestedByClient) { |
249 state.width = width; | 258 state.width = width; |
250 state.height = height; | 259 state.height = height; |
251 state.format = format; | 260 state.format = format; |
252 mClient.surfaceChanged(holder, format, width, height); | 261 mClient.surfaceChanged(holder, format, width, height); |
253 } | 262 } |
254 } | 263 } |
255 | 264 |
256 @Override | 265 @Override |
| 266 public void surfaceRedrawNeeded(SurfaceHolder holder) { |
| 267 // Intentionally not implemented. |
| 268 } |
| 269 |
| 270 // TODO(boliu): Mark this override instead. |
| 271 @UsedByReflection("Android") |
| 272 public void surfaceRedrawNeededAsync(SurfaceHolder holder, Runnable drawingF
inished) { |
| 273 mClient.surfaceRedrawNeededAsync(holder, drawingFinished); |
| 274 } |
| 275 |
| 276 @Override |
257 public void surfaceCreated(SurfaceHolder holder) { | 277 public void surfaceCreated(SurfaceHolder holder) { |
258 SurfaceState state = getStateForHolder(holder); | 278 SurfaceState state = getStateForHolder(holder); |
259 assert state != null; | 279 assert state != null; |
260 // Note that |createPending| might not be set, if Android destroyed and
recreated this | 280 // Note that |createPending| might not be set, if Android destroyed and
recreated this |
261 // surface on its own. | 281 // surface on its own. |
262 | 282 |
263 if (state != mRequestedByClient) { | 283 if (state != mRequestedByClient) { |
264 // Surface is created, but it's not the one that's been requested mo
st recently. Just | 284 // Surface is created, but it's not the one that's been requested mo
st recently. Just |
265 // destroy it again. | 285 // destroy it again. |
266 detachSurfaceLater(state); | 286 detachSurfaceLater(state); |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 | 471 |
452 state.destroyPending = true; | 472 state.destroyPending = true; |
453 mParentView.post(new Runnable() { | 473 mParentView.post(new Runnable() { |
454 @Override | 474 @Override |
455 public void run() { | 475 public void run() { |
456 detachSurfaceNow(state); | 476 detachSurfaceNow(state); |
457 } | 477 } |
458 }); | 478 }); |
459 } | 479 } |
460 } | 480 } |
OLD | NEW |