1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/gonk/libui/SpriteController.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,319 @@ 1.4 +/* 1.5 + * Copyright (C) 2011 The Android Open Source Project 1.6 + * 1.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.8 + * you may not use this file except in compliance with the License. 1.9 + * You may obtain a copy of the License at 1.10 + * 1.11 + * http://www.apache.org/licenses/LICENSE-2.0 1.12 + * 1.13 + * Unless required by applicable law or agreed to in writing, software 1.14 + * distributed under the License is distributed on an "AS IS" BASIS, 1.15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.16 + * See the License for the specific language governing permissions and 1.17 + * limitations under the License. 1.18 + */ 1.19 + 1.20 +#ifndef _UI_SPRITES_H 1.21 +#define _UI_SPRITES_H 1.22 + 1.23 +#include <utils/RefBase.h> 1.24 +#include <utils/Looper.h> 1.25 + 1.26 +#ifdef HAVE_ANDROID_OS 1.27 +#include <gui/SurfaceComposerClient.h> 1.28 +#endif 1.29 + 1.30 +#include <SkBitmap.h> 1.31 + 1.32 +namespace android { 1.33 + 1.34 +/* 1.35 + * Transformation matrix for a sprite. 1.36 + */ 1.37 +struct SpriteTransformationMatrix { 1.38 + inline SpriteTransformationMatrix() : dsdx(1.0f), dtdx(0.0f), dsdy(0.0f), dtdy(1.0f) { } 1.39 + inline SpriteTransformationMatrix(float dsdx, float dtdx, float dsdy, float dtdy) : 1.40 + dsdx(dsdx), dtdx(dtdx), dsdy(dsdy), dtdy(dtdy) { } 1.41 + 1.42 + float dsdx; 1.43 + float dtdx; 1.44 + float dsdy; 1.45 + float dtdy; 1.46 + 1.47 + inline bool operator== (const SpriteTransformationMatrix& other) { 1.48 + return dsdx == other.dsdx 1.49 + && dtdx == other.dtdx 1.50 + && dsdy == other.dsdy 1.51 + && dtdy == other.dtdy; 1.52 + } 1.53 + 1.54 + inline bool operator!= (const SpriteTransformationMatrix& other) { 1.55 + return !(*this == other); 1.56 + } 1.57 +}; 1.58 + 1.59 +/* 1.60 + * Icon that a sprite displays, including its hotspot. 1.61 + */ 1.62 +struct SpriteIcon { 1.63 + inline SpriteIcon() : hotSpotX(0), hotSpotY(0) { } 1.64 +#ifdef HAVE_ANDROID_OS 1.65 + inline SpriteIcon(const SkBitmap& bitmap, float hotSpotX, float hotSpotY) : 1.66 + bitmap(bitmap), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { } 1.67 + 1.68 + SkBitmap bitmap; 1.69 +#endif 1.70 + float hotSpotX; 1.71 + float hotSpotY; 1.72 + 1.73 + inline SpriteIcon copy() const { 1.74 +#ifdef HAVE_ANDROID_OS 1.75 + SkBitmap bitmapCopy; 1.76 + bitmap.copyTo(&bitmapCopy, SkBitmap::kARGB_8888_Config); 1.77 + return SpriteIcon(bitmapCopy, hotSpotX, hotSpotY); 1.78 +#else 1.79 + return SpriteIcon(); 1.80 +#endif 1.81 + } 1.82 + 1.83 + inline void reset() { 1.84 +#ifdef HAVE_ANDROID_OS 1.85 + bitmap.reset(); 1.86 + hotSpotX = 0; 1.87 + hotSpotY = 0; 1.88 +#endif 1.89 + } 1.90 + 1.91 + inline bool isValid() const { 1.92 +#ifdef HAVE_ANDROID_OS 1.93 + return !bitmap.isNull() && !bitmap.empty(); 1.94 +#else 1.95 + return false; 1.96 +#endif 1.97 + } 1.98 +}; 1.99 + 1.100 +/* 1.101 + * A sprite is a simple graphical object that is displayed on-screen above other layers. 1.102 + * The basic sprite class is an interface. 1.103 + * The implementation is provided by the sprite controller. 1.104 + */ 1.105 +class Sprite : public RefBase { 1.106 +protected: 1.107 + Sprite() { } 1.108 + virtual ~Sprite() { } 1.109 + 1.110 +public: 1.111 + enum { 1.112 + // The base layer for pointer sprites. 1.113 + BASE_LAYER_POINTER = 0, // reserve space for 1 pointer 1.114 + 1.115 + // The base layer for spot sprites. 1.116 + BASE_LAYER_SPOT = 1, // reserve space for MAX_POINTER_ID spots 1.117 + }; 1.118 + 1.119 + /* Sets the bitmap that is drawn by the sprite. 1.120 + * The sprite retains a copy of the bitmap for subsequent rendering. */ 1.121 + virtual void setIcon(const SpriteIcon& icon) = 0; 1.122 + 1.123 + inline void clearIcon() { 1.124 + setIcon(SpriteIcon()); 1.125 + } 1.126 + 1.127 + /* Sets whether the sprite is visible. */ 1.128 + virtual void setVisible(bool visible) = 0; 1.129 + 1.130 + /* Sets the sprite position on screen, relative to the sprite's hot spot. */ 1.131 + virtual void setPosition(float x, float y) = 0; 1.132 + 1.133 + /* Sets the layer of the sprite, relative to the system sprite overlay layer. 1.134 + * Layer 0 is the overlay layer, > 0 appear above this layer. */ 1.135 + virtual void setLayer(int32_t layer) = 0; 1.136 + 1.137 + /* Sets the sprite alpha blend ratio between 0.0 and 1.0. */ 1.138 + virtual void setAlpha(float alpha) = 0; 1.139 + 1.140 + /* Sets the sprite transformation matrix. */ 1.141 + virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix) = 0; 1.142 +}; 1.143 + 1.144 +/* 1.145 + * Displays sprites on the screen. 1.146 + * 1.147 + * This interface is used by PointerController and SpotController to draw pointers or 1.148 + * spot representations of fingers. It is not intended for general purpose use 1.149 + * by other components. 1.150 + * 1.151 + * All sprite position updates and rendering is performed asynchronously. 1.152 + * 1.153 + * Clients are responsible for animating sprites by periodically updating their properties. 1.154 + */ 1.155 +class SpriteController : public MessageHandler { 1.156 +protected: 1.157 + virtual ~SpriteController(); 1.158 + 1.159 +public: 1.160 + SpriteController(const sp<Looper>& looper, int32_t overlayLayer); 1.161 + 1.162 + /* Creates a new sprite, initially invisible. */ 1.163 + sp<Sprite> createSprite(); 1.164 + 1.165 + /* Opens or closes a transaction to perform a batch of sprite updates as part of 1.166 + * a single operation such as setPosition and setAlpha. It is not necessary to 1.167 + * open a transaction when updating a single property. 1.168 + * Calls to openTransaction() nest and must be matched by an equal number 1.169 + * of calls to closeTransaction(). */ 1.170 + void openTransaction(); 1.171 + void closeTransaction(); 1.172 + 1.173 +private: 1.174 + enum { 1.175 + MSG_UPDATE_SPRITES, 1.176 + MSG_DISPOSE_SURFACES, 1.177 + }; 1.178 + 1.179 + enum { 1.180 + DIRTY_BITMAP = 1 << 0, 1.181 + DIRTY_ALPHA = 1 << 1, 1.182 + DIRTY_POSITION = 1 << 2, 1.183 + DIRTY_TRANSFORMATION_MATRIX = 1 << 3, 1.184 + DIRTY_LAYER = 1 << 4, 1.185 + DIRTY_VISIBILITY = 1 << 5, 1.186 + DIRTY_HOTSPOT = 1 << 6, 1.187 + }; 1.188 + 1.189 + /* Describes the state of a sprite. 1.190 + * This structure is designed so that it can be copied during updates so that 1.191 + * surfaces can be resized and redrawn without blocking the client by holding a lock 1.192 + * on the sprites for a long time. 1.193 + * Note that the SkBitmap holds a reference to a shared (and immutable) pixel ref. */ 1.194 + struct SpriteState { 1.195 + inline SpriteState() : 1.196 + dirty(0), visible(false), 1.197 + positionX(0), positionY(0), layer(0), alpha(1.0f), 1.198 + surfaceWidth(0), surfaceHeight(0), surfaceDrawn(false), surfaceVisible(false) { 1.199 + } 1.200 + 1.201 + uint32_t dirty; 1.202 + 1.203 + SpriteIcon icon; 1.204 + bool visible; 1.205 + float positionX; 1.206 + float positionY; 1.207 + int32_t layer; 1.208 + float alpha; 1.209 + SpriteTransformationMatrix transformationMatrix; 1.210 + 1.211 +#ifdef HAVE_ANDROID_OS 1.212 + sp<SurfaceControl> surfaceControl; 1.213 +#endif 1.214 + int32_t surfaceWidth; 1.215 + int32_t surfaceHeight; 1.216 + bool surfaceDrawn; 1.217 + bool surfaceVisible; 1.218 + 1.219 + inline bool wantSurfaceVisible() const { 1.220 + return visible && alpha > 0.0f && icon.isValid(); 1.221 + } 1.222 + }; 1.223 + 1.224 + /* Client interface for a sprite. 1.225 + * Requests acquire a lock on the controller, update local state and request the 1.226 + * controller to invalidate the sprite. 1.227 + * The real heavy lifting of creating, resizing and redrawing surfaces happens 1.228 + * asynchronously with no locks held except in short critical section to copy 1.229 + * the sprite state before the work and update the sprite surface control afterwards. 1.230 + */ 1.231 + class SpriteImpl : public Sprite { 1.232 + protected: 1.233 + virtual ~SpriteImpl(); 1.234 + 1.235 + public: 1.236 + SpriteImpl(const sp<SpriteController> controller); 1.237 + 1.238 + virtual void setIcon(const SpriteIcon& icon); 1.239 + virtual void setVisible(bool visible); 1.240 + virtual void setPosition(float x, float y); 1.241 + virtual void setLayer(int32_t layer); 1.242 + virtual void setAlpha(float alpha); 1.243 + virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix); 1.244 + 1.245 + inline const SpriteState& getStateLocked() const { 1.246 + return mLocked.state; 1.247 + } 1.248 + 1.249 + inline void resetDirtyLocked() { 1.250 + mLocked.state.dirty = 0; 1.251 + } 1.252 + 1.253 +#ifdef HAVE_ANDROID_OS 1.254 + inline void setSurfaceLocked(const sp<SurfaceControl>& surfaceControl, 1.255 + int32_t width, int32_t height, bool drawn, bool visible) { 1.256 + mLocked.state.surfaceControl = surfaceControl; 1.257 + mLocked.state.surfaceWidth = width; 1.258 + mLocked.state.surfaceHeight = height; 1.259 + mLocked.state.surfaceDrawn = drawn; 1.260 + mLocked.state.surfaceVisible = visible; 1.261 + } 1.262 +#endif 1.263 + 1.264 + private: 1.265 + sp<SpriteController> mController; 1.266 + 1.267 + struct Locked { 1.268 + SpriteState state; 1.269 + } mLocked; // guarded by mController->mLock 1.270 + 1.271 + void invalidateLocked(uint32_t dirty); 1.272 + }; 1.273 + 1.274 + /* Stores temporary information collected during the sprite update cycle. */ 1.275 + struct SpriteUpdate { 1.276 + inline SpriteUpdate() : surfaceChanged(false) { } 1.277 + inline SpriteUpdate(const sp<SpriteImpl> sprite, const SpriteState& state) : 1.278 + sprite(sprite), state(state), surfaceChanged(false) { 1.279 + } 1.280 + 1.281 + sp<SpriteImpl> sprite; 1.282 + SpriteState state; 1.283 + bool surfaceChanged; 1.284 + }; 1.285 + 1.286 + mutable Mutex mLock; 1.287 + 1.288 + sp<Looper> mLooper; 1.289 + const int32_t mOverlayLayer; 1.290 +#ifdef HAVE_ANDROID_OS 1.291 + sp<WeakMessageHandler> mHandler; 1.292 + 1.293 + sp<SurfaceComposerClient> mSurfaceComposerClient; 1.294 +#endif 1.295 + 1.296 + struct Locked { 1.297 + Vector<sp<SpriteImpl> > invalidatedSprites; 1.298 +#ifdef HAVE_ANDROID_OS 1.299 + Vector<sp<SurfaceControl> > disposedSurfaces; 1.300 +#endif 1.301 + uint32_t transactionNestingCount; 1.302 + bool deferredSpriteUpdate; 1.303 + } mLocked; // guarded by mLock 1.304 + 1.305 + void invalidateSpriteLocked(const sp<SpriteImpl>& sprite); 1.306 +#ifdef HAVE_ANDROID_OS 1.307 + void disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl); 1.308 + 1.309 + void handleMessage(const Message& message); 1.310 +#endif 1.311 + void doUpdateSprites(); 1.312 + void doDisposeSurfaces(); 1.313 + 1.314 + void ensureSurfaceComposerClient(); 1.315 +#ifdef HAVE_ANDROID_OS 1.316 + sp<SurfaceControl> obtainSurface(int32_t width, int32_t height); 1.317 +#endif 1.318 +}; 1.319 + 1.320 +} // namespace android 1.321 + 1.322 +#endif // _UI_SPRITES_H