| /* | 
 |  * Copyright (C) 2011 The Android Open Source Project | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 |  | 
 | #ifndef _UI_SPRITES_H | 
 | #define _UI_SPRITES_H | 
 |  | 
 | #include <utils/RefBase.h> | 
 | #include <utils/Looper.h> | 
 |  | 
 | #include <gui/SurfaceComposerClient.h> | 
 |  | 
 | #include "SpriteIcon.h" | 
 |  | 
 | namespace android { | 
 |  | 
 | /* | 
 |  * Transformation matrix for a sprite. | 
 |  */ | 
 | struct SpriteTransformationMatrix { | 
 |     inline SpriteTransformationMatrix() : dsdx(1.0f), dtdx(0.0f), dsdy(0.0f), dtdy(1.0f) { } | 
 |     inline SpriteTransformationMatrix(float dsdx, float dtdx, float dsdy, float dtdy) : | 
 |             dsdx(dsdx), dtdx(dtdx), dsdy(dsdy), dtdy(dtdy) { } | 
 |  | 
 |     float dsdx; | 
 |     float dtdx; | 
 |     float dsdy; | 
 |     float dtdy; | 
 |  | 
 |     inline bool operator== (const SpriteTransformationMatrix& other) { | 
 |         return dsdx == other.dsdx | 
 |                 && dtdx == other.dtdx | 
 |                 && dsdy == other.dsdy | 
 |                 && dtdy == other.dtdy; | 
 |     } | 
 |  | 
 |     inline bool operator!= (const SpriteTransformationMatrix& other) { | 
 |         return !(*this == other); | 
 |     } | 
 | }; | 
 |  | 
 | /* | 
 |  * A sprite is a simple graphical object that is displayed on-screen above other layers. | 
 |  * The basic sprite class is an interface. | 
 |  * The implementation is provided by the sprite controller. | 
 |  */ | 
 | class Sprite : public RefBase { | 
 | protected: | 
 |     Sprite() { } | 
 |     virtual ~Sprite() { } | 
 |  | 
 | public: | 
 |     enum { | 
 |         // The base layer for pointer sprites. | 
 |         BASE_LAYER_POINTER = 0, // reserve space for 1 pointer | 
 |  | 
 |         // The base layer for spot sprites. | 
 |         BASE_LAYER_SPOT = 1, // reserve space for MAX_POINTER_ID spots | 
 |     }; | 
 |  | 
 |     /* Sets the bitmap that is drawn by the sprite. | 
 |      * The sprite retains a copy of the bitmap for subsequent rendering. */ | 
 |     virtual void setIcon(const SpriteIcon& icon) = 0; | 
 |  | 
 |     inline void clearIcon() { | 
 |         setIcon(SpriteIcon()); | 
 |     } | 
 |  | 
 |     /* Sets whether the sprite is visible. */ | 
 |     virtual void setVisible(bool visible) = 0; | 
 |  | 
 |     /* Sets the sprite position on screen, relative to the sprite's hot spot. */ | 
 |     virtual void setPosition(float x, float y) = 0; | 
 |  | 
 |     /* Sets the layer of the sprite, relative to the system sprite overlay layer. | 
 |      * Layer 0 is the overlay layer, > 0 appear above this layer. */ | 
 |     virtual void setLayer(int32_t layer) = 0; | 
 |  | 
 |     /* Sets the sprite alpha blend ratio between 0.0 and 1.0. */ | 
 |     virtual void setAlpha(float alpha) = 0; | 
 |  | 
 |     /* Sets the sprite transformation matrix. */ | 
 |     virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix) = 0; | 
 |  | 
 |     /* Sets the id of the display where the sprite should be shown. */ | 
 |     virtual void setDisplayId(int32_t displayId) = 0; | 
 | }; | 
 |  | 
 | /* | 
 |  * Displays sprites on the screen. | 
 |  * | 
 |  * This interface is used by PointerController and SpotController to draw pointers or | 
 |  * spot representations of fingers.  It is not intended for general purpose use | 
 |  * by other components. | 
 |  * | 
 |  * All sprite position updates and rendering is performed asynchronously. | 
 |  * | 
 |  * Clients are responsible for animating sprites by periodically updating their properties. | 
 |  */ | 
 | class SpriteController { | 
 | public: | 
 |     using ParentSurfaceProvider = std::function<sp<SurfaceControl>(int /*displayId*/)>; | 
 |     SpriteController(const sp<Looper>& looper, int32_t overlayLayer, ParentSurfaceProvider parent); | 
 |     SpriteController(const SpriteController&) = delete; | 
 |     SpriteController& operator=(const SpriteController&) = delete; | 
 |     virtual ~SpriteController(); | 
 |  | 
 |     /* Initialize the callback for the message handler. */ | 
 |     void setHandlerController(const std::shared_ptr<SpriteController>& controller); | 
 |  | 
 |     /* Creates a new sprite, initially invisible. The lifecycle of the sprite must not extend beyond | 
 |      * the lifecycle of this SpriteController. */ | 
 |     virtual sp<Sprite> createSprite(); | 
 |  | 
 |     /* Opens or closes a transaction to perform a batch of sprite updates as part of | 
 |      * a single operation such as setPosition and setAlpha.  It is not necessary to | 
 |      * open a transaction when updating a single property. | 
 |      * Calls to openTransaction() nest and must be matched by an equal number | 
 |      * of calls to closeTransaction(). */ | 
 |     virtual void openTransaction(); | 
 |     virtual void closeTransaction(); | 
 |  | 
 | private: | 
 |     class Handler : public virtual android::MessageHandler { | 
 |     public: | 
 |         enum { MSG_UPDATE_SPRITES, MSG_DISPOSE_SURFACES }; | 
 |  | 
 |         void handleMessage(const Message& message) override; | 
 |         std::weak_ptr<SpriteController> spriteController; | 
 |     }; | 
 |  | 
 |     enum { | 
 |         DIRTY_BITMAP = 1 << 0, | 
 |         DIRTY_ALPHA = 1 << 1, | 
 |         DIRTY_POSITION = 1 << 2, | 
 |         DIRTY_TRANSFORMATION_MATRIX = 1 << 3, | 
 |         DIRTY_LAYER = 1 << 4, | 
 |         DIRTY_VISIBILITY = 1 << 5, | 
 |         DIRTY_HOTSPOT = 1 << 6, | 
 |         DIRTY_DISPLAY_ID = 1 << 7, | 
 |         DIRTY_ICON_STYLE = 1 << 8, | 
 |     }; | 
 |  | 
 |     /* Describes the state of a sprite. | 
 |      * This structure is designed so that it can be copied during updates so that | 
 |      * surfaces can be resized and redrawn without blocking the client by holding a lock | 
 |      * on the sprites for a long time. | 
 |      * Note that the SpriteIcon holds a reference to a shared (and immutable) bitmap. */ | 
 |     struct SpriteState { | 
 |         inline SpriteState() : | 
 |                 dirty(0), visible(false), | 
 |                 positionX(0), positionY(0), layer(0), alpha(1.0f), displayId(ADISPLAY_ID_DEFAULT), | 
 |                 surfaceWidth(0), surfaceHeight(0), surfaceDrawn(false), surfaceVisible(false) { | 
 |         } | 
 |  | 
 |         uint32_t dirty; | 
 |  | 
 |         SpriteIcon icon; | 
 |         bool visible; | 
 |         float positionX; | 
 |         float positionY; | 
 |         int32_t layer; | 
 |         float alpha; | 
 |         SpriteTransformationMatrix transformationMatrix; | 
 |         int32_t displayId; | 
 |  | 
 |         sp<SurfaceControl> surfaceControl; | 
 |         int32_t surfaceWidth; | 
 |         int32_t surfaceHeight; | 
 |         bool surfaceDrawn; | 
 |         bool surfaceVisible; | 
 |  | 
 |         inline bool wantSurfaceVisible() const { | 
 |             return visible && alpha > 0.0f && icon.isValid(); | 
 |         } | 
 |     }; | 
 |  | 
 |     /* Client interface for a sprite. | 
 |      * Requests acquire a lock on the controller, update local state and request the | 
 |      * controller to invalidate the sprite. | 
 |      * The real heavy lifting of creating, resizing and redrawing surfaces happens | 
 |      * asynchronously with no locks held except in short critical section to copy | 
 |      * the sprite state before the work and update the sprite surface control afterwards. | 
 |      */ | 
 |     class SpriteImpl : public Sprite { | 
 |     protected: | 
 |         virtual ~SpriteImpl(); | 
 |  | 
 |     public: | 
 |         explicit SpriteImpl(SpriteController& controller); | 
 |  | 
 |         virtual void setIcon(const SpriteIcon& icon); | 
 |         virtual void setVisible(bool visible); | 
 |         virtual void setPosition(float x, float y); | 
 |         virtual void setLayer(int32_t layer); | 
 |         virtual void setAlpha(float alpha); | 
 |         virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix); | 
 |         virtual void setDisplayId(int32_t displayId); | 
 |  | 
 |         inline const SpriteState& getStateLocked() const { | 
 |             return mLocked.state; | 
 |         } | 
 |  | 
 |         inline void resetDirtyLocked() { | 
 |             mLocked.state.dirty = 0; | 
 |         } | 
 |  | 
 |         inline void setSurfaceLocked(const sp<SurfaceControl>& surfaceControl, | 
 |                 int32_t width, int32_t height, bool drawn, bool visible) { | 
 |             mLocked.state.surfaceControl = surfaceControl; | 
 |             mLocked.state.surfaceWidth = width; | 
 |             mLocked.state.surfaceHeight = height; | 
 |             mLocked.state.surfaceDrawn = drawn; | 
 |             mLocked.state.surfaceVisible = visible; | 
 |         } | 
 |  | 
 |     private: | 
 |         SpriteController& mController; | 
 |  | 
 |         struct Locked { | 
 |             SpriteState state; | 
 |         } mLocked; // guarded by mController->mLock | 
 |  | 
 |         void invalidateLocked(uint32_t dirty); | 
 |     }; | 
 |  | 
 |     /* Stores temporary information collected during the sprite update cycle. */ | 
 |     struct SpriteUpdate { | 
 |         inline SpriteUpdate() : surfaceChanged(false) { } | 
 |         inline SpriteUpdate(const sp<SpriteImpl> sprite, const SpriteState& state) : | 
 |                 sprite(sprite), state(state), surfaceChanged(false) { | 
 |         } | 
 |  | 
 |         sp<SpriteImpl> sprite; | 
 |         SpriteState state; | 
 |         bool surfaceChanged; | 
 |     }; | 
 |  | 
 |     mutable Mutex mLock; | 
 |  | 
 |     sp<Looper> mLooper; | 
 |     const int32_t mOverlayLayer; | 
 |     sp<Handler> mHandler; | 
 |     ParentSurfaceProvider mParentSurfaceProvider; | 
 |  | 
 |     sp<SurfaceComposerClient> mSurfaceComposerClient; | 
 |  | 
 |     struct Locked { | 
 |         std::vector<sp<SpriteImpl>> invalidatedSprites; | 
 |         std::vector<sp<SurfaceControl>> disposedSurfaces; | 
 |         uint32_t transactionNestingCount; | 
 |         bool deferredSpriteUpdate; | 
 |     } mLocked; // guarded by mLock | 
 |  | 
 |     void invalidateSpriteLocked(const sp<SpriteImpl>& sprite); | 
 |     void disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl); | 
 |  | 
 |     void doUpdateSprites(); | 
 |     void doDisposeSurfaces(); | 
 |  | 
 |     void ensureSurfaceComposerClient(); | 
 |     sp<SurfaceControl> obtainSurface(int32_t width, int32_t height, int32_t displayId); | 
 | }; | 
 |  | 
 | } // namespace android | 
 |  | 
 | #endif // _UI_SPRITES_H |