Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e116c043 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge changes 24119,24120 into eclair

* changes:
  delete old and unused source files
  fix [2068105] implement queueBuffer/lockBuffer/dequeueBuffer properly
parents 73c43911 8837e2f2
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -25,8 +25,6 @@
#include <ui/ISurfaceFlingerClient.h>
#include <ui/Region.h>

#include <private/ui/SharedState.h>

namespace android {

class Parcel;
+327 −0
Original line number Diff line number Diff line
/*
 * 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_UI_SHARED_BUFFER_STACK_H
#define ANDROID_UI_SHARED_BUFFER_STACK_H

#include <stdint.h>
#include <sys/types.h>

#include <cutils/compiler.h>

#include <utils/Debug.h>
#include <utils/threads.h>
#include <utils/String8.h>

#include <ui/Rect.h>

namespace android {
// ---------------------------------------------------------------------------

/*
 * These classes manage a stack of buffers in shared memory.
 * 
 * SharedClient: represents a client with several stacks
 * SharedBufferStack: represents a stack of buffers
 * SharedBufferClient: manipulates the SharedBufferStack from the client side 
 * SharedBufferServer: manipulates the SharedBufferStack from the server side 
 *
 * Buffers can be dequeued until there are none available, they can be locked
 * unless they are in use by the server, which is only the case for the last 
 * dequeue-able buffer. When these various conditions are not met, the caller
 * waits until the condition is met.
 *
 * 
 * CAVEATS:
 * 
 * In the current implementation there are several limitations:
 * - buffers must be locked in the same order they've been dequeued
 * - buffers must be enqueued in the same order they've been locked
 * - dequeue() is not reentrant
 * - no error checks are done on the condition above
 * 
 */

// When changing these values, the COMPILE_TIME_ASSERT at the end of this
// file need to be updated.
const unsigned int NUM_LAYERS_MAX  = 31;
const unsigned int NUM_BUFFER_MAX  = 4;
const unsigned int NUM_DISPLAY_MAX = 4;

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

class Region;
class SharedBufferStack;
class SharedClient;

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

struct FlatRegion { // 12 bytes
    static const unsigned int NUM_RECT_MAX = 1;
    uint32_t    count;
    uint16_t    rects[4*NUM_RECT_MAX];
};

// should be 128 bytes (32 longs)
class SharedBufferStack
{
    friend class SharedClient;
    friend class SharedBufferBase;
    friend class SharedBufferClient;
    friend class SharedBufferServer;

public:
    SharedBufferStack();
    status_t setDirtyRegion(int buffer, const Region& reg);
    Region getDirtyRegion(int buffer) const;

    // these attributes are part of the conditions/updates
    volatile int32_t head;      // server's current front buffer
    volatile int32_t available; // number of dequeue-able buffers
    volatile int32_t queued;    // number of buffers waiting for post
    volatile int32_t inUse;     // buffer currently in use by SF

    // not part of the conditions
    volatile int32_t reallocMask;

    int32_t     identity;       // surface's identity (const)
    status_t    status;         // surface's status code
    int32_t     reserved32[13];
    FlatRegion  dirtyRegion[NUM_BUFFER_MAX];    // 12*4=48 bytes
};

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

// 4 KB max
class SharedClient
{
public:
    SharedClient();
    ~SharedClient();

    status_t validate(size_t token) const;
    uint32_t getIdentity(size_t token) const;
    status_t setIdentity(size_t token, uint32_t identity);

private:
    friend class SharedBufferBase;
    friend class SharedBufferClient;
    friend class SharedBufferServer;

    // FIXME: this should be replaced by a lock-less primitive
    Mutex lock;
    Condition cv;
    SharedBufferStack surfaces[ NUM_LAYERS_MAX ];
};

// ============================================================================

class SharedBufferBase
{
public:
    SharedBufferBase(SharedClient* sharedClient, int surface, int num);
    ~SharedBufferBase();
    uint32_t getIdentity();
    size_t getFrontBuffer() const;
    String8 dump(char const* prefix) const;

protected:
    SharedClient* const mSharedClient;
    SharedBufferStack* const mSharedStack;
    const int mNumBuffers;

    friend struct Update;
    friend struct QueueUpdate;

    struct ConditionBase {
        SharedBufferStack& stack;
        inline ConditionBase(SharedBufferBase* sbc) 
            : stack(*sbc->mSharedStack) { }
    };

    struct UpdateBase {
        SharedBufferStack& stack;
        inline UpdateBase(SharedBufferBase* sbb) 
            : stack(*sbb->mSharedStack) { }
    };

    template <typename T>
    status_t waitForCondition(T condition);

