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

Commit 2be352ad authored by Mathias Agopian's avatar Mathias Agopian
Browse files

added the notion of fixed-size buffers

the new native_window_set_buffers_geometry allows
to specify a size and format for all buffers to be
dequeued. the buffer will be scalled to the window's
size.

Change-Id: I2c378b85c88d29cdd827a5f319d5c704d79ba381
parent 57d89899
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -279,7 +279,8 @@ public:
    ssize_t retireAndLock();
    ssize_t retireAndLock();
    status_t unlock(int buffer);
    status_t unlock(int buffer);
    void setStatus(status_t status);
    void setStatus(status_t status);
    status_t reallocate();
    status_t reallocateAll();
    status_t reallocateAllExcept(int buffer);
    status_t assertReallocate(int buffer);
    status_t assertReallocate(int buffer);
    int32_t getQueuedCount() const;
    int32_t getQueuedCount() const;
    Region getDirtyRegion(int buffer) const;
    Region getDirtyRegion(int buffer) const;
+2 −1
Original line number Original line Diff line number Diff line
@@ -53,7 +53,8 @@ protected:
public: 
public: 
    DECLARE_META_INTERFACE(Surface);
    DECLARE_META_INTERFACE(Surface);


    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage) = 0; 
    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx,
            uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0;
    virtual status_t setBufferCount(int bufferCount) = 0;
    virtual status_t setBufferCount(int bufferCount) = 0;
    
    
    class BufferHeap {
    class BufferHeap {
+32 −5
Original line number Original line Diff line number Diff line
@@ -36,6 +36,7 @@ namespace android {


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


class GraphicBuffer;
class GraphicBufferMapper;
class GraphicBufferMapper;
class IOMX;
class IOMX;
class Rect;
class Rect;
@@ -213,12 +214,14 @@ private:
    int  dispatch_disconnect(va_list args);
    int  dispatch_disconnect(va_list args);
    int  dispatch_crop(va_list args);
    int  dispatch_crop(va_list args);
    int  dispatch_set_buffer_count(va_list args);
    int  dispatch_set_buffer_count(va_list args);
    int  dispatch_set_buffers_geometry(va_list args);
    
    
    void setUsage(uint32_t reqUsage);
    void setUsage(uint32_t reqUsage);
    int  connect(int api);
    int  connect(int api);
    int  disconnect(int api);
    int  disconnect(int api);
    int  crop(Rect const* rect);
    int  crop(Rect const* rect);
    int  setBufferCount(int bufferCount);
    int  setBufferCount(int bufferCount);
    int  setBuffersGeometry(int w, int h, int format);


    /*
    /*
     *  private stuff...
     *  private stuff...
@@ -231,12 +234,34 @@ private:
    inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
    inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
    inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
    inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }


    status_t getBufferLocked(int index, int usage);
    status_t getBufferLocked(int index,
            uint32_t w, uint32_t h, uint32_t format, uint32_t usage);
    int getBufferIndex(const sp<GraphicBuffer>& buffer) const;
    int getBufferIndex(const sp<GraphicBuffer>& buffer) const;


    uint32_t getUsage() const;
    int getConnectedApi() const;
    int getConnectedApi() const;
    
    
    bool needNewBuffer(int bufIdx,
            uint32_t *pWidth, uint32_t *pHeight,
            uint32_t *pFormat, uint32_t *pUsage) const;

    class BufferInfo {
        uint32_t mWidth;
        uint32_t mHeight;
        uint32_t mFormat;
        uint32_t mUsage;
        mutable uint32_t mDirty;
        enum {
            GEOMETRY = 0x01
        };
    public:
        BufferInfo();
        void set(uint32_t w, uint32_t h, uint32_t format);
        void set(uint32_t usage);
        void get(uint32_t *pWidth, uint32_t *pHeight,
                uint32_t *pFormat, uint32_t *pUsage) const;
        bool validateBuffer(const sp<GraphicBuffer>& buffer) const;
    };

    // constants
    // constants
    sp<SurfaceComposerClient>   mClient;
    sp<SurfaceComposerClient>   mClient;
    sp<ISurface>                mSurface;
    sp<ISurface>                mSurface;
@@ -249,13 +274,12 @@ private:


    // protected by mSurfaceLock
    // protected by mSurfaceLock
    Rect                        mSwapRectangle;
    Rect                        mSwapRectangle;
    uint32_t                    mUsage;
    int                         mConnected;
    int                         mConnected;
    Rect                        mNextBufferCrop;
    Rect                        mNextBufferCrop;
    BufferInfo                  mBufferInfo;
    
    
    // protected by mSurfaceLock. These are also used from lock/unlock
    // protected by mSurfaceLock. These are also used from lock/unlock
    // but in that case, they must be called form the same thread.
    // but in that case, they must be called form the same thread.
    sp<GraphicBuffer>           mBuffers[2];
    mutable Region              mDirtyRegion;
    mutable Region              mDirtyRegion;


    // must be used from the lock/unlock thread
    // must be used from the lock/unlock thread
@@ -264,6 +288,9 @@ private:
    mutable Region              mOldDirtyRegion;
    mutable Region              mOldDirtyRegion;
    bool                        mReserved;
    bool                        mReserved;


    // only used from dequeueBuffer()
    Vector< sp<GraphicBuffer> > mBuffers;

    // query() must be called from dequeueBuffer() thread
    // query() must be called from dequeueBuffer() thread
    uint32_t                    mWidth;
    uint32_t                    mWidth;
    uint32_t                    mHeight;
    uint32_t                    mHeight;
+21 −0
Original line number Original line Diff line number Diff line
@@ -82,6 +82,7 @@ enum {
    NATIVE_WINDOW_DISCONNECT,
    NATIVE_WINDOW_DISCONNECT,
    NATIVE_WINDOW_SET_CROP,
    NATIVE_WINDOW_SET_CROP,
    NATIVE_WINDOW_SET_BUFFER_COUNT,
    NATIVE_WINDOW_SET_BUFFER_COUNT,
    NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
};
};


/* parameter for NATIVE_WINDOW_[DIS]CONNECT */
/* parameter for NATIVE_WINDOW_[DIS]CONNECT */
@@ -192,6 +193,7 @@ typedef struct android_native_window_t
     *     NATIVE_WINDOW_DISCONNECT
     *     NATIVE_WINDOW_DISCONNECT
     *     NATIVE_WINDOW_SET_CROP
     *     NATIVE_WINDOW_SET_CROP
     *     NATIVE_WINDOW_SET_BUFFER_COUNT
     *     NATIVE_WINDOW_SET_BUFFER_COUNT
     *     NATIVE_WINDOW_SET_BUFFERS_GEOMETRY
     *  
     *  
     */
     */
    
    
@@ -273,6 +275,25 @@ static inline int native_window_set_buffer_count(
    return window->perform(window, NATIVE_WINDOW_SET_BUFFER_COUNT, bufferCount);
    return window->perform(window, NATIVE_WINDOW_SET_BUFFER_COUNT, bufferCount);
}
}


/*
 * native_window_set_buffers_geometry(..., int w, int h, int format)
 * All buffers dequeued after this call will have the geometry specified.
 * In particular, all buffers will have a fixed-size, independent form the
 * native-window size. They will be appropriately scaled to the window-size
 * upon composition.
 *
 * If all parameters are 0, the normal behavior is restored. That is,
 * dequeued buffers following this call will be sized to the window's size.
 *
 */
static inline int native_window_set_buffers_geometry(
        android_native_window_t* window,
        int w, int h, int format)
{
    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
            w, h, format);
}

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


/* FIXME: this is legacy for pixmaps */
/* FIXME: this is legacy for pixmaps */
+70 −43
Original line number Original line Diff line number Diff line
@@ -55,7 +55,8 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display,
        mNeedsBlending(true),
        mNeedsBlending(true),
        mNeedsDithering(false),
        mNeedsDithering(false),
        mTextureManager(mFlags),
        mTextureManager(mFlags),
        mBufferManager(mTextureManager)
        mBufferManager(mTextureManager),
        mWidth(0), mHeight(0), mFixedSize(false)
{
{
    // no OpenGL operation is possible here, since we might not be
    // no OpenGL operation is possible here, since we might not be
    // in the OpenGL thread.
    // in the OpenGL thread.
@@ -227,10 +228,18 @@ status_t Layer::setBufferCount(int bufferCount)
    return err;
    return err;
}
}


sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
sp<GraphicBuffer> Layer::requestBuffer(int index,
        uint32_t reqWidth, uint32_t reqHeight, uint32_t reqFormat,
        uint32_t usage)
{
{
    sp<GraphicBuffer> buffer;
    sp<GraphicBuffer> buffer;


    if ((reqWidth | reqHeight | reqFormat) < 0)
        return buffer;

    if ((!reqWidth && reqHeight) || (reqWidth && !reqHeight))
        return buffer;

    // this ensures our client doesn't go away while we're accessing
    // this ensures our client doesn't go away while we're accessing
    // the shared area.
    // the shared area.
    sp<Client> ourClient(client.promote());
    sp<Client> ourClient(client.promote());
@@ -256,23 +265,33 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)
        return buffer;
        return buffer;
    }
    }


    uint32_t w, h;
    uint32_t w, h, f;
    { // scope for the lock
    { // scope for the lock
        Mutex::Autolock _l(mLock);
        Mutex::Autolock _l(mLock);
        w = mWidth;
        const bool fixedSizeChanged = mFixedSize != (reqWidth && reqHeight);
        h = mHeight;
        const bool formatChanged    = mReqFormat != reqFormat;
        mReqWidth  = reqWidth;
        mReqHeight = reqHeight;
        mReqFormat = reqFormat;
        mFixedSize = reqWidth && reqHeight;
        w = reqWidth  ? reqWidth  : mWidth;
        h = reqHeight ? reqHeight : mHeight;
        f = reqFormat ? reqFormat : mFormat;
        buffer = mBufferManager.detachBuffer(index);
        buffer = mBufferManager.detachBuffer(index);
        if (fixedSizeChanged || formatChanged) {
            lcblk->reallocateAllExcept(index);
        }
    }
    }


    const uint32_t effectiveUsage = getEffectiveUsage(usage);
    const uint32_t effectiveUsage = getEffectiveUsage(usage);
    if (buffer!=0 && buffer->getStrongCount() == 1) {
    if (buffer!=0 && buffer->getStrongCount() == 1) {
        err = buffer->reallocate(w, h, mFormat, effectiveUsage);
        err = buffer->reallocate(w, h, f, effectiveUsage);
    } else {
    } else {
        // here we have to reallocate a new buffer because we could have a
        // here we have to reallocate a new buffer because we could have a
        // client in our process with a reference to it (eg: status bar),
        // client in our process with a reference to it (eg: status bar),
        // and we can't release the handle under its feet.
        // and we can't release the handle under its feet.
        buffer.clear();
        buffer.clear();
        buffer = new GraphicBuffer(w, h, mFormat, effectiveUsage);
        buffer = new GraphicBuffer(w, h, f, effectiveUsage);
        err = buffer->initCheck();
        err = buffer->initCheck();
    }
    }


