diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:05:43 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:05:43 -0800 |
commit | e09fd9e819c23dc90bca68375645e15544861330 (patch) | |
tree | 9a9fdadd1301625f875a3c126c986c79e3363ac4 /libs/surfaceflinger/GPUHardware/GPUHardware.cpp | |
parent | 7c1b96a165f970a09ed239bb4fb3f1b0d8f2a407 (diff) | |
download | frameworks_native-e09fd9e819c23dc90bca68375645e15544861330.zip frameworks_native-e09fd9e819c23dc90bca68375645e15544861330.tar.gz frameworks_native-e09fd9e819c23dc90bca68375645e15544861330.tar.bz2 |
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'libs/surfaceflinger/GPUHardware/GPUHardware.cpp')
-rw-r--r-- | libs/surfaceflinger/GPUHardware/GPUHardware.cpp | 608 |
1 files changed, 316 insertions, 292 deletions
diff --git a/libs/surfaceflinger/GPUHardware/GPUHardware.cpp b/libs/surfaceflinger/GPUHardware/GPUHardware.cpp index b24a0f2..eb75f99 100644 --- a/libs/surfaceflinger/GPUHardware/GPUHardware.cpp +++ b/libs/surfaceflinger/GPUHardware/GPUHardware.cpp @@ -30,6 +30,7 @@ #include <cutils/log.h> #include <cutils/properties.h> +#include <utils/IBinder.h> #include <utils/MemoryDealer.h> #include <utils/MemoryBase.h> #include <utils/MemoryHeapPmem.h> @@ -48,36 +49,113 @@ #include "GPUHardware/GPUHardware.h" + /* - * This file manages the GPU if there is one. The intent is that this code - * needs to be different for every devce. Currently there is no abstraction, - * but in the long term, this code needs to be refactored so that API and - * implementation are separated. + * Manage the GPU. This implementation is very specific to the G1. + * There are no abstraction here. + * + * All this code will soon go-away and be replaced by a new architecture + * for managing graphics accelerators. * - * In this particular implementation, the GPU, its memory and register are - * managed here. Clients (such as OpenGL ES) request the GPU when then need - * it and are given a revokable heap containing the registers on memory. + * In the meantime, it is conceptually possible to instantiate a + * GPUHardwareInterface for another GPU (see GPUFactory at the bottom + * of this file); practically... doubtful. * */ namespace android { + // --------------------------------------------------------------------------- +class GPUClientHeap; +class GPUAreaHeap; + +class GPUHardware : public GPUHardwareInterface, public IBinder::DeathRecipient +{ +public: + static const int GPU_RESERVED_SIZE; + static const int GPUR_SIZE; + + GPUHardware(); + virtual ~GPUHardware(); + + virtual void revoke(int pid); + virtual sp<MemoryDealer> request(int pid); + virtual status_t request(int pid, + const sp<IGPUCallback>& callback, + ISurfaceComposer::gpu_info_t* gpu); + + virtual status_t friendlyRevoke(); + virtual void unconditionalRevoke(); + + virtual pid_t getOwner() const { return mOwner; } + + // used for debugging only... + virtual sp<SimpleBestFitAllocator> getAllocator() const; + +private: + + + enum { + NO_OWNER = -1, + }; + + struct GPUArea { + sp<GPUAreaHeap> heap; + sp<MemoryHeapPmem> clientHeap; + sp<IMemory> map(); + }; + + struct Client { + pid_t pid; + GPUArea smi; + GPUArea ebi; + GPUArea reg; + void createClientHeaps(); + void revokeAllHeaps(); + }; + + Client& getClientLocked(pid_t pid); + status_t requestLocked(int pid); + void releaseLocked(); + void takeBackGPULocked(); + void registerCallbackLocked(const sp<IGPUCallback>& callback, + Client& client); + + virtual void binderDied(const wp<IBinder>& who); + + mutable Mutex mLock; + sp<GPUAreaHeap> mSMIHeap; + sp<GPUAreaHeap> mEBIHeap; + sp<GPUAreaHeap> mREGHeap; + + KeyedVector<pid_t, Client> mClients; + DefaultKeyedVector< wp<IBinder>, pid_t > mRegisteredClients; + + pid_t mOwner; + + sp<MemoryDealer> mCurrentAllocator; + sp<IGPUCallback> mCallback; + + sp<SimpleBestFitAllocator> mAllocator; + + Condition mCondition; +}; + // size reserved for GPU surfaces // 1200 KB fits exactly: // - two 320*480 16-bits double-buffered surfaces // - one 320*480 32-bits double-buffered surface -// - one 320*240 16-bits double-bufferd, 4x anti-aliased surface -static const int GPU_RESERVED_SIZE = 1200 * 1024; - -static const int GPUR_SIZE = 1 * 1024 * 1024; +// - one 320*240 16-bits double-buffered, 4x anti-aliased surface +const int GPUHardware::GPU_RESERVED_SIZE = 1200 * 1024; +const int GPUHardware::GPUR_SIZE = 1 * 1024 * 1024; // --------------------------------------------------------------------------- /* * GPUHandle is a special IMemory given to the client. It represents their * handle to the GPU. Once they give it up, they loose GPU access, or if - * they explicitely revoke their acces through the binder code 1000. + * they explicitly revoke their access through the binder code 1000. * In both cases, this triggers a callback to revoke() * first, and then actually powers down the chip. * @@ -92,42 +170,99 @@ static const int GPUR_SIZE = 1 * 1024 * 1024; * */ -class GPUHandle : public BnMemory +class GPUClientHeap : public MemoryHeapPmem { public: - GPUHandle(const sp<GPUHardware>& gpu, const sp<IMemoryHeap>& heap) - : mGPU(gpu), mClientHeap(heap) { - } - virtual ~GPUHandle(); - virtual sp<IMemoryHeap> getMemory(ssize_t* offset, size_t* size) const; - virtual status_t onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); - void setOwner(int owner) { mOwner = owner; } + GPUClientHeap(const wp<GPUHardware>& gpu, + const sp<MemoryHeapBase>& heap) + : MemoryHeapPmem(heap), mGPU(gpu) { } +protected: + wp<GPUHardware> mGPU; +}; + +class GPUAreaHeap : public MemoryHeapBase +{ +public: + GPUAreaHeap(const wp<GPUHardware>& gpu, + const char* const vram, size_t size=0, size_t reserved=0) + : MemoryHeapBase(vram, size), mGPU(gpu) { + if (base() != MAP_FAILED) { + if (reserved == 0) + reserved = virtualSize(); + mAllocator = new SimpleBestFitAllocator(reserved); + } + } + virtual sp<MemoryHeapPmem> createClientHeap() { + sp<MemoryHeapBase> parentHeap(this); + return new GPUClientHeap(mGPU, parentHeap); + } + virtual const sp<SimpleBestFitAllocator>& getAllocator() const { + return mAllocator; + } private: - void revokeNotification(); + sp<SimpleBestFitAllocator> mAllocator; +protected: wp<GPUHardware> mGPU; - sp<IMemoryHeap> mClientHeap; - int mOwner; }; -GPUHandle::~GPUHandle() { +class GPURegisterHeap : public GPUAreaHeap +{ +public: + GPURegisterHeap(const sp<GPUHardware>& gpu) + : GPUAreaHeap(gpu, "/dev/hw3d", GPUHardware::GPUR_SIZE) { } + virtual sp<MemoryHeapPmem> createClientHeap() { + sp<MemoryHeapBase> parentHeap(this); + return new MemoryHeapRegs(mGPU, parentHeap); + } +private: + class MemoryHeapRegs : public GPUClientHeap { + public: + MemoryHeapRegs(const wp<GPUHardware>& gpu, + const sp<MemoryHeapBase>& heap) + : GPUClientHeap(gpu, heap) { } + sp<MemoryHeapPmem::MemoryPmem> createMemory(size_t offset, size_t size); + virtual void revoke(); + private: + class GPUHandle : public MemoryHeapPmem::MemoryPmem { + public: + GPUHandle(const sp<GPUHardware>& gpu, + const sp<MemoryHeapPmem>& heap) + : MemoryHeapPmem::MemoryPmem(heap), + mGPU(gpu), mOwner(gpu->getOwner()) { } + virtual ~GPUHandle(); + virtual sp<IMemoryHeap> getMemory( + ssize_t* offset, size_t* size) const; + virtual void revoke() { }; + virtual status_t onTransact( + uint32_t code, const Parcel& data, + Parcel* reply, uint32_t flags); + private: + void revokeNotification(); + wp<GPUHardware> mGPU; + pid_t mOwner; + }; + }; +}; + +GPURegisterHeap::MemoryHeapRegs::GPUHandle::~GPUHandle() { //LOGD("GPUHandle %p released, revoking GPU", this); revokeNotification(); } - -void GPUHandle::revokeNotification() { +void GPURegisterHeap::MemoryHeapRegs::GPUHandle::revokeNotification() { sp<GPUHardware> hw(mGPU.promote()); if (hw != 0) { hw->revoke(mOwner); } } -sp<IMemoryHeap> GPUHandle::getMemory(ssize_t* offset, size_t* size) const +sp<IMemoryHeap> GPURegisterHeap::MemoryHeapRegs::GPUHandle::getMemory( + ssize_t* offset, size_t* size) const { + sp<MemoryHeapPmem> heap = getHeap(); if (offset) *offset = 0; - if (size) *size = mClientHeap !=0 ? mClientHeap->virtualSize() : 0; - return mClientHeap; + if (size) *size = heap !=0 ? heap->virtualSize() : 0; + return heap; } -status_t GPUHandle::onTransact( +status_t GPURegisterHeap::MemoryHeapRegs::GPUHandle::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { status_t err = BnMemory::onTransact(code, data, reply, flags); @@ -150,22 +285,14 @@ status_t GPUHandle::onTransact( // --------------------------------------------------------------------------- -class MemoryHeapRegs : public MemoryHeapPmem -{ -public: - MemoryHeapRegs(const wp<GPUHardware>& gpu, const sp<MemoryHeapBase>& heap); - virtual ~MemoryHeapRegs(); - sp<IMemory> mapMemory(size_t offset, size_t size); - virtual void revoke(); -private: - wp<GPUHardware> mGPU; -}; -MemoryHeapRegs::MemoryHeapRegs(const wp<GPUHardware>& gpu, const sp<MemoryHeapBase>& heap) - : MemoryHeapPmem(heap), mGPU(gpu) +sp<MemoryHeapPmem::MemoryPmem> GPURegisterHeap::MemoryHeapRegs::createMemory( + size_t offset, size_t size) { + sp<GPUHandle> memory; + sp<GPUHardware> gpu = mGPU.promote(); + if (heapID()>0 && gpu!=0) { #if HAVE_ANDROID_OS - if (heapID()>0) { /* this is where the GPU is powered on and the registers are mapped * in the client */ //LOGD("ioctl(HW3D_GRANT_GPU)"); @@ -174,27 +301,16 @@ MemoryHeapRegs::MemoryHeapRegs(const wp<GPUHardware>& gpu, const sp<MemoryHeapBa // it can happen if the master heap has been closed already // in which case the GPU already is revoked (app crash for // instance). - //LOGW("HW3D_GRANT_GPU failed (%s), mFD=%d, base=%p", - // strerror(errno), heapID(), base()); + LOGW("HW3D_GRANT_GPU failed (%s), mFD=%d, base=%p", + strerror(errno), heapID(), base()); } - } -#endif -} - -MemoryHeapRegs::~MemoryHeapRegs() -{ -} - -sp<IMemory> MemoryHeapRegs::mapMemory(size_t offset, size_t size) -{ - sp<GPUHandle> memory; - sp<GPUHardware> gpu = mGPU.promote(); - if (heapID()>0 && gpu!=0) memory = new GPUHandle(gpu, this); +#endif + } return memory; } -void MemoryHeapRegs::revoke() +void GPURegisterHeap::MemoryHeapRegs::revoke() { MemoryHeapPmem::revoke(); #if HAVE_ANDROID_OS @@ -207,25 +323,6 @@ void MemoryHeapRegs::revoke() #endif } -// --------------------------------------------------------------------------- - -class GPURegisterHeap : public PMemHeapInterface -{ -public: - GPURegisterHeap(const sp<GPUHardware>& gpu) - : PMemHeapInterface("/dev/hw3d", GPUR_SIZE), mGPU(gpu) - { - } - virtual ~GPURegisterHeap() { - } - virtual sp<MemoryHeapPmem> createClientHeap() { - sp<MemoryHeapBase> parentHeap(this); - return new MemoryHeapRegs(mGPU, parentHeap); - } -private: - wp<GPUHardware> mGPU; -}; - /*****************************************************************************/ GPUHardware::GPUHardware() @@ -237,85 +334,87 @@ GPUHardware::~GPUHardware() { } -sp<MemoryDealer> GPUHardware::request(int pid) +status_t GPUHardware::requestLocked(int pid) { - sp<MemoryDealer> dealer; - - LOGD("pid %d requesting gpu surface (current owner = %d)", pid, mOwner); - const int self_pid = getpid(); if (pid == self_pid) { // can't use GPU from surfaceflinger's process - return dealer; + return PERMISSION_DENIED; } - Mutex::Autolock _l(mLock); - if (mOwner != pid) { - // someone already has the gpu. - takeBackGPULocked(); - - // releaseLocked() should be a no-op most of the time - releaseLocked(); - - requestLocked(); + if (mREGHeap != 0) { + if (mOwner != NO_OWNER) { + // someone already has the gpu. + takeBackGPULocked(); + releaseLocked(); + } + } else { + // first time, initialize the stuff. + if (mSMIHeap == 0) + mSMIHeap = new GPUAreaHeap(this, "/dev/pmem_gpu0"); + if (mEBIHeap == 0) + mEBIHeap = new GPUAreaHeap(this, + "/dev/pmem_gpu1", 0, GPU_RESERVED_SIZE); + mREGHeap = new GPURegisterHeap(this); + mAllocator = mEBIHeap->getAllocator(); + if (mAllocator == NULL) { + // something went terribly wrong. + mSMIHeap.clear(); + mEBIHeap.clear(); + mREGHeap.clear(); + return INVALID_OPERATION; + } + } + Client& client = getClientLocked(pid); + mCurrentAllocator = new MemoryDealer(client.ebi.clientHeap, mAllocator); + mOwner = pid; } + return NO_ERROR; +} - dealer = mAllocator; - mOwner = pid; - if (dealer == 0) { - mOwner = SURFACE_FAILED; +sp<MemoryDealer> GPUHardware::request(int pid) +{ + sp<MemoryDealer> dealer; + Mutex::Autolock _l(mLock); + Client* client; + LOGD("pid %d requesting gpu surface (current owner = %d)", pid, mOwner); + if (requestLocked(pid) == NO_ERROR) { + dealer = mCurrentAllocator; + LOGD_IF(dealer!=0, "gpu surface granted to pid %d", mOwner); } - - LOGD_IF(dealer!=0, "gpu surface granted to pid %d", mOwner); return dealer; } -status_t GPUHardware::request(const sp<IGPUCallback>& callback, +status_t GPUHardware::request(int pid, const sp<IGPUCallback>& callback, ISurfaceComposer::gpu_info_t* gpu) { - sp<IMemory> gpuHandle; - IPCThreadState* ipc = IPCThreadState::self(); - const int pid = ipc->getCallingPid(); - const int self_pid = getpid(); + if (callback == 0) + return BAD_VALUE; + sp<IMemory> gpuHandle; LOGD("pid %d requesting gpu core (owner = %d)", pid, mOwner); - - if (pid == self_pid) { - // can't use GPU from surfaceflinger's process - return PERMISSION_DENIED; - } - Mutex::Autolock _l(mLock); - if (mOwner != pid) { - // someone already has the gpu. - takeBackGPULocked(); - - // releaseLocked() should be a no-op most of the time - releaseLocked(); - - requestLocked(); - } - - if (mHeapR.isValid()) { + status_t err = requestLocked(pid); + if (err == NO_ERROR) { + // it's guaranteed to be there, be construction + Client& client = mClients.editValueFor(pid); + registerCallbackLocked(callback, client); gpu->count = 2; - gpu->regions[0].region = mHeap0.map(true); - gpu->regions[0].reserved = mHeap0.reserved; - gpu->regions[1].region = mHeap1.map(true); - gpu->regions[1].reserved = mHeap1.reserved; - gpu->regs = mHeapR.map(); + gpu->regions[0].region = client.smi.map(); + gpu->regions[1].region = client.ebi.map(); + gpu->regs = client.reg.map(); + gpu->regions[0].reserved = 0; + gpu->regions[1].reserved = GPU_RESERVED_SIZE; if (gpu->regs != 0) { - static_cast< GPUHandle* >(gpu->regs.get())->setOwner(pid); + //LOGD("gpu core granted to pid %d, handle base=%p", + // mOwner, gpu->regs->pointer()); } mCallback = callback; - mOwner = pid; - //LOGD("gpu core granted to pid %d, handle base=%p", - // mOwner, gpu->regs->pointer()); } else { LOGW("couldn't grant gpu core to pid %d", pid); } - - return NO_ERROR; + return err; } void GPUHardware::revoke(int pid) @@ -330,16 +429,16 @@ void GPUHardware::revoke(int pid) // mOwner could be <0 if the same process acquired the GPU // several times without releasing it first. mCondition.signal(); - releaseLocked(true); + releaseLocked(); } } status_t GPUHardware::friendlyRevoke() { Mutex::Autolock _l(mLock); - takeBackGPULocked(); //LOGD("friendlyRevoke owner=%d", mOwner); - releaseLocked(true); + takeBackGPULocked(); + releaseLocked(); return NO_ERROR; } @@ -353,90 +452,37 @@ void GPUHardware::takeBackGPULocked() } } -void GPUHardware::requestLocked() +void GPUHardware::releaseLocked() { - if (mAllocator == 0) { - GPUPart* part = 0; - sp<PMemHeap> surfaceHeap; - if (mHeap1.promote() == false) { - //LOGD("requestLocked: (1) creating new heap"); - mHeap1.set(new PMemHeap("/dev/pmem_gpu1", 0, GPU_RESERVED_SIZE)); - } - if (mHeap1.isValid()) { - //LOGD("requestLocked: (1) heap is valid"); - // NOTE: if GPU1 is available we use it for our surfaces - // this could be device specific, so we should do something more - // generic - surfaceHeap = static_cast< PMemHeap* >( mHeap1.getHeap().get() ); - part = &mHeap1; - if (mHeap0.promote() == false) { - //LOGD("requestLocked: (0) creating new heap"); - mHeap0.set(new PMemHeap("/dev/pmem_gpu0")); - } - } else { - //LOGD("requestLocked: (1) heap is not valid"); - // No GPU1, use GPU0 only - if (mHeap0.promote() == false) { - //LOGD("requestLocked: (0) creating new heap"); - mHeap0.set(new PMemHeap("/dev/pmem_gpu0", 0, GPU_RESERVED_SIZE)); - } - if (mHeap0.isValid()) { - //LOGD("requestLocked: (0) heap is valid"); - surfaceHeap = static_cast< PMemHeap* >( mHeap0.getHeap().get() ); - part = &mHeap0; - } - } - - if (mHeap0.isValid() || mHeap1.isValid()) { - if (mHeapR.promote() == false) { - //LOGD("requestLocked: (R) creating new register heap"); - mHeapR.set(new GPURegisterHeap(this)); - } - } else { - // we got nothing... - mHeap0.clear(); - mHeap1.clear(); - } - - if (mHeapR.isValid() == false) { - //LOGD("requestLocked: (R) register heap not valid!!!"); - // damn, couldn't get the gpu registers! - mHeap0.clear(); - mHeap1.clear(); - surfaceHeap.clear(); - part = NULL; - } - - if (surfaceHeap != 0 && part && part->getClientHeap()!=0) { - part->reserved = GPU_RESERVED_SIZE; - part->surface = true; - mAllocatorDebug = static_cast<SimpleBestFitAllocator*>( - surfaceHeap->getAllocator().get()); - mAllocator = new MemoryDealer( - part->getClientHeap(), - surfaceHeap->getAllocator()); + //LOGD("revoking gpu from pid %d", mOwner); + if (mOwner != NO_OWNER) { + // this may fail because the client might have died, and have + // been removed from the list. + ssize_t index = mClients.indexOfKey(mOwner); + if (index >= 0) { + Client& client(mClients.editValueAt(index)); + client.revokeAllHeaps(); } + mOwner = NO_OWNER; + mCurrentAllocator.clear(); + mCallback.clear(); } } -void GPUHardware::releaseLocked(bool dispose) +GPUHardware::Client& GPUHardware::getClientLocked(pid_t pid) { - /* - * if dispose is set, we will force the destruction of the heap, - * so it is given back to other systems, such as camera. - * Otherwise, we'll keep a weak pointer to it, this way we might be able - * to reuse it later if it's still around. - */ - //LOGD("revoking gpu from pid %d", mOwner); - mOwner = NO_OWNER; - mAllocator.clear(); - mCallback.clear(); - - /* if we're asked for a full revoke, dispose only of the heap - * we're not using for surface (as we might need it while drawing) */ - mHeap0.release(mHeap0.surface ? false : dispose); - mHeap1.release(mHeap1.surface ? false : dispose); - mHeapR.release(false); + ssize_t index = mClients.indexOfKey(pid); + if (index < 0) { + Client client; + client.pid = pid; + client.smi.heap = mSMIHeap; + client.ebi.heap = mEBIHeap; + client.reg.heap = mREGHeap; + index = mClients.add(pid, client); + } + Client& client(mClients.editValueAt(index)); + client.createClientHeaps(); + return client; } // ---------------------------------------------------------------------------- @@ -444,8 +490,7 @@ void GPUHardware::releaseLocked(bool dispose) sp<SimpleBestFitAllocator> GPUHardware::getAllocator() const { Mutex::Autolock _l(mLock); - sp<SimpleBestFitAllocator> allocator = mAllocatorDebug.promote(); - return allocator; + return mAllocator; } void GPUHardware::unconditionalRevoke() @@ -456,100 +501,79 @@ void GPUHardware::unconditionalRevoke() // --------------------------------------------------------------------------- - -GPUHardware::GPUPart::GPUPart() - : surface(false), reserved(0) -{ -} - -GPUHardware::GPUPart::~GPUPart() { -} - -const sp<PMemHeapInterface>& GPUHardware::GPUPart::getHeap() const { - return mHeap; -} - -const sp<MemoryHeapPmem>& GPUHardware::GPUPart::getClientHeap() const { - return mClientHeap; -} - -bool GPUHardware::GPUPart::isValid() const { - return ((mHeap!=0) && (mHeap->base() != MAP_FAILED)); +sp<IMemory> GPUHardware::GPUArea::map() { + sp<IMemory> memory; + if (clientHeap != 0 && heap != 0) { + memory = clientHeap->mapMemory(0, heap->virtualSize()); + } + return memory; } -void GPUHardware::GPUPart::clear() +void GPUHardware::Client::createClientHeaps() { - mHeap.clear(); - mHeapWeak.clear(); - mClientHeap.clear(); - surface = false; + if (smi.clientHeap == 0) + smi.clientHeap = smi.heap->createClientHeap(); + if (ebi.clientHeap == 0) + ebi.clientHeap = ebi.heap->createClientHeap(); + if (reg.clientHeap == 0) + reg.clientHeap = reg.heap->createClientHeap(); } -void GPUHardware::GPUPart::set(const sp<PMemHeapInterface>& heap) +void GPUHardware::Client::revokeAllHeaps() { - mHeapWeak.clear(); - if (heap!=0 && heap->base() == MAP_FAILED) { - mHeap.clear(); - mClientHeap.clear(); - } else { - mHeap = heap; - mClientHeap = mHeap->createClientHeap(); - } + if (smi.clientHeap != 0) + smi.clientHeap->revoke(); + if (ebi.clientHeap != 0) + ebi.clientHeap->revoke(); + if (reg.clientHeap != 0) + reg.clientHeap->revoke(); } -bool GPUHardware::GPUPart::promote() +void GPUHardware::registerCallbackLocked(const sp<IGPUCallback>& callback, + Client& client) { - //LOGD("mHeapWeak=%p, mHeap=%p", mHeapWeak.unsafe_get(), mHeap.get()); - if (mHeap == 0) { - mHeap = mHeapWeak.promote(); + sp<IBinder> binder = callback->asBinder(); + if (mRegisteredClients.add(binder, client.pid) >= 0) { + binder->linkToDeath(this); } - if (mHeap != 0) { - if (mClientHeap != 0) { - mClientHeap->revoke(); - } - mClientHeap = mHeap->createClientHeap(); - } else { - surface = false; - } - return mHeap != 0; } -sp<IMemory> GPUHardware::GPUPart::map(bool clear) +void GPUHardware::binderDied(const wp<IBinder>& who) { - sp<IMemory> memory; - if (mClientHeap != NULL) { - memory = mClientHeap->mapMemory(0, mHeap->virtualSize()); - if (clear && memory!=0) { - //StopWatch sw("memset"); - memset(memory->pointer(), 0, memory->size()); + Mutex::Autolock _l(mLock); + pid_t pid = mRegisteredClients.valueFor(who); + if (pid != 0) { + ssize_t index = mClients.indexOfKey(pid); + if (index >= 0) { + //LOGD("*** removing client at %d", index); + Client& client(mClients.editValueAt(index)); + client.revokeAllHeaps(); // not really needed in theory + mClients.removeItemsAt(index); + if (mClients.size() == 0) { + //LOGD("*** was last client closing everything"); + mCallback.clear(); + mAllocator.clear(); + mCurrentAllocator.clear(); + mSMIHeap.clear(); + mREGHeap.clear(); + + // NOTE: we cannot clear the EBI heap because surfaceflinger + // itself may be using it, since this is where surfaces + // are allocated. if we're in the middle of compositing + // a surface (even if its process just died), we cannot + // rip the heap under our feet. + + mOwner = NO_OWNER; + } } } - return memory; } -void GPUHardware::GPUPart::release(bool dispose) +// --------------------------------------------------------------------------- + +sp<GPUHardwareInterface> GPUFactory::getGPU() { - if (mClientHeap != 0) { - mClientHeap->revoke(); - mClientHeap.clear(); - } - if (dispose) { - if (mHeapWeak!=0 && mHeap==0) { - mHeap = mHeapWeak.promote(); - } - if (mHeap != 0) { - mHeap->dispose(); - mHeapWeak.clear(); - mHeap.clear(); - } else { - surface = false; - } - } else { - if (mHeap != 0) { - mHeapWeak = mHeap; - mHeap.clear(); - } - } + return new GPUHardware(); } // --------------------------------------------------------------------------- |