    template <typename T>
    status_t updateCondition(T update);
};

template <typename T>
status_t SharedBufferBase::waitForCondition(T condition) 
{
    SharedClient& client( *mSharedClient );
    const nsecs_t TIMEOUT = s2ns(1); 
    Mutex::Autolock _l(client.lock);
    while (!condition()) {
        status_t err = client.cv.waitRelative(client.lock, TIMEOUT);
        
        // handle errors and timeouts
        if (CC_UNLIKELY(err != NO_ERROR)) {
            if (err == TIMED_OUT) {
                if (condition()) {
                    LOGE("waitForCondition(%s) timed out (identity=%d), "
                            "but condition is true! We recovered but it "
                            "shouldn't happen." , 
                            T::name(), mSharedStack->identity);
                    break;
                } else {
                    LOGW("waitForCondition(%s) timed out (identity=%d). "
                            "CPU may be pegged. trying again.",
                            T::name(), mSharedStack->identity);
                }
            } else {
                LOGE("waitForCondition(%s) error (%s) ",
                        T::name(), strerror(-err));
                return err;
            }
        }
    }
    return NO_ERROR;
}


template <typename T>
status_t SharedBufferBase::updateCondition(T update) {
    SharedClient& client( *mSharedClient );
    Mutex::Autolock _l(client.lock);
    ssize_t result = update();
    client.cv.broadcast();    
    return result;
}

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

class SharedBufferClient : public SharedBufferBase
{
public:
    SharedBufferClient(SharedClient* sharedClient, int surface, int num);
    
    ssize_t dequeue();
    status_t undoDequeue(int buf);
    
    status_t lock(int buf);
    status_t queue(int buf);
    bool needNewBuffer(int buffer) const;
    status_t setDirtyRegion(int buffer, const Region& reg);

private:
    friend struct Condition;
    friend struct DequeueCondition;
    friend struct LockCondition;

    struct QueueUpdate : public UpdateBase {
        inline QueueUpdate(SharedBufferBase* sbb);
        inline ssize_t operator()();
    };

    struct UndoDequeueUpdate : public UpdateBase {
        inline UndoDequeueUpdate(SharedBufferBase* sbb);
        inline ssize_t operator()();
    };

    // --

    struct DequeueCondition : public ConditionBase {
        inline DequeueCondition(SharedBufferClient* sbc);
        inline bool operator()();
        static inline const char* name() { return "DequeueCondition"; }
    };

    struct LockCondition : public ConditionBase {
        int buf;
        inline LockCondition(SharedBufferClient* sbc, int buf);
        inline bool operator()();
        static inline const char* name() { return "LockCondition"; }
    };

    int32_t tail;
};

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

class SharedBufferServer : public SharedBufferBase
{
public:
    SharedBufferServer(SharedClient* sharedClient, int surface, int num);

    ssize_t retireAndLock();
    status_t unlock(int buffer);
    status_t reallocate();
    status_t assertReallocate(int buffer);

    Region getDirtyRegion(int buffer) const;

private:
    struct UnlockUpdate : public UpdateBase {
        const int lockedBuffer;
        inline UnlockUpdate(SharedBufferBase* sbb, int lockedBuffer);
        inline ssize_t operator()();
    };

    struct RetireUpdate : public UpdateBase {
        const int numBuffers;
        inline RetireUpdate(SharedBufferBase* sbb, int numBuffers);
        inline ssize_t operator()();
    };

    struct ReallocateCondition : public ConditionBase {
        int buf;
        inline ReallocateCondition(SharedBufferBase* sbb, int buf);
        inline bool operator()();
        static inline const char* name() { return "ReallocateCondition"; }
    };
};

// ===========================================================================

struct display_cblk_t
{
    uint16_t    w;
    uint16_t    h;
    uint8_t     format;
    uint8_t     orientation;
    uint8_t     reserved[2];
    float       fps;
    float       density;
    float       xdpi;
    float       ydpi;
    uint32_t    pad[2];
};

struct surface_flinger_cblk_t   // 4KB max
{
    uint8_t         connected;
    uint8_t         reserved[3];
    uint32_t        pad[7];
    display_cblk_t  displays[NUM_DISPLAY_MAX];
};

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

COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 4096)
COMPILE_TIME_ASSERT(sizeof(SharedBufferStack) == 128)
COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096)

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

#endif /* ANDROID_UI_SHARED_BUFFER_STACK_H */

include/private/ui/SharedState.h

deleted100644 → 0
+0 −154
Original line number Diff line number Diff line
/*
 * 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_UI_SHARED_STATE_H
#define ANDROID_UI_SHARED_STATE_H

#include <stdint.h>
#include <sys/types.h>

#include <utils/Debug.h>
#include <utils/threads.h>

namespace android {

/*
 * These structures are shared between the composer process and its clients
 */

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

