widget/gonk/libui/SpriteController.h

changeset 0
6474c204b198
     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

mercurial