@@ -288,12 +307,7 @@ sp<GraphicBuffer> Layer::requestBuffer(int index, int usage)


    if (err == NO_ERROR && buffer->handle != 0) {
    if (err == NO_ERROR && buffer->handle != 0) {
        Mutex::Autolock _l(mLock);
        Mutex::Autolock _l(mLock);
        if (mWidth && mHeight) {
        mBufferManager.attachBuffer(index, buffer);
        mBufferManager.attachBuffer(index, buffer);
        } else {
            // oops we got killed while we were allocating the buffer
            buffer.clear();
        }
    }
    }
    return buffer;
    return buffer;
}
}
@@ -330,8 +344,10 @@ uint32_t Layer::doTransaction(uint32_t flags)
    const Layer::State& front(drawingState());
    const Layer::State& front(drawingState());
    const Layer::State& temp(currentState());
    const Layer::State& temp(currentState());


    if ((front.requested_w != temp.requested_w) || 
    const bool sizeChanged = (front.requested_w != temp.requested_w) ||
        (front.requested_h != temp.requested_h)) {
            (front.requested_h != temp.requested_h);

    if (sizeChanged) {
        // the size changed, we need to ask our client to request a new buffer
        // the size changed, we need to ask our client to request a new buffer
        LOGD_IF(DEBUG_RESIZE,
        LOGD_IF(DEBUG_RESIZE,
                "resize (layer=%p), requested (%dx%d), drawing (%d,%d)",
                "resize (layer=%p), requested (%dx%d), drawing (%d,%d)",
@@ -339,6 +355,7 @@ uint32_t Layer::doTransaction(uint32_t flags)
                int(temp.requested_w), int(temp.requested_h),
                int(temp.requested_w), int(temp.requested_h),
                int(front.requested_w), int(front.requested_h));
                int(front.requested_w), int(front.requested_h));


        if (!isFixedSize()) {
            // we're being resized and there is a freeze display request,
            // we're being resized and there is a freeze display request,
            // acquire a freeze lock, so that the screen stays put
            // acquire a freeze lock, so that the screen stays put
            // until we've redrawn at the new size; this is to avoid
            // until we've redrawn at the new size; this is to avoid
@@ -357,12 +374,16 @@ uint32_t Layer::doTransaction(uint32_t flags)
            editDraw.requested_w = temp.requested_w;
            editDraw.requested_w = temp.requested_w;
            editDraw.requested_h = temp.requested_h;
            editDraw.requested_h = temp.requested_h;


        // record the new size, form this point on, when the client request a
            // record the new size, form this point on, when the client request
        // buffer, it'll get the new size.
            // a buffer, it'll get the new size.
        setDrawingSize(temp.requested_w, temp.requested_h);
            setBufferSize(temp.requested_w, temp.requested_h);


            // all buffers need reallocation
            // all buffers need reallocation
        lcblk->reallocate();
            lcblk->reallocateAll();
        } else {
            // record the new size
            setBufferSize(temp.requested_w, temp.requested_h);
        }
    }
    }


    if (temp.sequence != front.sequence) {
    if (temp.sequence != front.sequence) {
@@ -376,12 +397,17 @@ uint32_t Layer::doTransaction(uint32_t flags)
    return LayerBase::doTransaction(flags);
    return LayerBase::doTransaction(flags);
}
}