struct surface_info_t { // 4 longs, 16 bytes
    enum {
        eBufferDirty    = 0x01,
        eNeedNewBuffer  = 0x02
    };
    uint8_t     reserved[11];
    uint8_t     flags;
    status_t    status;
};

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

const uint32_t NUM_LAYERS_MAX = 31;

enum { // layer_cblk_t swapState
    eIndex              = 0x00000001,
    eFlipRequested      = 0x00000002,
    
    eResizeBuffer0      = 0x00000004,
    eResizeBuffer1      = 0x00000008,    
    eResizeRequested    = eResizeBuffer0 | eResizeBuffer1,
    
    eBusy               = 0x00000010,
    eLocked             = 0x00000020,
    eNextFlipPending    = 0x00000040,    
    eInvalidSurface     = 0x00000080
};

enum { // layer_cblk_t flags
    eLayerNotPosted     = 0x00000001,
    eNoCopyBack         = 0x00000002,
    eReserved           = 0x0000007C,
    eBufferIndexShift   = 7,
    eBufferIndex        = 1<<eBufferIndexShift,
};

struct flat_region_t    // 40 bytes
{
    int32_t     count;
    int16_t     l;
    int16_t     t;
    int16_t     r;
    int16_t     b;
    uint16_t    runs[14];
};

struct layer_cblk_t     // (128 bytes)
{
    volatile    int32_t             swapState;      //  4
    volatile    int32_t             flags;          //  4
    volatile    int32_t             identity;       //  4
                int32_t             reserved;       //  4
                surface_info_t      surface[2];     // 32
                flat_region_t       region[2];      // 80

    static inline int backBuffer(uint32_t state) {
        return ((state & eIndex) ^ ((state & eFlipRequested)>>1));
    }
    static inline int frontBuffer(uint32_t state) {
        return 1 - backBuffer(state);
    }
};

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

struct per_client_cblk_t   // 4KB max
{
    per_client_cblk_t() : lock(Mutex::SHARED) { }

                Mutex           lock;
                Condition       cv;
                layer_cblk_t    layers[NUM_LAYERS_MAX] __attribute__((aligned(32)));

    enum {
        BLOCKING = 0x00000001,
        INSPECT  = 0x00000002
    };

    // these functions are used by the clients
    status_t validate(size_t i) const;
    int32_t lock_layer(size_t i, uint32_t flags);
    uint32_t unlock_layer_and_post(size_t i);
    void unlock_layer(size_t i);
};
// ---------------------------------------------------------------------------

const uint32_t NUM_DISPLAY_MAX = 4;

struct display_cblk_t
{
    uint16_t    w;
    uint16_t    h;
    uint8_t     format;
    uint8_t     orientation;
    uint8_t     reserved[2];
    float       fps;
    float       density;
    float       xdpi;
    float       ydpi;
    uint32_t    pad[2];
};

struct surface_flinger_cblk_t   // 4KB max
{
    uint8_t         connected;
    uint8_t         reserved[3];
    uint32_t        pad[7];
    display_cblk_t  displays[NUM_DISPLAY_MAX];
};

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

COMPILE_TIME_ASSERT(sizeof(layer_cblk_t) == 128)
COMPILE_TIME_ASSERT(sizeof(per_client_cblk_t) <= 4096)
COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096)

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

#endif // ANDROID_UI_SHARED_STATE_H
+4 −0
Original line number Diff line number Diff line
@@ -47,6 +47,9 @@ public:
    status_t lock(uint32_t usage, const Rect& rect, void** vaddr);
    status_t unlock();

    void setIndex(int index);
    int getIndex() const;
    
protected:
            SurfaceBuffer();
            SurfaceBuffer(const Parcel& reply);
@@ -69,6 +72,7 @@ private:
            android_native_buffer_t const* buffer);
    
    BufferMapper& mBufferMapper;
    int mIndex;
};

}; // namespace android
+2 −2
Original line number Diff line number Diff line
@@ -44,13 +44,13 @@ protected:
        UNREGISTER_BUFFERS,
        POST_BUFFER, // one-way transaction
        CREATE_OVERLAY,
        GET_BUFFER,
        REQUEST_BUFFER,
    };

public: 
    DECLARE_META_INTERFACE(Surface);

    virtual sp<SurfaceBuffer> getBuffer(int usage) = 0; 
    virtual sp<SurfaceBuffer> requestBuffer(int bufferIdx, int usage) = 0; 
    
    class BufferHeap {
    public:
Loading