/*
* Copyright (C) 2007 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 ANDROID_SURFACE_FLINGER_H
#define ANDROID_SURFACE_FLINGER_H
#include <stdint.h>
#include <sys/types.h>
#include <utils/SortedVector.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
#include <utils/Atomic.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <binder/IMemory.h>
#include <binder/Permission.h>
#include <ui/PixelFormat.h>
#include <ui/ISurfaceComposer.h>
#include <ui/ISurfaceFlingerClient.h>
#include <private/ui/SharedBufferStack.h>
#include <private/ui/LayerState.h>
#include "Barrier.h"
#include "Layer.h"
#include "Tokenizer.h"
#include "MessageQueue.h"
struct copybit_device_t;
struct overlay_device_t;
namespace android {
// ---------------------------------------------------------------------------
class Client;
class BClient;
class DisplayHardware;
class FreezeLock;
class Layer;
class LayerBuffer;
typedef int32_t ClientID;
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
// ---------------------------------------------------------------------------
class Client : public RefBase
{
public:
Client(ClientID cid, const sp<SurfaceFlinger>& flinger);
~Client();
int32_t generateId(int pid);
void free(int32_t id);
status_t bindLayer(const sp<LayerBaseClient>& layer, int32_t id);
inline bool isValid(int32_t i) const;
sp<LayerBaseClient> getLayerUser(int32_t i) const;
void dump(const char* what);
const Vector< wp<LayerBaseClient> >& getLayers() const {
return mLayers;
}
const sp<IMemoryHeap>& getControlBlockMemory() const {
return mCblkHeap;
}
// pointer to this client's control block
SharedClient* ctrlblk;
ClientID cid;
private:
int getClientPid() const { return mPid; }
int mPid;
uint32_t mBitmap;
SortedVector<uint8_t> mInUse;
Vector< wp<LayerBaseClient> > mLayers;
sp<IMemoryHeap> mCblkHeap;
sp<SurfaceFlinger> mFlinger;
};
// ---------------------------------------------------------------------------
class GraphicPlane
{
public:
static status_t orientationToTransfrom(int orientation, int w, int h,
Transform* tr);
GraphicPlane();
~GraphicPlane();
bool initialized() const;
void setDisplayHardware(DisplayHardware *);
void setTransform(const Transform& tr);
status_t setOrientation(int orientation);
int getOrientation() const { return mOrientation; }
const DisplayHardware& displayHardware() const;
const Transform& transform() const;
EGLDisplay getEGLDisplay() const;
private:
GraphicPlane(const GraphicPlane&);
GraphicPlane operator = (const GraphicPlane&);
DisplayHardware* mHw;
Transform mTransform;
Transform mOrientationTransform;
Transform mGlobalTransform;
int mOrientation;
};
// ---------------------------------------------------------------------------
enum {
eTransactionNeeded = 0x01,
eTraversalNeeded = 0x02
};
class SurfaceFlinger : public BnSurfaceComposer, protected Thread
{
public:
static void instantiate();
static void shutdown();
SurfaceFlinger();
virtual ~SurfaceFlinger();
void init();
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
virtual status_t dump(int fd, const Vector<String16>& args);
// ISurfaceComposer interface
virtual sp<ISurfaceFlingerClient> createConnection();
virtual sp<IMemoryHeap> getCblk() const;
virtual void bootFinished();
virtual void openGlobalTransaction();
virtual void closeGlobalTransaction();
virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags);
virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags);
virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags);
virtual void signal() const;
void screenReleased(DisplayID dpy);
void screenAcquired(DisplayID dpy);
overlay_control_device_t* getOverlayEngine() const;
status_t removeLayer(const sp<LayerBase>& layer);
status_t addLayer(const sp<LayerBase>& layer);
status_t invalidateLayerVisibility(const sp<LayerBase>& layer);
private:
friend class BClient;
friend class LayerBase;
friend class LayerBuffer;
friend class LayerBaseClient;
friend class LayerBaseClient::Surface;
friend class Layer;
friend class LayerBlur;
friend class LayerDim;
sp<ISurface> createSurface(ClientID client, int pid,
ISurfaceFlingerClient::surface_data_t* params,
DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
uint32_t flags);
sp<LayerBaseClient> createNormalSurfaceLocked(
const sp<Client>& client, DisplayID display,
int32_t id, uint32_t w, uint32_t h, uint32_t flags,
PixelFormat& format);
sp<LayerBaseClient> createBlurSurfaceLocked(
const sp<Client>& client, DisplayID display,
int32_t id, uint32_t w, uint32_t h, uint32_t flags);
sp<LayerBaseClient> createDimSurfaceLocked(
const sp<Client>& client, DisplayID display,
int32_t id, uint32_t w, uint32_t h, uint32_t flags);
sp<LayerBaseClient> createPushBuffersSurfaceLocked(
const sp<Client>& client, DisplayID display,
int32_t id, uint32_t w, uint32_t h, uint32_t flags);
status_t removeSurface(SurfaceID surface_id);
status_t destroySurface(const sp<LayerBaseClient>& layer);
status_t setClientState(ClientID cid, int32_t count, const layer_state_t* states);
class LayerVector {
public:
inline LayerVector() { }
LayerVector(const LayerVector&);
inline size_t size() const { return layers.size(); }
inline sp<LayerBase> const* array() const { return layers.array(); }
ssize_t add(const sp<LayerBase>&, Vector< sp<LayerBase> >::compar_t);
ssize_t remove(const sp<LayerBase>&);
ssize_t reorder(const sp<LayerBase>&, Vector< sp<LayerBase> >::compar_t);
ssize_t indexOf(const sp<LayerBase>& key, size_t guess=0) const;
inline sp<LayerBase> operator [] (size_t i) const { return layers[i]; }
private:
KeyedVector< sp<LayerBase> , size_t> lookup;
Vector< sp<LayerBase> > layers;
};
struct State {
State() {
orientation = ISurfaceComposer::eOrientationDefault;
freezeDisplay = 0;
}
LayerVector layersSortedByZ;
uint8_t orientation;
uint8_t orientationType;
uint8_t freezeDisplay;
};
virtual bool threadLoop();
virtual status_t readyToRun();
virtual void onFirstRef();
const GraphicPlane& graphicPlane(int dpy) const;
GraphicPlane& graphicPlane(int dpy);
void waitForEvent();
public: // hack to work around gcc 4.0.3 bug
void signalEvent();
private:
void signalDelayedEvent(nsecs_t delay);
void handleConsoleEvents();
void handleTransaction(uint32_t transactionFlags);
void handleTransactionLocked(
uint32_t transactionFlags,
Vector< sp<LayerBase> >& ditchedLayers);
void computeVisibleRegions(
LayerVector& currentLayers,
Region& dirtyRegion,
Region& wormholeRegion);
void handlePageFlip();
bool lockPageFlip(const LayerVector& currentLayers);
void unlockPageFlip(const LayerVector& currentLayers);
void handleRepaint();
void postFramebuffer();
void composeSurfaces(const Region& dirty);
void unlockClients();
void destroyConnection(ClientID cid);
sp<LayerBaseClient> getLayerUser_l(SurfaceID index) const;
status_t addLayer_l(const sp<LayerBase>& layer);
status_t removeLayer_l(const sp<LayerBase>& layer);
status_t purgatorizeLayer_l(const sp<LayerBase>& layer);
void free_resources_l();
uint32_t getTransactionFlags(uint32_t flags);
uint32_t setTransactionFlags(uint32_t flags, nsecs_t delay = 0);
void commitTransaction();
friend class FreezeLock;
sp<FreezeLock> getFreezeLock() const;
inline void incFreezeCount() { mFreezeCount++; }
inline void decFreezeCount() { if (mFreezeCount > 0) mFreezeCount--; }
inline bool hasFreezeRequest() const { return mFreezeDisplay; }
inline bool isFrozen() const {
return (mFreezeDisplay || mFreezeCount>0) && mBootFinished;
}
void debugFlashRegions();
void debugShowFPS() const;
void drawWormhole() const;
mutable MessageQueue mEventQueue;
// access must be protected by mStateLock
mutable Mutex mStateLock;
State mCurrentState;
State mDrawingState;
volatile int32_t mTransactionFlags;
volatile int32_t mTransactionCount;
Condition mTransactionCV;
bool mResizeTransationPending;
// protected by mStateLock (but we could use another lock)
Tokenizer mTokens;
DefaultKeyedVector<ClientID, sp<Client> > mClientsMap;
DefaultKeyedVector<SurfaceID, sp<LayerBaseClient> > mLayerMap;
GraphicPlane mGraphicPlanes[1];
bool mLayersRemoved;
Vector< sp<Client> > mDisconnectedClients;
// constant members (no synchronization needed for access)
sp<IMemoryHeap> mServerHeap;
surface_flinger_cblk_t* mServerCblk;
GLuint mWormholeTexName;
nsecs_t mBootTime;
Permission mHardwareTest;
Permission mAccessSurfaceFlinger;
Permission mDump;
// Can only accessed from the main thread, these members
// don't need synchronization
Region mDirtyRegion;
Region mDirtyRegionRemovedLayer;
Region mInvalidRegion;
Region mWormholeRegion;
bool mVisibleRegionsDirty;
bool mDeferReleaseConsole;
bool mFreezeDisplay;
int32_t mFreezeCount;
nsecs_t mFreezeDisplayTime;
// don't use a lock for these, we don't care
int mDebugRegion;
int mDebugBackground;
volatile nsecs_t mDebugInSwapBuffers;
nsecs_t mLastSwapBufferTime;
volatile nsecs_t mDebugInTransaction;
nsecs_t mLastTransactionTime;
bool mBootFinished;
// these are thread safe
mutable Barrier mReadyToRunBarrier;
// atomic variables
enum {
eConsoleReleased = 1,
eConsoleAcquired = 2
};
volatile int32_t mConsoleSignals;
// only written in the main thread, only read in other threads
volatile int32_t mSecureFrameBuffer;
};
// ---------------------------------------------------------------------------
class FreezeLock : public LightRefBase<FreezeLock> {
SurfaceFlinger* mFlinger;
public:
FreezeLock(SurfaceFlinger* flinger)
: mFlinger(flinger) {
mFlinger->incFreezeCount();
}
~FreezeLock() {
mFlinger->decFreezeCount();
}
};
// ---------------------------------------------------------------------------
class BClient : public BnSurfaceFlingerClient
{
public:
BClient(SurfaceFlinger *flinger, ClientID cid,
const sp<IMemoryHeap>& cblk);
~BClient();
// ISurfaceFlingerClient interface
virtual sp<IMemoryHeap> getControlBlock() const;
virtual sp<ISurface> createSurface(
surface_data_t* params, int pid,
DisplayID display, uint32_t w, uint32_t h,PixelFormat format,
uint32_t flags);
virtual status_t destroySurface(SurfaceID surfaceId);
virtual status_t setState(int32_t count, const layer_state_t* states);
private:
ClientID mId;
SurfaceFlinger* mFlinger;
sp<IMemoryHeap> mCblk;
};
// ---------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_SURFACE_FLINGER_H