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

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

Merge change 21401 into eclair

* changes:
  make sure to update a surface's usage bits when it changes, instead of only the first time.
parents 82726f04 321abdb0
Loading
Loading
Loading
Loading
+35 −17
Original line number Diff line number Diff line
@@ -146,16 +146,16 @@ public:
    static bool isValid(const sp<Surface>& surface) {
        return (surface != 0) && surface->isValid();
    }
    bool isValid() {
        return mToken>=0 && mClient!=0;
    }

    static bool isSameSurface(
            const sp<Surface>& lhs, const sp<Surface>& rhs);

    bool        isValid();
    SurfaceID   ID() const          { return mToken; }
    uint32_t    getFlags() const    { return mFlags; }
    uint32_t    getIdentity() const { return mIdentity; }


    // the lock/unlock APIs must be used from the same thread
    status_t    lock(SurfaceInfo* info, bool blocking = true);
    status_t    lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
    status_t    unlockAndPost();
@@ -175,14 +175,18 @@ private:
    friend class SurfaceComposerClient;
    friend class SurfaceControl;

    
    // camera and camcorder need access to the ISurface binder interface for preview
    friend class Camera;
    friend class MediaRecorder;
    // mediaplayer needs access to ISurface for display
    friend class MediaPlayer;
    friend class Test;
    friend class IOMX;
    const sp<ISurface>& getISurface() const { return mSurface; }
    // this is just to be able to write some unit tests
    friend class Test;

    sp<SurfaceComposerClient> getClient() const;
    sp<ISurface> getISurface() const;

    status_t getBufferLocked(int index, int usage);
   
@@ -210,24 +214,38 @@ private:
    status_t queueBuffer(const sp<SurfaceBuffer>& buffer);

    
    alloc_device_t*             mAllocDevice;
    void setUsage(uint32_t reqUsage);
    
    // constants
    sp<SurfaceComposerClient>   mClient;
    sp<ISurface>                mSurface;
    sp<SurfaceBuffer>           mBuffers[2];
    sp<SurfaceBuffer>           mLockedBuffer;
    SurfaceID                   mToken;
    uint32_t                    mIdentity;
    uint32_t                    mWidth;
    uint32_t                    mHeight;
    uint32_t                    mUsage;
    PixelFormat                 mFormat;
    uint32_t                    mFlags;
    BufferMapper&               mBufferMapper;

    // protected by mSurfaceLock
    Rect                        mSwapRectangle;
    uint32_t                    mUsage;
    bool                        mUsageChanged;
    
    // protected by mSurfaceLock. These are also used from lock/unlock
    // but in that case, they must be called form the same thread.
    sp<SurfaceBuffer>           mBuffers[2];
    mutable Region              mDirtyRegion;
    mutable Region              mOldDirtyRegion;
    mutable uint8_t             mBackbufferIndex;

    // must be used from the lock/unlock thread
    sp<SurfaceBuffer>           mLockedBuffer;
    mutable Region              mOldDirtyRegion;

    // query() must be called from dequeueBuffer() thread
    uint32_t                    mWidth;
    uint32_t                    mHeight;

    // Inherently thread-safe
    mutable Mutex               mSurfaceLock;
    Rect                        mSwapRectangle;
    BufferMapper&               mBufferMapper;
};

}; // namespace android
+52 −23
Original line number Diff line number Diff line
@@ -382,9 +382,9 @@ sp<Surface> SurfaceControl::getSurface() const
Surface::Surface(const sp<SurfaceControl>& surface)
    : mClient(surface->mClient), mSurface(surface->mSurface),
      mToken(surface->mToken), mIdentity(surface->mIdentity),
      mWidth(surface->mWidth), mHeight(surface->mHeight),
      mFormat(surface->mFormat), mFlags(surface->mFlags),
      mBufferMapper(BufferMapper::get())
      mBufferMapper(BufferMapper::get()),
      mWidth(surface->mWidth), mHeight(surface->mHeight)
{
    init();
}
@@ -426,9 +426,9 @@ void Surface::init()
    const_cast<uint32_t&>(android_native_window_t::flags) = 0;
    // be default we request a hardware surface
    mUsage = GRALLOC_USAGE_HW_RENDER;
    mUsageChanged = true;
}


Surface::~Surface()
{
    // this is a client-side operation, the surface is destroyed, unmap
@@ -446,11 +446,24 @@ Surface::~Surface()
    IPCThreadState::self()->flushCommands();
}

sp<SurfaceComposerClient> Surface::getClient() const {
    return mClient;
}

sp<ISurface> Surface::getISurface() const {
    return mSurface;
}

bool Surface::isValid() {
    return mToken>=0 && mClient!=0;
}

