summaryrefslogtreecommitdiffstats
path: root/widget/gonk/libui/SpriteController.h
diff options
context:
space:
mode:
Diffstat (limited to 'widget/gonk/libui/SpriteController.h')
-rw-r--r--widget/gonk/libui/SpriteController.h319
1 files changed, 319 insertions, 0 deletions
diff --git a/widget/gonk/libui/SpriteController.h b/widget/gonk/libui/SpriteController.h
new file mode 100644
index 000000000..4926095ec
--- /dev/null
+++ b/widget/gonk/libui/SpriteController.h
@@ -0,0 +1,319 @@
+/*
+ * 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>
+
+#ifdef HAVE_ANDROID_OS
+#include <gui/SurfaceComposerClient.h>
+#endif
+
+#include <SkBitmap.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);
+ }
+};
+
+/*
+ * Icon that a sprite displays, including its hotspot.
+ */
+struct SpriteIcon {
+ inline SpriteIcon() : hotSpotX(0), hotSpotY(0) { }
+#ifdef HAVE_ANDROID_OS
+ inline SpriteIcon(const SkBitmap& bitmap, float hotSpotX, float hotSpotY) :
+ bitmap(bitmap), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { }
+
+ SkBitmap bitmap;
+#endif
+ float hotSpotX;
+ float hotSpotY;
+
+ inline SpriteIcon copy() const {
+#ifdef HAVE_ANDROID_OS
+ SkBitmap bitmapCopy;
+ bitmap.copyTo(&bitmapCopy, SkBitmap::kARGB_8888_Config);
+ return SpriteIcon(bitmapCopy, hotSpotX, hotSpotY);
+#else
+ return SpriteIcon();
+#endif
+ }
+
+ inline void reset() {
+#ifdef HAVE_ANDROID_OS
+ bitmap.reset();
+ hotSpotX = 0;
+ hotSpotY = 0;
+#endif
+ }
+
+ inline bool isValid() const {
+#ifdef HAVE_ANDROID_OS
+ return !bitmap.isNull() && !bitmap.empty();
+#else
+ return false;
+#endif
+ }
+};
+
+/*
+ * 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;
+};
+
+/*
+ * 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 MessageHandler {
+protected:
+ virtual ~SpriteController();
+
+public:
+ SpriteController(const sp<Looper>& looper, int32_t overlayLayer);
+
+ /* Creates a new sprite, initially invisible. */
+ 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(). */
+ void openTransaction();
+ void closeTransaction();
+
+private:
+ enum {
+ MSG_UPDATE_SPRITES,
+ MSG_DISPOSE_SURFACES,
+ };
+
+ 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,
+ };
+
+ /* 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 SkBitmap holds a reference to a shared (and immutable) pixel ref. */
+ struct SpriteState {
+ inline SpriteState() :
+ dirty(0), visible(false),
+ positionX(0), positionY(0), layer(0), alpha(1.0f),
+ 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;
+
+#ifdef HAVE_ANDROID_OS
+ sp<SurfaceControl> surfaceControl;
+#endif
+ 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:
+ SpriteImpl(const sp<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);
+
+ inline const SpriteState& getStateLocked() const {
+ return mLocked.state;
+ }
+
+ inline void resetDirtyLocked() {
+ mLocked.state.dirty = 0;
+ }
+
+#ifdef HAVE_ANDROID_OS
+ 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;
+ }
+#endif
+
+ private:
+ sp<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;
+#ifdef HAVE_ANDROID_OS
+ sp<WeakMessageHandler> mHandler;
+
+ sp<SurfaceComposerClient> mSurfaceComposerClient;
+#endif
+
+ struct Locked {
+ Vector<sp<SpriteImpl> > invalidatedSprites;
+#ifdef HAVE_ANDROID_OS
+ Vector<sp<SurfaceControl> > disposedSurfaces;
+#endif
+ uint32_t transactionNestingCount;
+ bool deferredSpriteUpdate;
+ } mLocked; // guarded by mLock
+
+ void invalidateSpriteLocked(const sp<SpriteImpl>& sprite);
+#ifdef HAVE_ANDROID_OS
+ void disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl);
+
+ void handleMessage(const Message& message);
+#endif
+ void doUpdateSprites();
+ void doDisposeSurfaces();
+
+ void ensureSurfaceComposerClient();
+#ifdef HAVE_ANDROID_OS
+ sp<SurfaceControl> obtainSurface(int32_t width, int32_t height);
+#endif
+};
+
+} // namespace android
+
+#endif // _UI_SPRITES_H