blob: 79a904f5fe65113a5faf639331e2a843ef0ea6a1 [file] [log] [blame]
Jeff Brown5541de92011-04-11 11:54:25 -07001/*
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#ifndef _UI_SPRITES_H
18#define _UI_SPRITES_H
19
20#include <utils/RefBase.h>
21#include <utils/Looper.h>
22
Mathias Agopian8335f1c2012-02-25 18:48:35 -080023#include <gui/SurfaceComposerClient.h>
Jeff Brown5541de92011-04-11 11:54:25 -070024
25#include <SkBitmap.h>
26
27namespace android {
28
29/*
30 * Transformation matrix for a sprite.
31 */
32struct SpriteTransformationMatrix {
33 inline SpriteTransformationMatrix() : dsdx(1.0f), dtdx(0.0f), dsdy(0.0f), dtdy(1.0f) { }
Jeff Brown2352b972011-04-12 22:39:53 -070034 inline SpriteTransformationMatrix(float dsdx, float dtdx, float dsdy, float dtdy) :
35 dsdx(dsdx), dtdx(dtdx), dsdy(dsdy), dtdy(dtdy) { }
Jeff Brown5541de92011-04-11 11:54:25 -070036
37 float dsdx;
38 float dtdx;
39 float dsdy;
40 float dtdy;
41
42 inline bool operator== (const SpriteTransformationMatrix& other) {
43 return dsdx == other.dsdx
44 && dtdx == other.dtdx
45 && dsdy == other.dsdy
46 && dtdy == other.dtdy;
47 }
48
49 inline bool operator!= (const SpriteTransformationMatrix& other) {
50 return !(*this == other);
51 }
52};
53
54/*
Jeff Brown2352b972011-04-12 22:39:53 -070055 * Icon that a sprite displays, including its hotspot.
56 */
57struct SpriteIcon {
Garfield Tan67e479a2019-08-05 16:47:40 -070058 inline SpriteIcon() : style(0), hotSpotX(0), hotSpotY(0) { }
59 inline SpriteIcon(const SkBitmap& bitmap, int32_t style, float hotSpotX, float hotSpotY) :
60 bitmap(bitmap), style(style), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { }
Jeff Brown2352b972011-04-12 22:39:53 -070061
62 SkBitmap bitmap;
Garfield Tan67e479a2019-08-05 16:47:40 -070063 int32_t style;
Jeff Brown2352b972011-04-12 22:39:53 -070064 float hotSpotX;
65 float hotSpotY;
66
67 inline SpriteIcon copy() const {
68 SkBitmap bitmapCopy;
Matt Sarett155d5212017-04-25 17:32:34 -040069 if (bitmapCopy.tryAllocPixels(bitmap.info().makeColorType(kN32_SkColorType))) {
70 bitmap.readPixels(bitmapCopy.info(), bitmapCopy.getPixels(), bitmapCopy.rowBytes(),
71 0, 0);
72 }
Garfield Tan67e479a2019-08-05 16:47:40 -070073 return SpriteIcon(bitmapCopy, style, hotSpotX, hotSpotY);
Jeff Brown2352b972011-04-12 22:39:53 -070074 }
75
76 inline void reset() {
77 bitmap.reset();
Garfield Tan67e479a2019-08-05 16:47:40 -070078 style = 0;
Jeff Brown2352b972011-04-12 22:39:53 -070079 hotSpotX = 0;
80 hotSpotY = 0;
81 }
82
83 inline bool isValid() const {
84 return !bitmap.isNull() && !bitmap.empty();
85 }
86};
87
88/*
Jeff Brown5541de92011-04-11 11:54:25 -070089 * A sprite is a simple graphical object that is displayed on-screen above other layers.
90 * The basic sprite class is an interface.
91 * The implementation is provided by the sprite controller.
92 */
93class Sprite : public RefBase {
94protected:
95 Sprite() { }
96 virtual ~Sprite() { }
97
98public:
Jeff Brown2352b972011-04-12 22:39:53 -070099 enum {
100 // The base layer for pointer sprites.
101 BASE_LAYER_POINTER = 0, // reserve space for 1 pointer
102
103 // The base layer for spot sprites.
104 BASE_LAYER_SPOT = 1, // reserve space for MAX_POINTER_ID spots
105 };
106
Jeff Brown5541de92011-04-11 11:54:25 -0700107 /* Sets the bitmap that is drawn by the sprite.
108 * The sprite retains a copy of the bitmap for subsequent rendering. */
Jeff Brown2352b972011-04-12 22:39:53 -0700109 virtual void setIcon(const SpriteIcon& icon) = 0;
110
111 inline void clearIcon() {
112 setIcon(SpriteIcon());
113 }
Jeff Brown5541de92011-04-11 11:54:25 -0700114
115 /* Sets whether the sprite is visible. */
116 virtual void setVisible(bool visible) = 0;
117
118 /* Sets the sprite position on screen, relative to the sprite's hot spot. */
119 virtual void setPosition(float x, float y) = 0;
120
121 /* Sets the layer of the sprite, relative to the system sprite overlay layer.
122 * Layer 0 is the overlay layer, > 0 appear above this layer. */
123 virtual void setLayer(int32_t layer) = 0;
124
125 /* Sets the sprite alpha blend ratio between 0.0 and 1.0. */
126 virtual void setAlpha(float alpha) = 0;
127
128 /* Sets the sprite transformation matrix. */
129 virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix) = 0;
Arthur Hungb9b32002018-12-18 17:39:43 +0800130
131 /* Sets the id of the display where the sprite should be shown. */
132 virtual void setDisplayId(int32_t displayId) = 0;
Jeff Brown5541de92011-04-11 11:54:25 -0700133};
134
135/*
136 * Displays sprites on the screen.
137 *
138 * This interface is used by PointerController and SpotController to draw pointers or
139 * spot representations of fingers. It is not intended for general purpose use
140 * by other components.
141 *
142 * All sprite position updates and rendering is performed asynchronously.
143 *
144 * Clients are responsible for animating sprites by periodically updating their properties.
145 */
146class SpriteController : public MessageHandler {
147protected:
148 virtual ~SpriteController();
149
150public:
151 SpriteController(const sp<Looper>& looper, int32_t overlayLayer);
152
153 /* Creates a new sprite, initially invisible. */
Garfield Tan67e479a2019-08-05 16:47:40 -0700154 virtual sp<Sprite> createSprite();
Jeff Brown5541de92011-04-11 11:54:25 -0700155
Jeff Brown2352b972011-04-12 22:39:53 -0700156 /* Opens or closes a transaction to perform a batch of sprite updates as part of
157 * a single operation such as setPosition and setAlpha. It is not necessary to
158 * open a transaction when updating a single property.
159 * Calls to openTransaction() nest and must be matched by an equal number
160 * of calls to closeTransaction(). */
Garfield Tan67e479a2019-08-05 16:47:40 -0700161 virtual void openTransaction();
162 virtual void closeTransaction();
Jeff Brown2352b972011-04-12 22:39:53 -0700163
Jeff Brown5541de92011-04-11 11:54:25 -0700164private:
165 enum {
166 MSG_UPDATE_SPRITES,
167 MSG_DISPOSE_SURFACES,
168 };
169
170 enum {
171 DIRTY_BITMAP = 1 << 0,
172 DIRTY_ALPHA = 1 << 1,
173 DIRTY_POSITION = 1 << 2,
174 DIRTY_TRANSFORMATION_MATRIX = 1 << 3,
175 DIRTY_LAYER = 1 << 4,
176 DIRTY_VISIBILITY = 1 << 5,
177 DIRTY_HOTSPOT = 1 << 6,
Arthur Hungb9b32002018-12-18 17:39:43 +0800178 DIRTY_DISPLAY_ID = 1 << 7,
Garfield Tan67e479a2019-08-05 16:47:40 -0700179 DIRTY_ICON_STYLE = 1 << 8,
Jeff Brown5541de92011-04-11 11:54:25 -0700180 };
181
182 /* Describes the state of a sprite.
183 * This structure is designed so that it can be copied during updates so that
184 * surfaces can be resized and redrawn without blocking the client by holding a lock
185 * on the sprites for a long time.
186 * Note that the SkBitmap holds a reference to a shared (and immutable) pixel ref. */
187 struct SpriteState {
188 inline SpriteState() :
Jeff Brown2352b972011-04-12 22:39:53 -0700189 dirty(0), visible(false),
Arthur Hungb9b32002018-12-18 17:39:43 +0800190 positionX(0), positionY(0), layer(0), alpha(1.0f), displayId(ADISPLAY_ID_DEFAULT),
Jeff Brown5541de92011-04-11 11:54:25 -0700191 surfaceWidth(0), surfaceHeight(0), surfaceDrawn(false), surfaceVisible(false) {
192 }
193
194 uint32_t dirty;
195
Jeff Brown2352b972011-04-12 22:39:53 -0700196 SpriteIcon icon;
Jeff Brown5541de92011-04-11 11:54:25 -0700197 bool visible;
198 float positionX;
199 float positionY;
200 int32_t layer;
201 float alpha;
202 SpriteTransformationMatrix transformationMatrix;
Arthur Hungb9b32002018-12-18 17:39:43 +0800203 int32_t displayId;
Jeff Brown5541de92011-04-11 11:54:25 -0700204
205 sp<SurfaceControl> surfaceControl;
206 int32_t surfaceWidth;
207 int32_t surfaceHeight;
208 bool surfaceDrawn;
209 bool surfaceVisible;
210
211 inline bool wantSurfaceVisible() const {
Jeff Brown2352b972011-04-12 22:39:53 -0700212 return visible && alpha > 0.0f && icon.isValid();
Jeff Brown5541de92011-04-11 11:54:25 -0700213 }
214 };
215
216 /* Client interface for a sprite.
217 * Requests acquire a lock on the controller, update local state and request the
218 * controller to invalidate the sprite.
219 * The real heavy lifting of creating, resizing and redrawing surfaces happens
220 * asynchronously with no locks held except in short critical section to copy
221 * the sprite state before the work and update the sprite surface control afterwards.
222 */
223 class SpriteImpl : public Sprite {
224 protected:
225 virtual ~SpriteImpl();
226
227 public:
Chih-Hung Hsieh6d09d542016-08-29 14:51:31 -0700228 explicit SpriteImpl(const sp<SpriteController> controller);
Jeff Brown5541de92011-04-11 11:54:25 -0700229
Jeff Brown2352b972011-04-12 22:39:53 -0700230 virtual void setIcon(const SpriteIcon& icon);
Jeff Brown5541de92011-04-11 11:54:25 -0700231 virtual void setVisible(bool visible);
232 virtual void setPosition(float x, float y);
233 virtual void setLayer(int32_t layer);
234 virtual void setAlpha(float alpha);
235 virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix);
Arthur Hungb9b32002018-12-18 17:39:43 +0800236 virtual void setDisplayId(int32_t displayId);
Jeff Brown5541de92011-04-11 11:54:25 -0700237
238 inline const SpriteState& getStateLocked() const {
Jeff Brown2352b972011-04-12 22:39:53 -0700239 return mLocked.state;
Jeff Brown5541de92011-04-11 11:54:25 -0700240 }
241
242 inline void resetDirtyLocked() {
Jeff Brown2352b972011-04-12 22:39:53 -0700243 mLocked.state.dirty = 0;
Jeff Brown5541de92011-04-11 11:54:25 -0700244 }
245
246 inline void setSurfaceLocked(const sp<SurfaceControl>& surfaceControl,
247 int32_t width, int32_t height, bool drawn, bool visible) {
Jeff Brown2352b972011-04-12 22:39:53 -0700248 mLocked.state.surfaceControl = surfaceControl;
249 mLocked.state.surfaceWidth = width;
250 mLocked.state.surfaceHeight = height;
251 mLocked.state.surfaceDrawn = drawn;
252 mLocked.state.surfaceVisible = visible;
Jeff Brown5541de92011-04-11 11:54:25 -0700253 }
254
255 private:
256 sp<SpriteController> mController;
257
Jeff Brown2352b972011-04-12 22:39:53 -0700258 struct Locked {
259 SpriteState state;
260 } mLocked; // guarded by mController->mLock
Jeff Brown5541de92011-04-11 11:54:25 -0700261
262 void invalidateLocked(uint32_t dirty);
263 };
264
265 /* Stores temporary information collected during the sprite update cycle. */
266 struct SpriteUpdate {
267 inline SpriteUpdate() : surfaceChanged(false) { }
268 inline SpriteUpdate(const sp<SpriteImpl> sprite, const SpriteState& state) :
269 sprite(sprite), state(state), surfaceChanged(false) {
270 }
271
272 sp<SpriteImpl> sprite;
273 SpriteState state;
274 bool surfaceChanged;
275 };
276
277 mutable Mutex mLock;
278
279 sp<Looper> mLooper;
280 const int32_t mOverlayLayer;
281 sp<WeakMessageHandler> mHandler;
282
283 sp<SurfaceComposerClient> mSurfaceComposerClient;
284
Jeff Brown2352b972011-04-12 22:39:53 -0700285 struct Locked {
286 Vector<sp<SpriteImpl> > invalidatedSprites;
287 Vector<sp<SurfaceControl> > disposedSurfaces;
288 uint32_t transactionNestingCount;
289 bool deferredSpriteUpdate;
290 } mLocked; // guarded by mLock
Jeff Brown5541de92011-04-11 11:54:25 -0700291
292 void invalidateSpriteLocked(const sp<SpriteImpl>& sprite);
293 void disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl);
294
295 void handleMessage(const Message& message);
296 void doUpdateSprites();
297 void doDisposeSurfaces();
298
299 void ensureSurfaceComposerClient();
300 sp<SurfaceControl> obtainSurface(int32_t width, int32_t height);
301};
302
303} // namespace android
304
305#endif // _UI_SPRITES_H