1 /* 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 <android/graphics/bitmap.h> 24 #include <gui/SurfaceComposerClient.h> 25 26 namespace android { 27 28 /* 29 * Transformation matrix for a sprite. 30 */ 31 struct SpriteTransformationMatrix { SpriteTransformationMatrixSpriteTransformationMatrix32 inline SpriteTransformationMatrix() : dsdx(1.0f), dtdx(0.0f), dsdy(0.0f), dtdy(1.0f) { } SpriteTransformationMatrixSpriteTransformationMatrix33 inline SpriteTransformationMatrix(float dsdx, float dtdx, float dsdy, float dtdy) : 34 dsdx(dsdx), dtdx(dtdx), dsdy(dsdy), dtdy(dtdy) { } 35 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 /* 54 * Icon that a sprite displays, including its hotspot. 55 */ 56 struct SpriteIcon { SpriteIconSpriteIcon57 inline SpriteIcon() : style(0), hotSpotX(0), hotSpotY(0) { } SpriteIconSpriteIcon58 inline SpriteIcon(const graphics::Bitmap& bitmap, int32_t style, float hotSpotX, float hotSpotY) : 59 bitmap(bitmap), style(style), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { } 60 61 graphics::Bitmap bitmap; 62 int32_t style; 63 float hotSpotX; 64 float hotSpotY; 65 copySpriteIcon66 inline SpriteIcon copy() const { 67 return SpriteIcon(bitmap.copy(ANDROID_BITMAP_FORMAT_RGBA_8888), style, hotSpotX, hotSpotY); 68 } 69 resetSpriteIcon70 inline void reset() { 71 bitmap.reset(); 72 style = 0; 73 hotSpotX = 0; 74 hotSpotY = 0; 75 } 76 isValidSpriteIcon77 inline bool isValid() const { 78 return bitmap.isValid() && !bitmap.isEmpty(); 79 } 80 }; 81 82 /* 83 * 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 */ 87 class Sprite : public RefBase { 88 protected: Sprite()89 Sprite() { } ~Sprite()90 virtual ~Sprite() { } 91 92 public: 93 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 101 /* Sets the bitmap that is drawn by the sprite. 102 * The sprite retains a copy of the bitmap for subsequent rendering. */ 103 virtual void setIcon(const SpriteIcon& icon) = 0; 104 clearIcon()105 inline void clearIcon() { 106 setIcon(SpriteIcon()); 107 } 108 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; 124 125 /* Sets the id of the display where the sprite should be shown. */ 126 virtual void setDisplayId(int32_t displayId) = 0; 127 }; 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 */ 140 class SpriteController : public MessageHandler { 141 protected: 142 virtual ~SpriteController(); 143 144 public: 145 SpriteController(const sp<Looper>& looper, int32_t overlayLayer); 146 147 /* Creates a new sprite, initially invisible. */ 148 virtual sp<Sprite> createSprite(); 149 150 /* 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 virtual void openTransaction(); 156 virtual void closeTransaction(); 157 158 private: 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 DIRTY_DISPLAY_ID = 1 << 7, 173 DIRTY_ICON_STYLE = 1 << 8, 174 }; 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. 180 * Note that the SpriteIcon holds a reference to a shared (and immutable) bitmap. */ 181 struct SpriteState { SpriteStateSpriteState182 inline SpriteState() : 183 dirty(0), visible(false), 184 positionX(0), positionY(0), layer(0), alpha(1.0f), displayId(ADISPLAY_ID_DEFAULT), 185 surfaceWidth(0), surfaceHeight(0), surfaceDrawn(false), surfaceVisible(false) { 186 } 187 188 uint32_t dirty; 189 190 SpriteIcon icon; 191 bool visible; 192 float positionX; 193 float positionY; 194 int32_t layer; 195 float alpha; 196 SpriteTransformationMatrix transformationMatrix; 197 int32_t displayId; 198 199 sp<SurfaceControl> surfaceControl; 200 int32_t surfaceWidth; 201 int32_t surfaceHeight; 202 bool surfaceDrawn; 203 bool surfaceVisible; 204 wantSurfaceVisibleSpriteState205 inline bool wantSurfaceVisible() const { 206 return visible && alpha > 0.0f && icon.isValid(); 207 } 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: 222 explicit SpriteImpl(const sp<SpriteController> controller); 223 224 virtual void setIcon(const SpriteIcon& icon); 225 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); 230 virtual void setDisplayId(int32_t displayId); 231 getStateLocked()232 inline const SpriteState& getStateLocked() const { 233 return mLocked.state; 234 } 235 resetDirtyLocked()236 inline void resetDirtyLocked() { 237 mLocked.state.dirty = 0; 238 } 239 setSurfaceLocked(const sp<SurfaceControl> & surfaceControl,int32_t width,int32_t height,bool drawn,bool visible)240 inline void setSurfaceLocked(const sp<SurfaceControl>& surfaceControl, 241 int32_t width, int32_t height, bool drawn, bool visible) { 242 mLocked.state.surfaceControl = surfaceControl; 243 mLocked.state.surfaceWidth = width; 244 mLocked.state.surfaceHeight = height; 245 mLocked.state.surfaceDrawn = drawn; 246 mLocked.state.surfaceVisible = visible; 247 } 248 249 private: 250 sp<SpriteController> mController; 251 252 struct Locked { 253 SpriteState state; 254 } mLocked; // guarded by mController->mLock 255 256 void invalidateLocked(uint32_t dirty); 257 }; 258 259 /* Stores temporary information collected during the sprite update cycle. */ 260 struct SpriteUpdate { SpriteUpdateSpriteUpdate261 inline SpriteUpdate() : surfaceChanged(false) { } SpriteUpdateSpriteUpdate262 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 279 struct Locked { 280 Vector<sp<SpriteImpl> > invalidatedSprites; 281 Vector<sp<SurfaceControl> > disposedSurfaces; 282 uint32_t transactionNestingCount; 283 bool deferredSpriteUpdate; 284 } mLocked; // guarded by mLock 285 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 300