From b296533607232357597b255679db29470ab5925d Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 27 Apr 2010 16:41:19 -0700 Subject: [PATCH] cleanup. waitForCondition() now uses polymorphsim instead of templtes the reason for the above change is that waitForCondition() had become large over time, mainly to handle error cases, using inlines to evaluate the condition doesn't buys us much anymore while it increases code size. Change-Id: I2595d850832628954b900ab8bb1796c863447bc7 --- .../surfaceflinger/SharedBufferStack.h | 59 ++++--------------- include/surfaceflinger/Surface.h | 56 ++++++++++-------- .../SharedBufferStack.cpp | 42 ++++++++++++- libs/surfaceflinger_client/Surface.cpp | 30 ++++------ 4 files changed, 94 insertions(+), 93 deletions(-) diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h index 39ef3a186..dc53d6a4b 100644 --- a/include/private/surfaceflinger/SharedBufferStack.h +++ b/include/private/surfaceflinger/SharedBufferStack.h @@ -176,60 +176,21 @@ protected: SharedBufferStack& stack; inline ConditionBase(SharedBufferBase* sbc) : stack(*sbc->mSharedStack) { } + virtual ~ConditionBase() { }; + virtual bool operator()() const = 0; + virtual const char* name() const = 0; }; + status_t waitForCondition(const ConditionBase& condition); struct UpdateBase { SharedBufferStack& stack; inline UpdateBase(SharedBufferBase* sbb) : stack(*sbb->mSharedStack) { } }; - - template - status_t waitForCondition(T condition); - template status_t updateCondition(T update); }; -template -status_t SharedBufferBase::waitForCondition(T condition) -{ - const SharedBufferStack& stack( *mSharedStack ); - SharedClient& client( *mSharedClient ); - const nsecs_t TIMEOUT = s2ns(1); - Mutex::Autolock _l(client.lock); - while ((condition()==false) && - (stack.identity == mIdentity) && - (stack.status == NO_ERROR)) - { - 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(), - stack.identity); - break; - } else { - LOGW("waitForCondition(%s) timed out " - "(identity=%d, status=%d). " - "CPU may be pegged. trying again.", T::name(), - stack.identity, stack.status); - } - } else { - LOGE("waitForCondition(%s) error (%s) ", - T::name(), strerror(-err)); - return err; - } - } - } - return (stack.identity != mIdentity) ? status_t(BAD_INDEX) : stack.status; -} - - template status_t SharedBufferBase::updateCondition(T update) { SharedClient& client( *mSharedClient ); @@ -275,15 +236,15 @@ private: struct DequeueCondition : public ConditionBase { inline DequeueCondition(SharedBufferClient* sbc); - inline bool operator()(); - static inline const char* name() { return "DequeueCondition"; } + inline bool operator()() const; + inline const char* name() const { return "DequeueCondition"; } }; struct LockCondition : public ConditionBase { int buf; inline LockCondition(SharedBufferClient* sbc, int buf); - inline bool operator()(); - static inline const char* name() { return "LockCondition"; } + inline bool operator()() const; + inline const char* name() const { return "LockCondition"; } }; int32_t tail; @@ -334,8 +295,8 @@ private: struct ReallocateCondition : public ConditionBase { int buf; inline ReallocateCondition(SharedBufferBase* sbb, int buf); - inline bool operator()(); - static inline const char* name() { return "ReallocateCondition"; } + inline bool operator()() const; + inline const char* name() const { return "ReallocateCondition"; } }; }; diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h index 40dc467fb..7ab3a0014 100644 --- a/include/surfaceflinger/Surface.h +++ b/include/surfaceflinger/Surface.h @@ -165,38 +165,36 @@ public: // setSwapRectangle() is intended to be used by GL ES clients void setSwapRectangle(const Rect& r); + private: - // can't be copied - Surface& operator = (Surface& rhs); - Surface(const Surface& rhs); - - Surface(const sp& control); - void init(); - ~Surface(); - - friend class SurfaceComposerClient; - friend class SurfaceControl; - - + /* + * Android frameworks friends + * (eventually this should go away and be replaced by proper APIs) + */ // 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 + // MediaPlayer needs access to ISurface for display friend class MediaPlayer; friend class IOMX; // this is just to be able to write some unit tests friend class Test; - sp getClient() const; - sp getISurface() const; +private: + friend class SurfaceComposerClient; + friend class SurfaceControl; - status_t getBufferLocked(int index, int usage); - - status_t validate() const; + // can't be copied + Surface& operator = (Surface& rhs); + Surface(const Surface& rhs); - inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; } - inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; } - + Surface(const sp& control); + ~Surface(); + + + /* + * android_native_window_t hooks + */ static int setSwapInterval(android_native_window_t* window, int interval); static int dequeueBuffer(android_native_window_t* window, android_native_buffer_t** buffer); static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer); @@ -210,8 +208,6 @@ private: int query(int what, int* value); int perform(int operation, va_list args); - status_t dequeueBuffer(sp* buffer); - void dispatch_setUsage(va_list args); int dispatch_connect(va_list args); int dispatch_disconnect(va_list args); @@ -222,6 +218,20 @@ private: int disconnect(int api); int crop(Rect const* rect); + /* + * private stuff... + */ + void init(); + status_t validate() const; + sp getClient() const; + sp getISurface() const; + + inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; } + inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; } + + status_t getBufferLocked(int index, int usage); + int getBufferIndex(const sp& buffer) const; + uint32_t getUsage() const; int getConnectedApi() const; diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp index 674570477..21a40db4e 100644 --- a/libs/surfaceflinger_client/SharedBufferStack.cpp +++ b/libs/surfaceflinger_client/SharedBufferStack.cpp @@ -195,6 +195,42 @@ int32_t SharedBufferBase::computeTail() const return (mNumBuffers + stack.head - stack.available + 1) % mNumBuffers; } +status_t SharedBufferBase::waitForCondition(const ConditionBase& condition) +{ + const SharedBufferStack& stack( *mSharedStack ); + SharedClient& client( *mSharedClient ); + const nsecs_t TIMEOUT = s2ns(1); + const int identity = mIdentity; + + Mutex::Autolock _l(client.lock); + while ((condition()==false) && + (stack.identity == identity) && + (stack.status == NO_ERROR)) + { + 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." , condition.name(), stack.identity); + break; + } else { + LOGW("waitForCondition(%s) timed out " + "(identity=%d, status=%d). " + "CPU may be pegged. trying again.", condition.name(), + stack.identity, stack.status); + } + } else { + LOGE("waitForCondition(%s) error (%s) ", + condition.name(), strerror(-err)); + return err; + } + } + } + return (stack.identity != mIdentity) ? status_t(BAD_INDEX) : stack.status; +} // ============================================================================ // conditions and updates // ============================================================================ @@ -202,14 +238,14 @@ int32_t SharedBufferBase::computeTail() const SharedBufferClient::DequeueCondition::DequeueCondition( SharedBufferClient* sbc) : ConditionBase(sbc) { } -bool SharedBufferClient::DequeueCondition::operator()() { +bool SharedBufferClient::DequeueCondition::operator()() const { return stack.available > 0; } SharedBufferClient::LockCondition::LockCondition( SharedBufferClient* sbc, int buf) : ConditionBase(sbc), buf(buf) { } -bool SharedBufferClient::LockCondition::operator()() { +bool SharedBufferClient::LockCondition::operator()() const { return (buf != stack.head || (stack.queued > 0 && stack.inUse != buf)); } @@ -217,7 +253,7 @@ bool SharedBufferClient::LockCondition::operator()() { SharedBufferServer::ReallocateCondition::ReallocateCondition( SharedBufferBase* sbb, int buf) : ConditionBase(sbb), buf(buf) { } -bool SharedBufferServer::ReallocateCondition::operator()() { +bool SharedBufferServer::ReallocateCondition::operator()() const { // TODO: we should also check that buf has been dequeued return (buf != stack.head); } diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp index 057d211c5..eee4dae3d 100644 --- a/libs/surfaceflinger_client/Surface.cpp +++ b/libs/surfaceflinger_client/Surface.cpp @@ -463,18 +463,6 @@ int Surface::perform(android_native_window_t* window, // ---------------------------------------------------------------------------- -status_t Surface::dequeueBuffer(sp* buffer) { - android_native_buffer_t* out; - status_t err = dequeueBuffer(&out); - if (err == NO_ERROR) { - *buffer = GraphicBuffer::getSelf(out); - } - return err; -} - -// ---------------------------------------------------------------------------- - - int Surface::dequeueBuffer(android_native_buffer_t** buffer) { sp client(getClient()); @@ -530,7 +518,7 @@ int Surface::lockBuffer(android_native_buffer_t* buffer) if (err != NO_ERROR) return err; - int32_t bufIdx = GraphicBuffer::getSelf(buffer)->getIndex(); + int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer)); err = mSharedBufferClient->lock(bufIdx); LOGE_IF(err, "error locking buffer %d (%s)", bufIdx, strerror(-err)); return err; @@ -547,7 +535,7 @@ int Surface::queueBuffer(android_native_buffer_t* buffer) mDirtyRegion.set(mSwapRectangle); } - int32_t bufIdx = GraphicBuffer::getSelf(buffer)->getIndex(); + int32_t bufIdx = getBufferIndex(GraphicBuffer::getSelf(buffer)); mSharedBufferClient->setCrop(bufIdx, mNextBufferCrop); mSharedBufferClient->setDirtyRegion(bufIdx, mDirtyRegion); err = mSharedBufferClient->queue(bufIdx); @@ -722,13 +710,14 @@ status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) // we're intending to do software rendering from this point setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); - sp backBuffer; - status_t err = dequeueBuffer(&backBuffer); + android_native_buffer_t* out; + status_t err = dequeueBuffer(&out); LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err)); if (err == NO_ERROR) { + sp backBuffer(GraphicBuffer::getSelf(out)); err = lockBuffer(backBuffer.get()); LOGE_IF(err, "lockBuffer (idx=%d) failed (%s)", - backBuffer->getIndex(), strerror(-err)); + getBufferIndex(backBuffer), strerror(-err)); if (err == NO_ERROR) { const Rect bounds(backBuffer->width, backBuffer->height); const Region boundsRegion(bounds); @@ -797,7 +786,7 @@ status_t Surface::unlockAndPost() err = queueBuffer(mLockedBuffer.get()); LOGE_IF(err, "queueBuffer (idx=%d) failed (%s)", - mLockedBuffer->getIndex(), strerror(-err)); + getBufferIndex(mLockedBuffer), strerror(-err)); mPostedBuffer = mLockedBuffer; mLockedBuffer = 0; @@ -809,6 +798,11 @@ void Surface::setSwapRectangle(const Rect& r) { mSwapRectangle = r; } +int Surface::getBufferIndex(const sp& buffer) const +{ + return buffer->getIndex(); +} + status_t Surface::getBufferLocked(int index, int usage) { sp s(mSurface);