status_t Surface::validate(per_client_cblk_t const* cblk) const
{
    sp<SurfaceComposerClient> client(getClient());
    if (mToken<0 || mClient==0) {
        LOGE("invalid token (%d, identity=%u) or client (%p)", 
                mToken, mIdentity, mClient.get());
                mToken, mIdentity, client.get());
        return NO_INIT;
    }
    if (cblk == 0) {
@@ -477,6 +490,7 @@ bool Surface::isSameSurface(
{
    if (lhs == 0 || rhs == 0)
        return false;

    return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
}

@@ -532,10 +546,9 @@ status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* buffer)
{
    android_native_buffer_t* out;
    status_t err = dequeueBuffer(&out);
    if (err == NO_ERROR) {
        *buffer = SurfaceBuffer::getSelf(out);
    // reset the width/height with the what we get from the buffer
    mWidth  = uint32_t(out->width);
    mHeight = uint32_t(out->height);
    }
    return err;
}

@@ -557,7 +570,8 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer)

    Mutex::Autolock _l(mSurfaceLock);

    per_client_cblk_t* const cblk = mClient->mControl;
    sp<SurfaceComposerClient> client(getClient());
    per_client_cblk_t* const cblk = client->mControl;
    status_t err = validate(cblk);
    if (err != NO_ERROR)
        return err;
@@ -572,14 +586,17 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer)

    mBackbufferIndex = backIdx;
    layer_cblk_t* const lcblk = &(cblk->layers[index]);

    volatile const surface_info_t* const back = lcblk->surface + backIdx;
    if (back->flags & surface_info_t::eNeedNewBuffer) {
    if ((back->flags & surface_info_t::eNeedNewBuffer) || mUsageChanged) {
        mUsageChanged = false;
        err = getBufferLocked(backIdx, mUsage);
    }

    if (err == NO_ERROR) {
        const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
        // reset the width/height with the what we get from the buffer
        mWidth  = uint32_t(backBuffer->width);
        mHeight = uint32_t(backBuffer->height);
        mDirtyRegion.set(backBuffer->width, backBuffer->height);
        *buffer = backBuffer.get();
    }
@@ -591,7 +608,8 @@ int Surface::lockBuffer(android_native_buffer_t* buffer)
{
    Mutex::Autolock _l(mSurfaceLock);

    per_client_cblk_t* const cblk = mClient->mControl;
    sp<SurfaceComposerClient> client(getClient());
    per_client_cblk_t* const cblk = client->mControl;
    status_t err = validate(cblk);
    if (err != NO_ERROR)
        return err;
@@ -604,7 +622,8 @@ int Surface::queueBuffer(android_native_buffer_t* buffer)
{   
    Mutex::Autolock _l(mSurfaceLock);

    per_client_cblk_t* const cblk = mClient->mControl;
    sp<SurfaceComposerClient> client(getClient());
    per_client_cblk_t* const cblk = client->mControl;
    status_t err = validate(cblk);
    if (err != NO_ERROR)
        return err;
@@ -620,7 +639,7 @@ int Surface::queueBuffer(android_native_buffer_t* buffer)

    uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
    if (!(newstate & eNextFlipPending))
        mClient->signalServer();
        client->signalServer();

    return NO_ERROR;
}
@@ -646,7 +665,7 @@ int Surface::perform(int operation, va_list args)
    int res = NO_ERROR;
    switch (operation) {
        case NATIVE_WINDOW_SET_USAGE:
            mUsage = va_arg(args, int);
            setUsage( va_arg(args, int) );
            break;
        default:
            res = NAME_NOT_FOUND;
@@ -655,6 +674,15 @@ int Surface::perform(int operation, va_list args)
    return res;
}

void Surface::setUsage(uint32_t reqUsage)
{
    Mutex::Autolock _l(mSurfaceLock);
    if (mUsage != reqUsage) {
        mUsageChanged = true;
        mUsage = reqUsage;
    }
}

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

status_t Surface::lock(SurfaceInfo* info, bool blocking) {
@@ -663,10 +691,8 @@ status_t Surface::lock(SurfaceInfo* info, bool blocking) {

status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) 
{
    // FIXME: needs some locking here

    // we're intending to do software rendering from this point
    mUsage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
    setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);

    sp<SurfaceBuffer> backBuffer;
    status_t err = dequeueBuffer(&backBuffer);
@@ -679,7 +705,8 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
            Region scratch(bounds);
            Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch);

            per_client_cblk_t* const cblk = mClient->mControl;
            sp<SurfaceComposerClient> client(getClient());
            per_client_cblk_t* const cblk = client->mControl;
            layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
            volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
            if (back->flags & surface_info_t::eBufferDirty) {
@@ -725,8 +752,6 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
    
status_t Surface::unlockAndPost() 
{
    // FIXME: needs some locking here

    if (mLockedBuffer == 0)
        return BAD_VALUE;

@@ -753,13 +778,17 @@ void Surface::_send_dirty_region(
}

void Surface::setSwapRectangle(const Rect& r) {
    Mutex::Autolock _l(mSurfaceLock);
    mSwapRectangle = r;
}

status_t Surface::getBufferLocked(int index, int usage)
{
    sp<ISurface> s(mSurface);
    if (s == 0) return NO_INIT;

    status_t err = NO_MEMORY;
    sp<SurfaceBuffer> buffer = mSurface->getBuffer(usage);
    sp<SurfaceBuffer> buffer = s->getBuffer(usage);
    LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
    if (buffer != 0) {
        sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);