void Layer::setDrawingSize(uint32_t w, uint32_t h) {
void Layer::setBufferSize(uint32_t w, uint32_t h) {
    Mutex::Autolock _l(mLock);
    Mutex::Autolock _l(mLock);
    mWidth = w;
    mWidth = w;
    mHeight = h;
    mHeight = h;
}
}


bool Layer::isFixedSize() const {
    Mutex::Autolock _l(mLock);
    return mFixedSize;
}

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// pageflip handling...
// pageflip handling...
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
@@ -677,7 +703,8 @@ Layer::SurfaceLayer::~SurfaceLayer()
{
{
}
}


sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index,
        uint32_t w, uint32_t h, uint32_t format, uint32_t usage)
{
{
    sp<GraphicBuffer> buffer;
    sp<GraphicBuffer> buffer;
    sp<Layer> owner(getOwner());
    sp<Layer> owner(getOwner());
@@ -687,7 +714,7 @@ sp<GraphicBuffer> Layer::SurfaceLayer::requestBuffer(int index, int usage)
         * as it could cause a dead-lock, since it may have to wait
         * as it could cause a dead-lock, since it may have to wait
         * on conditions updated my the main thread.
         * on conditions updated my the main thread.
         */
         */
        buffer = owner->requestBuffer(index, usage);
        buffer = owner->requestBuffer(index, w, h, format, usage);
    }
    }
    return buffer;
    return buffer;
}
}
Loading