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 <gui/SurfaceComposerClient.h> 24 25 #include <SkBitmap.h> 26 27 namespace android { 28 29 /* 30 * Transformation matrix for a sprite. 31 */ 32 struct SpriteTransformationMatrix { SpriteTransformationMatrixSpriteTransformationMatrix33 inline SpriteTransformationMatrix() : dsdx(1.0f), dtdx(0.0f), dsdy(0.0f), dtdy(1.0f) { } SpriteTransformationMatrixSpriteTransformationMatrix34 inline SpriteTransformationMatrix(float dsdx, float dtdx, float dsdy, float dtdy) : 35 dsdx(dsdx), dtdx(dtdx), dsdy(dsdy), dtdy(dtdy) { } 36 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 /* 55 * Icon that a sprite displays, including its hotspot. 56 */ 57 struct SpriteIcon { SpriteIconSpriteIcon58 inline SpriteIcon() : hotSpotX(0), hotSpotY(0) { } SpriteIconSpriteIcon59 inline SpriteIcon(const SkBitmap& bitmap, float hotSpotX, float hotSpotY) : 60 bitmap(bitmap), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { } 61 62 SkBitmap bitmap; 63 float hotSpotX; 64 float hotSpotY; 65 copySpriteIcon66 inline SpriteIcon copy() const { 67 SkBitmap bitmapCopy; 68 if (bitmapCopy.tryAllocPixels(bitmap.info().makeColorType(kN32_SkColorType))) { 69 bitmap.readPixels(bitmapCopy.info(), bitmapCopy.getPixels(), bitmapCopy.rowBytes(), 70 0, 0); 71 } 72 return SpriteIcon(bitmapCopy, hotSpotX, hotSpotY); 73 } 74 resetSpriteIcon75 inline void reset() { 76 bitmap.reset(); 77 hotSpotX = 0; 78 hotSpotY = 0; 79 } 80 isValidSpriteIcon81 inline bool isValid() const { 82 return !bitmap.isNull() && !bitmap.empty(); 83 } 84 }; 85 86 /* 87 * A sprite is a simple graphical object that is displayed on-screen above other layers. 88 * The basic sprite class is an interface. 89 * The implementation is provided by the sprite controller. 90 */ 91 class Sprite : public RefBase { 92 protected: Sprite()93 Sprite() { } ~Sprite()94 virtual ~Sprite() { } 95 96 public: 97 enum { 98 // The base layer for pointer sprites. 99 BASE_LAYER_POINTER = 0, // reserve space for 1 pointer 100 101 // The base layer for spot sprites. 102 BASE_LAYER_SPOT = 1, // reserve space for MAX_POINTER_ID spots 103 }; 104 105 /* Sets the bitmap that is drawn by the sprite. 106 * The sprite retains a copy of the bitmap for subsequent rendering. */ 107 virtual void setIcon(const SpriteIcon& icon) = 0; 108 clearIcon()109 inline void clearIcon() { 110 setIcon(SpriteIcon()); 111 } 112 113 /* Sets whether the sprite is visible. */ 114 virtual void setVisible(bool visible) = 0; 115 116 /* Sets the sprite position on screen, relative to the sprite's hot spot. */ 117 virtual void setPosition(float x, float y) = 0; 118 119 /* Sets the layer of the sprite, relative to the system sprite overlay layer. 120 * Layer 0 is the overlay layer, > 0 appear above this layer. */ 121 virtual void setLayer(int32_t layer) = 0; 122 123 /* Sets the sprite alpha blend ratio between 0.0 and 1.0. */ 124 virtual void setAlpha(float alpha) = 0; 125 126 /* Sets the sprite transformation matrix. */ 127 virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix) = 0; 128 129 /* Sets the id of the display where the sprite should be shown. */ 130 virtual void setDisplayId(int32_t displayId) = 0; 131 }; 132 133 /* 134 * Displays sprites on the screen. 135 * 136 * This interface is used by PointerController and SpotController to draw pointers or 137 * spot representations of fingers. It is not intended for general purpose use 138 * by other components. 139 * 140 * All sprite position updates and rendering is performed asynchronously. 141 * 142 * Clients are responsible for animating sprites by periodically updating their properties. 143 */ 144 class SpriteController : public MessageHandler { 145 protected: 146 virtual ~SpriteController(); 147 148 public: 149 SpriteController(const sp<Looper>& looper, int32_t overlayLayer); 150 151 /* Creates a new sprite, initially invisible. */ 152 sp<Sprite> createSprite(); 153 154 /* Opens or closes a transaction to perform a batch of sprite updates as part of 155 * a single operation such as setPosition and setAlpha. It is not necessary to 156 * open a transaction when updating a single property. 157 * Calls to openTransaction() nest and must be matched by an equal number 158 * of calls to closeTransaction(). */ 159 void openTransaction(); 160 void closeTransaction(); 161 162 private: 163 enum { 164 MSG_UPDATE_SPRITES, 165 MSG_DISPOSE_SURFACES, 166 }; 167 168 enum { 169 DIRTY_BITMAP = 1 << 0, 170 DIRTY_ALPHA = 1 << 1, 171 DIRTY_POSITION = 1 << 2, 172 DIRTY_TRANSFORMATION_MATRIX = 1 << 3, 173 DIRTY_LAYER = 1 << 4, 174 DIRTY_VISIBILITY = 1 << 5, 175 DIRTY_HOTSPOT = 1 << 6, 176 DIRTY_DISPLAY_ID = 1 << 7, 177 }; 178 179 /* Describes the state of a sprite. 180 * This structure is designed so that it can be copied during updates so that 181 * surfaces can be resized and redrawn without blocking the client by holding a lock 182 * on the sprites for a long time. 183 * Note that the SkBitmap holds a reference to a shared (and immutable) pixel ref. */ 184 struct SpriteState { SpriteStateSpriteState185 inline SpriteState() : 186 dirty(0), visible(false), 187 positionX(0), positionY(0), layer(0), alpha(1.0f), displayId(ADISPLAY_ID_DEFAULT), 188 surfaceWidth(0), surfaceHeight(0), surfaceDrawn(false), surfaceVisible(false) { 189 } 190 191 uint32_t dirty; 192 193 SpriteIcon icon; 194 bool visible; 195 float positionX; 196 float positionY; 197 int32_t layer; 198 float alpha; 199 SpriteTransformationMatrix transformationMatrix; 200 int32_t displayId; 201 202 sp<SurfaceControl> surfaceControl; 203 int32_t surfaceWidth; 204 int32_t surfaceHeight; 205 bool surfaceDrawn; 206 bool surfaceVisible; 207 wantSurfaceVisibleSpriteState208 inline bool wantSurfaceVisible() const { 209 return visible && alpha > 0.0f && icon.isValid(); 210 } 211 }; 212 213 /* Client interface for a sprite. 214 * Requests acquire a lock on the controller, update local state and request the 215 * controller to invalidate the sprite. 216 * The real heavy lifting of creating, resizing and redrawing surfaces happens 217 * asynchronously with no locks held except in short critical section to copy 218 * the sprite state before the work and update the sprite surface control afterwards. 219 */ 220 class SpriteImpl : public Sprite { 221 protected: 222 virtual ~SpriteImpl(); 223 224 public: 225 explicit SpriteImpl(const sp<SpriteController> controller); 226 227 virtual void setIcon(const SpriteIcon& icon); 228 virtual void setVisible(bool visible); 229 virtual void setPosition(float x, float y); 230 virtual void setLayer(int32_t layer); 231 virtual void setAlpha(float alpha); 232 virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix); 233 virtual void setDisplayId(int32_t displayId); 234 getStateLocked()235 inline const SpriteState& getStateLocked() const { 236 return mLocked.state; 237 } 238 resetDirtyLocked()239 inline void resetDirtyLocked() { 240 mLocked.state.dirty = 0; 241 } 242 setSurfaceLocked(const sp<SurfaceControl> & surfaceControl,int32_t width,int32_t height,bool drawn,bool visible)243 inline void setSurfaceLocked(const sp<SurfaceControl>& surfaceControl, 244 int32_t width, int32_t height, bool drawn, bool visible) { 245 mLocked.state.surfaceControl = surfaceControl; 246 mLocked.state.surfaceWidth = width; 247 mLocked.state.surfaceHeight = height; 248 mLocked.state.surfaceDrawn = drawn; 249 mLocked.state.surfaceVisible = visible; 250 } 251 252 private: 253 sp<SpriteController> mController; 254 255 struct Locked { 256 SpriteState state; 257 } mLocked; // guarded by mController->mLock 258 259 void invalidateLocked(uint32_t dirty); 260 }; 261 262 /* Stores temporary information collected during the sprite update cycle. */ 263 struct SpriteUpdate { SpriteUpdateSpriteUpdate264 inline SpriteUpdate() : surfaceChanged(false) { } SpriteUpdateSpriteUpdate265 inline SpriteUpdate(const sp<SpriteImpl> sprite, const SpriteState& state) : 266 sprite(sprite), state(state), surfaceChanged(false) { 267 } 268 269 sp<SpriteImpl> sprite; 270 SpriteState state; 271 bool surfaceChanged; 272 }; 273 274 mutable Mutex mLock; 275 276 sp<Looper> mLooper; 277 const int32_t mOverlayLayer; 278 sp<WeakMessageHandler> mHandler; 279 280 sp<SurfaceComposerClient> mSurfaceComposerClient; 281 282 struct Locked { 283 Vector<sp<SpriteImpl> > invalidatedSprites; 284 Vector<sp<SurfaceControl> > disposedSurfaces; 285 uint32_t transactionNestingCount; 286 bool deferredSpriteUpdate; 287 } mLocked; // guarded by mLock 288 289 void invalidateSpriteLocked(const sp<SpriteImpl>& sprite); 290 void disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl); 291 292 void handleMessage(const Message& message); 293 void doUpdateSprites(); 294 void doDisposeSurfaces(); 295 296 void ensureSurfaceComposerClient(); 297 sp<SurfaceControl> obtainSurface(int32_t width, int32_t height); 298 }; 299 300 } // namespace android 301 302 #endif // _UI_SPRITES_H 303