Home | History | Annotate | Download | only in input
      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 {
     33     inline SpriteTransformationMatrix() : dsdx(1.0f), dtdx(0.0f), dsdy(0.0f), dtdy(1.0f) { }
     34     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 {
     58     inline SpriteIcon() : hotSpotX(0), hotSpotY(0) { }
     59     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 
     66     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 
     75     inline void reset() {
     76         bitmap.reset();
     77         hotSpotX = 0;
     78         hotSpotY = 0;
     79     }
     80 
     81     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:
     93     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 
    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 {
    185         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 
    208         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 
    235         inline const SpriteState& getStateLocked() const {
    236             return mLocked.state;
    237         }
    238 
    239         inline void resetDirtyLocked() {
    240             mLocked.state.dirty = 0;
    241         }
    242 
    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 {
    264         inline SpriteUpdate() : surfaceChanged(false) { }
    265         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