/*
 * 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/MemoryDealer.h>

#include <ui/PixelFormat.h>
#include <ui/ISurfaceComposer.h>
#include <ui/ISurfaceFlingerClient.h>

#include <private/ui/SharedState.h>
#include <private/ui/LayerState.h>
#include <private/ui/SurfaceFlingerSynchro.h>

#include "Barrier.h"
#include "CPUGauge.h"
#include "Layer.h"
#include "Tokenizer.h"

struct copybit_device_t;
struct overlay_device_t;

namespace android {

// ---------------------------------------------------------------------------

class Client;
class BClient;
class DisplayHardware;
class FreezeLock;
class GPUHardwareInterface;
class IGPUCallback;
class Layer;
class LayerBuffer;
class LayerOrientationAnim;
class OrientationAnimation;
class SurfaceHeapManager;

typedef int32_t ClientID;

#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))

// ---------------------------------------------------------------------------

class Client
{
public:
            Client(ClientID cid, const sp<SurfaceFlinger>& flinger);
            ~Client();

            int32_t                 generateId(int pid);
            void                    free(int32_t id);
            status_t                bindLayer(LayerBaseClient* layer, int32_t id);
            sp<MemoryDealer>        createAllocator(uint32_t memory_type);

    inline  bool                    isValid(int32_t i) const;
    inline  const uint8_t*          inUseArray() const;
    inline  size_t                  numActiveLayers() const;
    LayerBaseClient*                getLayerUser(int32_t i) const;
    const Vector<LayerBaseClient*>& getLayers() const { return mLayers; }
    const sp<IMemory>&              controlBlockMemory() const { return mCblkMemory; }
    void                            dump(const char* what);
    const sp<SurfaceHeapManager>&   getSurfaceHeapManager() const;
    
    // pointer to this client's control block
    per_client_cblk_t*      ctrlblk;
    ClientID                cid;

    
private:
    int                     getClientPid() const { return mPid; }
        
    int                         mPid;
    uint32_t                    mBitmap;
    SortedVector<uint8_t>       mInUse;
    Vector<LayerBaseClient*>    mLayers;
    sp<MemoryDealer>            mCblkHeap;
    sp<SurfaceFlinger>          mFlinger;
    sp<MemoryDealer>            mSharedHeapAllocator;
    sp<MemoryDealer>            mPMemAllocator;
    sp<IMemory>                 mCblkMemory;
};

// ---------------------------------------------------------------------------

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;
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<IMemory>                 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;
    virtual status_t requestGPU(const sp<IGPUCallback>& callback, 
            gpu_info_t* gpu);
    virtual status_t revokeGPU();

            void                        screenReleased(DisplayID dpy);
            void                        screenAcquired(DisplayID dpy);

            const sp<SurfaceHeapManager>& getSurfaceHeapManager() const { 
                return mSurfaceHeapManager; 
            }

            const sp<GPUHardwareInterface>& getGPU() const {
                return mGPU; 
            }

            copybit_device_t* getBlitEngine() const;
            overlay_control_device_t* getOverlayEngine() const;

            
    status_t removeLayer(LayerBase* layer);
    status_t addLayer(LayerBase* layer);
    status_t invalidateLayerVisibility(LayerBase* layer);
    
private:
    friend class BClient;
    friend class LayerBase;
    friend class LayerBuffer;
    friend class LayerBaseClient;
    friend class Layer;
    friend class LayerBlur;

    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);

    LayerBaseClient* createNormalSurfaceLocked(Client* client, DisplayID display,
            int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags);

    LayerBaseClient* createBlurSurfaceLocked(Client* client, DisplayID display,
            int32_t id, uint32_t w, uint32_t h, uint32_t flags);

    LayerBaseClient* createDimSurfaceLocked(Client* client, DisplayID display,
            int32_t id, uint32_t w, uint32_t h, uint32_t flags);

    LayerBaseClient* createPushBuffersSurfaceLocked(Client* client, DisplayID display,
            int32_t id, uint32_t w, uint32_t h, uint32_t flags);

    status_t    destroySurface(SurfaceID surface_id);
    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 LayerBase*const* array() const { return layers.array(); }
        ssize_t             add(LayerBase*, Vector<LayerBase*>::compar_t);
        ssize_t             remove(LayerBase*);
        ssize_t             reorder(LayerBase*, Vector<LayerBase*>::compar_t);
        ssize_t             indexOf(LayerBase* key, size_t guess=0) const;
        inline LayerBase*   operator [] (size_t i) const { return layers[i]; }
    private:
        KeyedVector<LayerBase*, size_t> lookup;
        Vector<LayerBase*>              layers;
    };

    struct State {
        State() {
            orientation = ISurfaceComposer::eOrientationDefault;
            freezeDisplay = 0;
        }
        LayerVector     layersSortedByZ;
        uint8_t         orientation;
        uint8_t         orientationType;
        uint8_t         freezeDisplay;
    };

    class DelayedTransaction : public Thread
    {
        friend class SurfaceFlinger;
        sp<SurfaceFlinger>  mFlinger;
        nsecs_t             mDelay;
    public:
        DelayedTransaction(const sp<SurfaceFlinger>& flinger, nsecs_t delay)
            : Thread(false), mFlinger(flinger), mDelay(delay) {
        }
        virtual bool threadLoop() {
            usleep(mDelay / 1000);
            if (android_atomic_and(~1,
                    &mFlinger->mDeplayedTransactionPending) == 1) {
                mFlinger->signalEvent();
            }
            return false;
        }
    };

    virtual bool        threadLoop();
    virtual status_t    readyToRun();
    virtual void        onFirstRef();

    const GraphicPlane&     graphicPlane(int dpy) const;
          GraphicPlane&     graphicPlane(int dpy);

            void        waitForEvent();
            void        signalEvent();
            void        signalDelayedEvent(nsecs_t delay);

            void        handleConsoleEvents();
            void        handleTransaction(uint32_t transactionFlags);

            void        computeVisibleRegions(
                            LayerVector& currentLayers,
                            Region& dirtyRegion,
                            Region& wormholeRegion);

            void        handlePageFlip();
            bool        lockPageFlip(const LayerVector& currentLayers);
            void        unlockPageFlip(const LayerVector& currentLayers);
            void        handleRepaint();
            void        handleDebugCpu();
            void        scheduleBroadcast(Client* client);
            void        executeScheduledBroadcasts();
            void        postFramebuffer();
            void        composeSurfaces(const Region& dirty);
            void        unlockClients();


            void        destroyConnection(ClientID cid);
            LayerBaseClient* getLayerUser_l(SurfaceID index) const;
            status_t    addLayer_l(LayerBase* layer);
            status_t    removeLayer_l(LayerBase* layer);
            void        destroy_all_removed_layers_l();
            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;
            }

            
            void        debugFlashRegions();
            void        debugShowFPS() const;
            void        drawWormhole() const;
           
                // access must be protected by mStateLock
    mutable     Mutex                   mStateLock;
                State                   mCurrentState;
                State                   mDrawingState;
    volatile    int32_t                 mTransactionFlags;
    volatile    int32_t                 mTransactionCount;
                Condition               mTransactionCV;

                // protected by mStateLock (but we could use another lock)
                Tokenizer                               mTokens;
                DefaultKeyedVector<ClientID, Client*>   mClientsMap;
                DefaultKeyedVector<SurfaceID, LayerBaseClient*>   mLayerMap;
                GraphicPlane                            mGraphicPlanes[1];
                SortedVector<LayerBase*>                mRemovedLayers;
                Vector<Client*>                         mDisconnectedClients;

                // constant members (no synchronization needed for access)
                sp<MemoryDealer>            mServerHeap;
                sp<IMemory>                 mServerCblkMemory;
                surface_flinger_cblk_t*     mServerCblk;
                sp<SurfaceHeapManager>      mSurfaceHeapManager;
                sp<GPUHardwareInterface>    mGPU;
                GLuint                      mWormholeTexName;
                nsecs_t                     mBootTime;
                
                // Can only accessed from the main thread, these members
                // don't need synchronization
                Region                      mDirtyRegion;
                Region                      mInvalidRegion;
                Region                      mWormholeRegion;
                Client*                     mLastScheduledBroadcast;
                SortedVector<Client*>       mScheduledBroadcasts;
                bool                        mVisibleRegionsDirty;
                bool                        mDeferReleaseConsole;
                bool                        mFreezeDisplay;
                int32_t                     mFreezeCount;
                nsecs_t                     mFreezeDisplayTime;
                friend class OrientationAnimation;
                OrientationAnimation*       mOrientationAnimation;

                // access protected by mDebugLock
    mutable     Mutex                       mDebugLock;
                sp<CPUGauge>                mCpuGauge;

                // don't use a lock for these, we don't care
                int                         mDebugRegion;
                int                         mDebugCpu;
                int                         mDebugFps;
                int                         mDebugBackground;

                // these are thread safe
    mutable     Barrier                     mReadyToRunBarrier;
    mutable     SurfaceFlingerSynchro       mSyncObject;
    volatile    int32_t                     mDeplayedTransactionPending;

                // 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<IMemory>& cblk);
    ~BClient();

    // ISurfaceFlingerClient interface
    virtual void getControlBlocks(sp<IMemory>* ctrl) 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<IMemory>         mCblk;
};

// ---------------------------------------------------------------------------
}; // namespace android

#endif // ANDROID_SURFACE_FLINGER_H
