Loading libs/ui/GraphicBufferAllocator.cpp +108 −52 Original line number Original line Diff line number Diff line Loading @@ -90,59 +90,36 @@ void GraphicBufferAllocator::dumpToSystemLog() ALOGD("%s", s.string()); ALOGD("%s", s.string()); } } status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, class BufferLiberatorThread : public Thread { int usage, buffer_handle_t* handle, int32_t* stride) public: { ATRACE_CALL(); // make sure to not allocate a N x 0 or 0 x N buffer, since this is // allowed from an API stand-point allocate a 1x1 buffer instead. if (!w || !h) w = h = 1; // we have a h/w allocator and h/w buffer is requested status_t err; err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride); ALOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)", static void queueCaptiveBuffer(buffer_handle_t handle) { w, h, format, usage, err, strerror(-err)); size_t queueSize; { Mutex::Autolock lock(sMutex); if (sThread == NULL) { sThread = new BufferLiberatorThread; sThread->run("BufferLiberator"); } if (err == NO_ERROR) { sThread->mQueue.push_back(handle); Mutex::Autolock _l(sLock); sThread->mQueuedCondition.signal(); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); queueSize = sThread->mQueue.size(); int bpp = bytesPerPixel(format); if (bpp < 0) { // probably a HAL custom format. in any case, we don't know // what its pixel size is. bpp = 0; } } alloc_rec_t rec; rec.w = w; rec.h = h; rec.s = *stride; rec.format = format; rec.usage = usage; rec.size = h * stride[0] * bpp; list.add(*handle, rec); } } return err; static void waitForLiberation() { } Mutex::Autolock lock(sMutex); class BufferLiberatorThread : public Thread { waitForLiberationLocked(); public: } static void queueCaptiveBuffer(buffer_handle_t handle) { static void maybeWaitForLiberation() { static sp<BufferLiberatorThread> thread(new BufferLiberatorThread); Mutex::Autolock lock(sMutex); static bool running = false; if (sThread != NULL) { if (!running) { if (sThread->mQueue.size() > 8) { thread->run("BufferLiberator"); waitForLiberationLocked(); running = true; } } { Mutex::Autolock lock(thread->mMutex); thread->mQueue.push_back(handle); thread->mCondition.signal(); } } } } Loading @@ -152,13 +129,12 @@ private: virtual bool threadLoop() { virtual bool threadLoop() { buffer_handle_t handle; buffer_handle_t handle; { { // Scope for mutex Mutex::Autolock lock(mMutex); Mutex::Autolock lock(sMutex); while (mQueue.isEmpty()) { while (mQueue.isEmpty()) { mCondition.wait(mMutex); mQueuedCondition.wait(sMutex); } } handle = mQueue[0]; handle = mQueue[0]; mQueue.removeAt(0); } } status_t err; status_t err; Loading @@ -176,14 +152,94 @@ private: list.removeItem(handle); list.removeItem(handle); } } { // Scope for mutex Mutex::Autolock lock(sMutex); mQueue.removeAt(0); mFreedCondition.broadcast(); } return true; return true; } } static void waitForLiberationLocked() { if (sThread == NULL) { return; } const nsecs_t timeout = 500 * 1000 * 1000; nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); nsecs_t timeToStop = now + timeout; while (!sThread->mQueue.isEmpty() && now < timeToStop) { sThread->mFreedCondition.waitRelative(sMutex, timeToStop - now); now = systemTime(SYSTEM_TIME_MONOTONIC); } if (!sThread->mQueue.isEmpty()) { ALOGW("waitForLiberationLocked timed out"); } } static Mutex sMutex; static sp<BufferLiberatorThread> sThread; Vector<buffer_handle_t> mQueue; Vector<buffer_handle_t> mQueue; Condition mCondition; Condition mQueuedCondition; Mutex mMutex; Condition mFreedCondition; }; }; Mutex BufferLiberatorThread::sMutex; sp<BufferLiberatorThread> BufferLiberatorThread::sThread; status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, int usage, buffer_handle_t* handle, int32_t* stride) { ATRACE_CALL(); // make sure to not allocate a N x 0 or 0 x N buffer, since this is // allowed from an API stand-point allocate a 1x1 buffer instead. if (!w || !h) w = h = 1; // we have a h/w allocator and h/w buffer is requested status_t err; // If too many async frees are queued up then wait for some of them to // complete before attempting to allocate more memory. This is exercised // by the android.opengl.cts.GLSurfaceViewTest CTS test. BufferLiberatorThread::maybeWaitForLiberation(); err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride); if (err != NO_ERROR) { ALOGW("WOW! gralloc alloc failed, waiting for pending frees!"); BufferLiberatorThread::waitForLiberation(); err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride); } ALOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)", w, h, format, usage, err, strerror(-err)); if (err == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); int bpp = bytesPerPixel(format); if (bpp < 0) { // probably a HAL custom format. in any case, we don't know // what its pixel size is. bpp = 0; } alloc_rec_t rec; rec.w = w; rec.h = h; rec.s = *stride; rec.format = format; rec.usage = usage; rec.size = h * stride[0] * bpp; list.add(*handle, rec); } return err; } status_t GraphicBufferAllocator::free(buffer_handle_t handle) status_t GraphicBufferAllocator::free(buffer_handle_t handle) { { BufferLiberatorThread::queueCaptiveBuffer(handle); BufferLiberatorThread::queueCaptiveBuffer(handle); Loading Loading
libs/ui/GraphicBufferAllocator.cpp +108 −52 Original line number Original line Diff line number Diff line Loading @@ -90,59 +90,36 @@ void GraphicBufferAllocator::dumpToSystemLog() ALOGD("%s", s.string()); ALOGD("%s", s.string()); } } status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, class BufferLiberatorThread : public Thread { int usage, buffer_handle_t* handle, int32_t* stride) public: { ATRACE_CALL(); // make sure to not allocate a N x 0 or 0 x N buffer, since this is // allowed from an API stand-point allocate a 1x1 buffer instead. if (!w || !h) w = h = 1; // we have a h/w allocator and h/w buffer is requested status_t err; err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride); ALOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)", static void queueCaptiveBuffer(buffer_handle_t handle) { w, h, format, usage, err, strerror(-err)); size_t queueSize; { Mutex::Autolock lock(sMutex); if (sThread == NULL) { sThread = new BufferLiberatorThread; sThread->run("BufferLiberator"); } if (err == NO_ERROR) { sThread->mQueue.push_back(handle); Mutex::Autolock _l(sLock); sThread->mQueuedCondition.signal(); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); queueSize = sThread->mQueue.size(); int bpp = bytesPerPixel(format); if (bpp < 0) { // probably a HAL custom format. in any case, we don't know // what its pixel size is. bpp = 0; } } alloc_rec_t rec; rec.w = w; rec.h = h; rec.s = *stride; rec.format = format; rec.usage = usage; rec.size = h * stride[0] * bpp; list.add(*handle, rec); } } return err; static void waitForLiberation() { } Mutex::Autolock lock(sMutex); class BufferLiberatorThread : public Thread { waitForLiberationLocked(); public: } static void queueCaptiveBuffer(buffer_handle_t handle) { static void maybeWaitForLiberation() { static sp<BufferLiberatorThread> thread(new BufferLiberatorThread); Mutex::Autolock lock(sMutex); static bool running = false; if (sThread != NULL) { if (!running) { if (sThread->mQueue.size() > 8) { thread->run("BufferLiberator"); waitForLiberationLocked(); running = true; } } { Mutex::Autolock lock(thread->mMutex); thread->mQueue.push_back(handle); thread->mCondition.signal(); } } } } Loading @@ -152,13 +129,12 @@ private: virtual bool threadLoop() { virtual bool threadLoop() { buffer_handle_t handle; buffer_handle_t handle; { { // Scope for mutex Mutex::Autolock lock(mMutex); Mutex::Autolock lock(sMutex); while (mQueue.isEmpty()) { while (mQueue.isEmpty()) { mCondition.wait(mMutex); mQueuedCondition.wait(sMutex); } } handle = mQueue[0]; handle = mQueue[0]; mQueue.removeAt(0); } } status_t err; status_t err; Loading @@ -176,14 +152,94 @@ private: list.removeItem(handle); list.removeItem(handle); } } { // Scope for mutex Mutex::Autolock lock(sMutex); mQueue.removeAt(0); mFreedCondition.broadcast(); } return true; return true; } } static void waitForLiberationLocked() { if (sThread == NULL) { return; } const nsecs_t timeout = 500 * 1000 * 1000; nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); nsecs_t timeToStop = now + timeout; while (!sThread->mQueue.isEmpty() && now < timeToStop) { sThread->mFreedCondition.waitRelative(sMutex, timeToStop - now); now = systemTime(SYSTEM_TIME_MONOTONIC); } if (!sThread->mQueue.isEmpty()) { ALOGW("waitForLiberationLocked timed out"); } } static Mutex sMutex; static sp<BufferLiberatorThread> sThread; Vector<buffer_handle_t> mQueue; Vector<buffer_handle_t> mQueue; Condition mCondition; Condition mQueuedCondition; Mutex mMutex; Condition mFreedCondition; }; }; Mutex BufferLiberatorThread::sMutex; sp<BufferLiberatorThread> BufferLiberatorThread::sThread; status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format, int usage, buffer_handle_t* handle, int32_t* stride) { ATRACE_CALL(); // make sure to not allocate a N x 0 or 0 x N buffer, since this is // allowed from an API stand-point allocate a 1x1 buffer instead. if (!w || !h) w = h = 1; // we have a h/w allocator and h/w buffer is requested status_t err; // If too many async frees are queued up then wait for some of them to // complete before attempting to allocate more memory. This is exercised // by the android.opengl.cts.GLSurfaceViewTest CTS test. BufferLiberatorThread::maybeWaitForLiberation(); err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride); if (err != NO_ERROR) { ALOGW("WOW! gralloc alloc failed, waiting for pending frees!"); BufferLiberatorThread::waitForLiberation(); err = mAllocDev->alloc(mAllocDev, w, h, format, usage, handle, stride); } ALOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)", w, h, format, usage, err, strerror(-err)); if (err == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); int bpp = bytesPerPixel(format); if (bpp < 0) { // probably a HAL custom format. in any case, we don't know // what its pixel size is. bpp = 0; } alloc_rec_t rec; rec.w = w; rec.h = h; rec.s = *stride; rec.format = format; rec.usage = usage; rec.size = h * stride[0] * bpp; list.add(*handle, rec); } return err; } status_t GraphicBufferAllocator::free(buffer_handle_t handle) status_t GraphicBufferAllocator::free(buffer_handle_t handle) { { BufferLiberatorThread::queueCaptiveBuffer(handle); BufferLiberatorThread::queueCaptiveBuffer(handle); Loading