blob: 2513544d4bdffc08290aaae7721c4585ce790930 [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
Derek Sollenberger9ca5bbe2019-08-14 15:50:59 -040023#include <android/graphics/bitmap.h>
Mathias Agopian8335f1c2012-02-25 18:48:35 -080024#include <gui/SurfaceComposerClient.h>
Jeff Brown5541de92011-04-11 11:54:25 -070025
Jeff Brown5541de92011-04-11 11:54:25 -070026namespace android {
27
28/*
29 * Transformation matrix for a sprite.
30 */
31struct SpriteTransformationMatrix {
32 inline SpriteTransformationMatrix() : dsdx(1.0f), dtdx(0.0f), dsdy(0.0f), dtdy(1.0f) { }
Jeff Brown2352b972011-04-12 22:39:53 -070033 inline SpriteTransformationMatrix(float dsdx, float dtdx, float dsdy, float dtdy) :
34 dsdx(dsdx), dtdx(dtdx), dsdy(dsdy), dtdy(dtdy) { }
Jeff Brown5541de92011-04-11 11:54:25 -070035
36 float dsdx;
37 float dtdx;
38 float dsdy;
39 float dtdy;
40
41 inline bool operator== (const SpriteTransformationMatrix& other) {
42 return dsdx == other.dsdx
43 && dtdx == other.dtdx
44 && dsdy == other.dsdy
45 && dtdy == other.dtdy;
46 }
47
48 inline bool operator!= (const SpriteTransformationMatrix& other) {
49 return !(*this == other);
50 }
51};
52
53/*
Jeff Brown2352b972011-04-12 22:39:53 -070054 * Icon that a sprite displays, including its hotspot.
55 */
56struct SpriteIcon {
Garfield Tan67e479a2019-08-05 16:47:40 -070057 inline SpriteIcon() : style(0), hotSpotX(0), hotSpotY(0) { }
Derek Sollenberger9ca5bbe2019-08-14 15:50:59 -040058 inline SpriteIcon(const graphics::Bitmap& bitmap, int32_t style, float hotSpotX, float hotSpotY) :
Garfield Tan67e479a2019-08-05 16:47:40 -070059 bitmap(bitmap), style(style), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { }
Jeff Brown2352b972011-04-12 22:39:53 -070060
Derek Sollenberger9ca5bbe2019-08-14 15:50:59 -040061 graphics::Bitmap bitmap;
Garfield Tan67e479a2019-08-05 16:47:40 -070062 int32_t style;
Jeff Brown2352b972011-04-12 22:39:53 -070063 float hotSpotX;
64 float hotSpotY;
65
66 inline SpriteIcon copy() const {
Derek Sollenberger9ca5bbe2019-08-14 15:50:59 -040067 return SpriteIcon(bitmap.copy(ANDROID_BITMAP_FORMAT_RGBA_8888), style, hotSpotX, hotSpotY);
Jeff Brown2352b972011-04-12 22:39:53 -070068 }
69
70 inline void reset() {
71 bitmap.reset();
Garfield Tan67e479a2019-08-05 16:47:40 -070072 style = 0;
Jeff Brown2352b972011-04-12 22:39:53 -070073 hotSpotX = 0;
74 hotSpotY = 0;
75 }
76
77 inline bool isValid() const {
Derek Sollenberger9ca5bbe2019-08-14 15:50:59 -040078 return bitmap.isValid() && !bitmap.isEmpty();
Jeff Brown2352b972011-04-12 22:39:53 -070079 }
80};
81
82/*
Jeff Brown5541de92011-04-11 11:54:25 -070083 * A sprite is a simple graphical object that is displayed on-screen above other layers.
84 * The basic sprite class is an interface.
85 * The implementation is provided by the sprite controller.
86 */
87class Sprite : public RefBase {
88protected:
89 Sprite() { }
90 virtual ~Sprite() { }
91
92public:
Jeff Brown2352b972011-04-12 22:39:53 -070093 enum {
94 // The base layer for pointer sprites.
95 BASE_LAYER_POINTER = 0, // reserve space for 1 pointer
96
97 // The base layer for spot sprites.
98 BASE_LAYER_SPOT = 1, // reserve space for MAX_POINTER_ID spots
99 };
100
Jeff Brown5541de92011-04-11 11:54:25 -0700101 /* Sets the bitmap that is drawn by the sprite.
102 * The sprite retains a copy of the bitmap for subsequent rendering. */
Jeff Brown2352b972011-04-12 22:39:53 -0700103 virtual void setIcon(const SpriteIcon& icon) = 0;
104
105 inline void clearIcon() {
106 setIcon(SpriteIcon());
107 }
Jeff Brown5541de92011-04-11 11:54:25 -0700108
109 /* Sets whether the sprite is visible. */
110 virtual void setVisible(bool visible) = 0;
111
112 /* Sets the sprite position on screen, relative to the sprite's hot spot. */
113 virtual void setPosition(float x, float y) = 0;
114
115 /* Sets the layer of the sprite, relative to the system sprite overlay layer.
116 * Layer 0 is the overlay layer, > 0 appear above this layer. */
117 virtual void setLayer(int32_t layer) = 0;
118
119 /* Sets the sprite alpha blend ratio between 0.0 and 1.0. */
120 virtual void setAlpha(float alpha) = 0;
121
122 /* Sets the sprite transformation matrix. */
123 virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix) = 0;
Arthur Hungb9b32002018-12-18 17:39:43 +0800124
125 /* Sets the id of the display where the sprite should be shown. */
126 virtual void setDisplayId(int32_t displayId) = 0;
Jeff Brown5541de92011-04-11 11:54:25 -0700127};
128
129/*
130 * Displays sprites on the screen.
131 *
132 * This interface is used by PointerController and SpotController to draw pointers or
133 * spot representations of fingers. It is not intended for general purpose use
134 * by other components.
135 *
136 * All sprite position updates and rendering is performed asynchronously.
137 *
138 * Clients are responsible for animating sprites by periodically updating their properties.
139 */
140class SpriteController : public MessageHandler {
141protected:
142 virtual ~SpriteController();
143
144public:
145 SpriteController(const sp<Looper>& looper, int32_t overlayLayer);
146
147 /* Creates a new sprite, initially invisible. */
Garfield Tan67e479a2019-08-05 16:47:40 -0700148 virtual sp<Sprite> createSprite();
Jeff Brown5541de92011-04-11 11:54:25 -0700149
Jeff Brown2352b972011-04-12 22:39:53 -0700150 /* Opens or closes a transaction to perform a batch of sprite updates as part of
151 * a single operation such as setPosition and setAlpha. It is not necessary to
152 * open a transaction when updating a single property.
153 * Calls to openTransaction() nest and must be matched by an equal number
154 * of calls to closeTransaction(). */
Garfield Tan67e479a2019-08-05 16:47:40 -0700155 virtual void openTransaction();
156 virtual void closeTransaction();
Jeff Brown2352b972011-04-12 22:39:53 -0700157
Jeff Brown5541de92011-04-11 11:54:25 -0700158private:
159 enum {
160 MSG_UPDATE_SPRITES,
161 MSG_DISPOSE_SURFACES,
162 };
163
164 enum {
165 DIRTY_BITMAP = 1 << 0,
166 DIRTY_ALPHA = 1 << 1,
167 DIRTY_POSITION = 1 << 2,
168 DIRTY_TRANSFORMATION_MATRIX = 1 << 3,
169 DIRTY_LAYER = 1 << 4,
170 DIRTY_VISIBILITY = 1 << 5,
171 DIRTY_HOTSPOT = 1 << 6,
Arthur Hungb9b32002018-12-18 17:39:43 +0800172 DIRTY_DISPLAY_ID = 1 << 7,
Garfield Tan67e479a2019-08-05 16:47:40 -0700173 DIRTY_ICON_STYLE = 1 << 8,
Jeff Brown5541de92011-04-11 11:54:25 -0700174 };
175
176 /* Describes the state of a sprite.
177 * This structure is designed so that it can be copied during updates so that
178 * surfaces can be resized and redrawn without blocking the client by holding a lock
179 * on the sprites for a long time.
Derek Sollenberger9ca5bbe2019-08-14 15:50:59 -0400180 * Note that the SpriteIcon holds a reference to a shared (and immutable) bitmap. */
Jeff Brown5541de92011-04-11 11:54:25 -0700181 struct SpriteState {
182 inline SpriteState() :
Jeff Brown2352b972011-04-12 22:39:53 -0700183 dirty(0), visible(false),
Arthur Hungb9b32002018-12-18 17:39:43 +0800184 positionX(0), positionY(0), layer(0), alpha(1.0f), displayId(ADISPLAY_ID_DEFAULT),
Jeff Brown5541de92011-04-11 11:54:25 -0700185 surfaceWidth(0), surfaceHeight(0), surfaceDrawn(false), surfaceVisible(false) {
186 }
187
188 uint32_t dirty;
189
Jeff Brown2352b972011-04-12 22:39:53 -0700190 SpriteIcon icon;
Jeff Brown5541de92011-04-11 11:54:25 -0700191 bool visible;
192 float positionX;
193 float positionY;
194 int32_t layer;
195 float alpha;
196 SpriteTransformationMatrix transformationMatrix;
Arthur Hungb9b32002018-12-18 17:39:43 +0800197 int32_t displayId;
Jeff Brown5541de92011-04-11 11:54:25 -0700198
199 sp<SurfaceControl> surfaceControl;
200 int32_t surfaceWidth;
201 int32_t surfaceHeight;
202 bool surfaceDrawn;
203 bool surfaceVisible;
204
205 inline bool wantSurfaceVisible() const {
Jeff Brown2352b972011-04-12 22:39:53 -0700206 return visible && alpha > 0.0f && icon.isValid();
Jeff Brown5541de92011-04-11 11:54:25 -0700207 }
208 };
209
210 /* Client interface for a sprite.
211 * Requests acquire a lock on the controller, update local state and request the
212 * controller to invalidate the sprite.
213 * The real heavy lifting of creating, resizing and redrawing surfaces happens
214 * asynchronously with no locks held except in short critical section to copy
215 * the sprite state before the work and update the sprite surface control afterwards.
216 */
217 class SpriteImpl : public Sprite {
218 protected:
219 virtual ~SpriteImpl();
220
221 public:
Chih-Hung Hsieh6d09d542016-08-29 14:51:31 -0700222 explicit SpriteImpl(const sp<SpriteController> controller);
Jeff Brown5541de92011-04-11 11:54:25 -0700223
Jeff Brown2352b972011-04-12 22:39:53 -0700224 virtual void setIcon(const SpriteIcon& icon);
Jeff Brown5541de92011-04-11 11:54:25 -0700225 virtual void setVisible(bool visible);
226 virtual void setPosition(float x, float y);
227 virtual void setLayer(int32_t layer);
228 virtual void setAlpha(float alpha);
229 virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix);
Arthur Hungb9b32002018-12-18 17:39:43 +0800230 virtual void setDisplayId(int32_t displayId);
Jeff Brown5541de92011-04-11 11:54:25 -0700231
232 inline const SpriteState& getStateLocked() const {
Jeff Brown2352b972011-04-12 22:39:53 -0700233 return mLocked.state;
Jeff Brown5541de92011-04-11 11:54:25 -0700234 }
235
236 inline void resetDirtyLocked() {
Jeff Brown2352b972011-04-12 22:39:53 -0700237 mLocked.state.dirty = 0;
Jeff Brown5541de92011-04-11 11:54:25 -0700238 }
239
240 inline void setSurfaceLocked(const sp<SurfaceControl>& surfaceControl,
241 int32_t width, int32_t height, bool drawn, bool visible) {
Jeff Brown2352b972011-04-12 22:39:53 -0700242 mLocked.state.surfaceControl = surfaceControl;
243 mLocked.state.surfaceWidth = width;
244 mLocked.state.surfaceHeight = height;
245 mLocked.state.surfaceDrawn = drawn;
246 mLocked.state.surfaceVisible = visible;
Jeff Brown5541de92011-04-11 11:54:25 -0700247 }
248
249 private:
250 sp<SpriteController> mController;
251
Jeff Brown2352b972011-04-12 22:39:53 -0700252 struct Locked {
253 SpriteState state;
254 } mLocked; // guarded by mController->mLock
Jeff Brown5541de92011-04-11 11:54:25 -0700255
256 void invalidateLocked(uint32_t dirty);
257 };
258
259 /* Stores temporary information collected during the sprite update cycle. */
260 struct SpriteUpdate {
261 inline SpriteUpdate() : surfaceChanged(false) { }
262 inline SpriteUpdate(const sp<SpriteImpl> sprite, const SpriteState& state) :
263 sprite(sprite), state(state), surfaceChanged(false) {
264 }
265
266 sp<SpriteImpl> sprite;
267 SpriteState state;
268 bool surfaceChanged;
269 };
270
271 mutable Mutex mLock;
272
273 sp<Looper> mLooper;
274 const int32_t mOverlayLayer;
275 sp<WeakMessageHandler> mHandler;
276
277 sp<SurfaceComposerClient> mSurfaceComposerClient;
278
Jeff Brown2352b972011-04-12 22:39:53 -0700279 struct Locked {
280 Vector<sp<SpriteImpl> > invalidatedSprites;
281 Vector<sp<SurfaceControl> > disposedSurfaces;
282 uint32_t transactionNestingCount;
283 bool deferredSpriteUpdate;
284 } mLocked; // guarded by mLock
Jeff Brown5541de92011-04-11 11:54:25 -0700285
286 void invalidateSpriteLocked(const sp<SpriteImpl>& sprite);
287 void disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl);
288
289 void handleMessage(const Message& message);
290 void doUpdateSprites();
291 void doDisposeSurfaces();
292
293 void ensureSurfaceComposerClient();
294 sp<SurfaceControl> obtainSurface(int32_t width, int32_t height);
295};
296
297} // namespace android
298
299#endif // _UI_SPRITES_H