blob: 50ae8a538869af6396d3ad9a717a9ef7d7594e53 [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
23#include <surfaceflinger/Surface.h>
24#include <surfaceflinger/SurfaceComposerClient.h>
25#include <surfaceflinger/ISurfaceComposer.h>
26
27#include <SkBitmap.h>
28
29namespace android {
30
31/*
32 * Transformation matrix for a sprite.
33 */
34struct SpriteTransformationMatrix {
35 inline SpriteTransformationMatrix() : dsdx(1.0f), dtdx(0.0f), dsdy(0.0f), dtdy(1.0f) { }
Jeff Brown2352b972011-04-12 22:39:53 -070036 inline SpriteTransformationMatrix(float dsdx, float dtdx, float dsdy, float dtdy) :
37 dsdx(dsdx), dtdx(dtdx), dsdy(dsdy), dtdy(dtdy) { }
Jeff Brown5541de92011-04-11 11:54:25 -070038
39 float dsdx;
40 float dtdx;
41 float dsdy;
42 float dtdy;
43
44 inline bool operator== (const SpriteTransformationMatrix& other) {
45 return dsdx == other.dsdx
46 && dtdx == other.dtdx
47 && dsdy == other.dsdy
48 && dtdy == other.dtdy;
49 }
50
51 inline bool operator!= (const SpriteTransformationMatrix& other) {
52 return !(*this == other);
53 }
54};
55
56/*
Jeff Brown2352b972011-04-12 22:39:53 -070057 * Icon that a sprite displays, including its hotspot.
58 */
59struct SpriteIcon {
60 inline SpriteIcon() : hotSpotX(0), hotSpotY(0) { }
61 inline SpriteIcon(const SkBitmap& bitmap, float hotSpotX, float hotSpotY) :
62 bitmap(bitmap), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { }
63
64 SkBitmap bitmap;
65 float hotSpotX;
66 float hotSpotY;
67
68 inline SpriteIcon copy() const {
69 SkBitmap bitmapCopy;
70 bitmap.copyTo(&bitmapCopy, SkBitmap::kARGB_8888_Config);
71 return SpriteIcon(bitmapCopy, hotSpotX, hotSpotY);
72 }
73
74 inline void reset() {
75 bitmap.reset();
76 hotSpotX = 0;
77 hotSpotY = 0;
78 }
79
80 inline bool isValid() const {
81 return !bitmap.isNull() && !bitmap.empty();
82 }
83};
84
85/*
Jeff Brown5541de92011-04-11 11:54:25 -070086 * A sprite is a simple graphical object that is displayed on-screen above other layers.
87 * The basic sprite class is an interface.
88 * The implementation is provided by the sprite controller.
89 */
90class Sprite : public RefBase {
91protected:
92 Sprite() { }
93 virtual ~Sprite() { }
94
95public:
Jeff Brown2352b972011-04-12 22:39:53 -070096 enum {
97 // The base layer for pointer sprites.
98 BASE_LAYER_POINTER = 0, // reserve space for 1 pointer
99
100 // The base layer for spot sprites.
101 BASE_LAYER_SPOT = 1, // reserve space for MAX_POINTER_ID spots
102 };
103
Jeff Brown5541de92011-04-11 11:54:25 -0700104 /* Sets the bitmap that is drawn by the sprite.
105 * The sprite retains a copy of the bitmap for subsequent rendering. */
Jeff Brown2352b972011-04-12 22:39:53 -0700106 virtual void setIcon(const SpriteIcon& icon) = 0;
107
108 inline void clearIcon() {
109 setIcon(SpriteIcon());
110 }
Jeff Brown5541de92011-04-11 11:54:25 -0700111
112 /* Sets whether the sprite is visible. */
113 virtual void setVisible(bool visible) = 0;
114
115 /* Sets the sprite position on screen, relative to the sprite's hot spot. */
116 virtual void setPosition(float x, float y) = 0;
117
118 /* Sets the layer of the sprite, relative to the system sprite overlay layer.
119 * Layer 0 is the overlay layer, > 0 appear above this layer. */
120 virtual void setLayer(int32_t layer) = 0;
121
122 /* Sets the sprite alpha blend ratio between 0.0 and 1.0. */
123 virtual void setAlpha(float alpha) = 0;
124
125 /* Sets the sprite transformation matrix. */
126 virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix) = 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. */
148 sp<Sprite> createSprite();
149
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(). */
155 void openTransaction();
156 void closeTransaction();
157
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,
172 };
173
174 /* Describes the state of a sprite.
175 * This structure is designed so that it can be copied during updates so that
176 * surfaces can be resized and redrawn without blocking the client by holding a lock
177 * on the sprites for a long time.
178 * Note that the SkBitmap holds a reference to a shared (and immutable) pixel ref. */
179 struct SpriteState {
180 inline SpriteState() :
Jeff Brown2352b972011-04-12 22:39:53 -0700181 dirty(0), visible(false),
Jeff Brown5541de92011-04-11 11:54:25 -0700182 positionX(0), positionY(0), layer(0), alpha(1.0f),
183 surfaceWidth(0), surfaceHeight(0), surfaceDrawn(false), surfaceVisible(false) {
184 }
185
186 uint32_t dirty;
187
Jeff Brown2352b972011-04-12 22:39:53 -0700188 SpriteIcon icon;
Jeff Brown5541de92011-04-11 11:54:25 -0700189 bool visible;
190 float positionX;
191 float positionY;
192 int32_t layer;
193 float alpha;
194 SpriteTransformationMatrix transformationMatrix;
195
196 sp<SurfaceControl> surfaceControl;
197 int32_t surfaceWidth;
198 int32_t surfaceHeight;
199 bool surfaceDrawn;
200 bool surfaceVisible;
201
202 inline bool wantSurfaceVisible() const {
Jeff Brown2352b972011-04-12 22:39:53 -0700203 return visible && alpha > 0.0f && icon.isValid();
Jeff Brown5541de92011-04-11 11:54:25 -0700204 }
205 };
206
207 /* Client interface for a sprite.
208 * Requests acquire a lock on the controller, update local state and request the
209 * controller to invalidate the sprite.
210 * The real heavy lifting of creating, resizing and redrawing surfaces happens
211 * asynchronously with no locks held except in short critical section to copy
212 * the sprite state before the work and update the sprite surface control afterwards.
213 */
214 class SpriteImpl : public Sprite {
215 protected:
216 virtual ~SpriteImpl();
217
218 public:
219 SpriteImpl(const sp<SpriteController> controller);
220
Jeff Brown2352b972011-04-12 22:39:53 -0700221 virtual void setIcon(const SpriteIcon& icon);
Jeff Brown5541de92011-04-11 11:54:25 -0700222 virtual void setVisible(bool visible);
223 virtual void setPosition(float x, float y);
224 virtual void setLayer(int32_t layer);
225 virtual void setAlpha(float alpha);
226 virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix);
Jeff Brown5541de92011-04-11 11:54:25 -0700227
228 inline const SpriteState& getStateLocked() const {
Jeff Brown2352b972011-04-12 22:39:53 -0700229 return mLocked.state;
Jeff Brown5541de92011-04-11 11:54:25 -0700230 }
231
232 inline void resetDirtyLocked() {
Jeff Brown2352b972011-04-12 22:39:53 -0700233 mLocked.state.dirty = 0;
Jeff Brown5541de92011-04-11 11:54:25 -0700234 }
235
236 inline void setSurfaceLocked(const sp<SurfaceControl>& surfaceControl,
237 int32_t width, int32_t height, bool drawn, bool visible) {
Jeff Brown2352b972011-04-12 22:39:53 -0700238 mLocked.state.surfaceControl = surfaceControl;
239 mLocked.state.surfaceWidth = width;
240 mLocked.state.surfaceHeight = height;
241 mLocked.state.surfaceDrawn = drawn;
242 mLocked.state.surfaceVisible = visible;
Jeff Brown5541de92011-04-11 11:54:25 -0700243 }
244
245 private:
246 sp<SpriteController> mController;
247
Jeff Brown2352b972011-04-12 22:39:53 -0700248 struct Locked {
249 SpriteState state;
250 } mLocked; // guarded by mController->mLock
Jeff Brown5541de92011-04-11 11:54:25 -0700251
252 void invalidateLocked(uint32_t dirty);
253 };
254
255 /* Stores temporary information collected during the sprite update cycle. */
256 struct SpriteUpdate {
257 inline SpriteUpdate() : surfaceChanged(false) { }
258 inline SpriteUpdate(const sp<SpriteImpl> sprite, const SpriteState& state) :
259 sprite(sprite), state(state), surfaceChanged(false) {
260 }
261
262 sp<SpriteImpl> sprite;
263 SpriteState state;
264 bool surfaceChanged;
265 };
266
267 mutable Mutex mLock;
268
269 sp<Looper> mLooper;
270 const int32_t mOverlayLayer;
271 sp<WeakMessageHandler> mHandler;
272
273 sp<SurfaceComposerClient> mSurfaceComposerClient;
274
Jeff Brown2352b972011-04-12 22:39:53 -0700275 struct Locked {
276 Vector<sp<SpriteImpl> > invalidatedSprites;
277 Vector<sp<SurfaceControl> > disposedSurfaces;
278 uint32_t transactionNestingCount;
279 bool deferredSpriteUpdate;
280 } mLocked; // guarded by mLock
Jeff Brown5541de92011-04-11 11:54:25 -0700281
282 void invalidateSpriteLocked(const sp<SpriteImpl>& sprite);
283 void disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl);
284
285 void handleMessage(const Message& message);
286 void doUpdateSprites();
287 void doDisposeSurfaces();
288
289 void ensureSurfaceComposerClient();
290 sp<SurfaceControl> obtainSurface(int32_t width, int32_t height);
291};
292
293} // namespace android
294
295#endif // _UI_SPRITES_H