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